criew 0.0.3

Terminal-first Linux kernel patch mail workflow TUI
# Code Preview Vim 内联编辑原型设计

## 文档导航

1. 背景与目标
2. 原型范围(P0)
3. 交互原型
4. 技术方案(原型建议)
5. 代码变更点(草案)
6. 测试原型(建议)
7. 后续迭代(P1/P2)
8. 验收标准(P0)
9. VM2 外部 Vim 会话原型(增强)

## 1. 背景与目标

当前 `Code Browser` 页面的 `Source Preview` 是只读预览。
本原型目标是在不离开 `Code Preview` 的前提下提供 Vim 风格编辑体验,并避免和主页面全局键位冲突:

- 默认仍是浏览模式,沿用当前配置选中的主页面键位
- `ui.keymap = "default"` 时为 `j/l` 焦点切换、`i/k` 移动
- `ui.keymap = "vim"` 时为 `h/l` 焦点切换、`j/k` 移动
- 仅在用户按 `e` 后,进入 Vim-like 编辑模式
- 编辑完成后可保存并回到浏览模式,预览立即显示最新内容

## 2. 原型范围(P0)

本阶段只做最小可用的内联 Vim-like 模式:

- 支持在 `UiPage::CodeBrowser` + `CodePaneFocus::Source` + 选中文件时,按 `e` 进入编辑
- 提供 `NORMAL` / `INSERT` / `COMMAND` 三种模式
- 支持基础移动、插入、删除、保存、退出
- 支持最小 `:` 命令:`:w``:q``:wq`
- 不改变默认模式下当前配置所选择的全局键位语义

不在 P0 范围内:

- 完整 Vim/Ex 命令集(如宏、寄存器、复杂文本对象、复杂命令组合)
- Neovim 嵌入协议、插件体系、LSP
- 多文件 buffer / split 窗口

## 3. 交互原型

### 3.1 模式状态

- `Browse`(默认)
  - CRIEW 接管按键
  - 现有行为不变
- `VimNormal`(按 `e` 进入)
  - 按键由编辑状态机接管
  - 可移动光标、删除字符、进入插入、保存退出
- `VimInsert`
  - 可输入文本
  - `Esc` 返回 `VimNormal`
- `VimCommand`
  - 底部显示 `:` 命令输入行
  - `Enter` 执行命令后返回 `VimNormal`

### 3.2 进入条件

按 `e` 仅在以下条件满足时生效:

1. 当前页面是 `CodeBrowser`
2. 当前焦点是 `Source`
3. 当前选中项是文件(不是目录)

否则仅提示状态信息,例如:

- `select a source file in Source pane, then press e`

### 3.3 P0 键位草案

`Browse` 模式:

- 保持当前键位,不变

`VimNormal` 模式:

- `h/j/k/l`: 光标左/下/上/右
- `i`: 进入 `VimInsert`
- `x`: 删除当前字符
- `s`: 保存到文件
- `:`: 进入 `VimCommand`
- `Esc`: 退出编辑并回到 `Browse`(未保存时给出提示)

`VimInsert` 模式:

- 可打印字符:插入
- `Enter`: 换行
- `Backspace`: 删除前一字符
- `Esc`: 返回 `VimNormal`

`VimCommand` 模式:

- 可打印字符:追加到命令行(前缀 `:` 仅展示,不重复输入)
- `Backspace`: 删除命令字符
- `Enter`: 执行命令(MVP 仅支持 `w``q``wq`- `Esc`: 取消命令并返回 `VimNormal`

说明:

- 编辑模式激活后,`j/l/i/k` 不再触发全局动作,避免冲突。
- `:q` 在有未保存改动时不退出,状态栏提示先 `:w` 或使用 `:wq`
## 4. 技术方案(原型建议)

### 4.1 核心数据结构

建议在 `AppState` 增加内联编辑状态:

- `code_edit_mode: Browse | VimNormal | VimInsert | VimCommand`
- `code_edit_target: Option<PathBuf>`
- `code_edit_buffer: Vec<String>`(按行存储)
- `code_edit_cursor_row: usize`
- `code_edit_cursor_col: usize`
- `code_edit_dirty: bool`
- `code_edit_command_input: String``COMMAND` 模式命令缓存)

### 4.2 运行流程

1. `Browse` 中按 `e`,校验当前选中是文件
2. 读取文件到 `code_edit_buffer`,进入 `VimNormal`
3. 按当前模式路由按键事件并更新 buffer/cursor
4.`VimNormal` 下按 `:` 进入 `VimCommand`
5. 执行 `:w` / `:q` / `:wq`,并更新 dirty 与模式状态
6. 用户按 `s``:w` 时写回文件并清除 dirty
7. 用户退出编辑模式后恢复 `Browse`
8. 退出后右侧预览基于最新文件内容重新渲染

### 4.3 异常与恢复

- 读取失败:不进入编辑,状态栏显示错误
- 保存失败:保持编辑模式,状态栏显示错误
- 命令不支持:保持 `VimNormal`,提示 `unsupported command`
- `:q` 遇到未保存改动:拒绝退出并提示 `unsaved changes`
- 文件在外部变化:P0 不做自动合并,仅提示可能已过期

## 5. 代码变更点(草案)

建议最小变更点:`src/ui/tui.rs`

- `AppState` 新增内联编辑状态字段
- `handle_key_event` 新增编辑模式分流:
  - 编辑模式开启时,优先走 `handle_code_edit_key_event`
  - 非编辑模式下保留现有分支
- `draw_code_source_preview` 根据模式渲染:
  - 浏览态渲染只读文本
  - 编辑态渲染 buffer + 光标/模式指示
- 新增函数(或方法):
  - `enter_code_edit_mode()`
  - `save_code_edit_buffer()`
  - `exit_code_edit_mode()`
  - `handle_code_edit_key_event()`
  - `handle_code_command(input: &str)`

## 6. 测试原型(建议)

### 6.1 行为测试

1. 不在 `CodeBrowser` 页面按 `e`:不进入编辑模式
2. 选中目录按 `e`:不进入编辑模式,给出提示
3. 选中文件按 `e`:进入 `VimNormal`
4. `i` 进入 `VimInsert`,输入后 `Esc` 回到 `VimNormal`
5. `s` 保存后文件内容更新,预览同步更新
6. `:w` 保存成功,`:q` 退出,`:wq` 保存并退出
7. `:q` 在 dirty 状态下拒绝退出并提示
8. `Esc` 退出编辑后恢复 `Browse` 键位行为

### 6.2 回归测试

- 未进入编辑模式时,主页面当前配置键位、`Tab`、命令栏、搜索、patch 操作行为不变
- Code Browser 的 tree 展开/收起行为不变

## 7. 后续迭代(P1/P2)

- P1: 增加 `a/o/dd/u` 等常见 Vim 动作
- P1: 增加 `:q!``:w!` 等最小扩展命令
- P2: 评估 Neovim 内嵌(msgpack-rpc)可行性,决定是否升级为“真 Vim”

## 8. 验收标准(P0)

满足以下条件即验收通过:

1. 默认状态下,CRIEW 现有键位无冲突
2. 用户按 `e` 才进入 `Code Preview` 内联编辑模式
3. 编辑态支持最小 Vim-like 体验(`NORMAL/INSERT/COMMAND`、保存、退出)
4. 命令模式支持 `:w``:q``:wq` 且行为符合预期
5. 退出编辑后能回到浏览态并看到最新内容
6. 异常路径(无文件、读写失败、非法命令)有明确状态提示

## 9. VM2 外部 Vim 会话原型(增强)

VM2 目标:在 VM1 内联编辑之外,支持从 `Code Preview` 切出到外部 Vim 进行完整编辑。

### 9.1 入口与触发

- 建议入口:`E`(与 VM1 的 `e` 区分)
- 可选入口:命令模式支持 `:vim`
- 触发条件:
  1. 当前页面 `CodeBrowser`
  2. 当前焦点 `Source`
  3. 当前选中项是文件

### 9.2 与 VM1 协同规则

- 若内联编辑 buffer 为 dirty:
  - 默认拒绝切出外部 Vim
  - 状态栏提示:`unsaved changes, run :w before external vim`
- 若无 dirty:
  - 允许直接切出外部 Vim
  - 外部 Vim 退出后,强制从磁盘重载并刷新预览

### 9.3 时序草图

1. 用户触发 `E`(或 `:vim`2. 校验文件与 dirty 状态
3. 执行 `disable_raw_mode()`
4. 执行 `LeaveAlternateScreen`
5. 前台启动外部编辑器(`VISUAL -> EDITOR -> vim`6. 编辑器退出后执行 `EnterAlternateScreen`
7. 执行 `enable_raw_mode()`
8. 重新读取文件并刷新 `Code Preview`
9. 状态栏提示执行结果(成功/失败/退出码)

### 9.4 错误处理草图

- 启动失败:回到 TUI,提示 `failed to launch external editor`
- 编辑器异常退出:回到 TUI,提示 exit code/signal
- 恢复失败:记录错误并尽力恢复可操作终端

### 9.5 VM2 验收补充

1. 有效文件场景触发 `E` 可打开外部 Vim
2. 退出后返回 CRIEW,预览显示最新内容
3. dirty 场景触发 `E` 会被阻止并提示先保存
4. 失败路径不会导致 TUI 卡死或终端不可用