Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

25 - vim 模块源码分析

路径: src/vim/ 文件数: 5 个 总行数: 1513 行 功能: Vim 模式 — 终端输入框的 Vim 键绑定支持


文件详解

1. types.ts — Vim 状态类型(199 行)

// VimState 是联合类型,只有 INSERT 和 NORMAL 两种模式(大写)
// 不存在 Visual 和 Command 模式
type VimState =
  | { mode: 'INSERT'; insertedText: string }
  | { mode: 'NORMAL'; command: CommandState }

// NORMAL 模式下的命令状态机(11 种状态)
type CommandState =
  | { type: 'idle' }
  | { type: 'count'; digits: string }
  | { type: 'operator'; op: Operator; count: number }
  | { type: 'operatorCount'; op: Operator; count: number; digits: string }
  | { type: 'operatorFind'; op: Operator; count: number; find: FindType }
  | { type: 'operatorTextObj'; op: Operator; count: number; scope: TextObjScope }
  | { type: 'find'; find: FindType; count: number }
  | { type: 'g'; count: number }
  | { type: 'operatorG'; op: Operator; count: number }
  | { type: 'replace'; count: number }
  | { type: 'indent'; dir: '>' | '<'; count: number }

// 持久状态(跨命令保持)
type PersistentState = {
  lastChange: RecordedChange | null  // dot-repeat 记录
  lastFind: { type: FindType; char: string } | null
  register: string                    // 寄存器内容
  registerIsLinewise: boolean
}

function createInitialVimState(): VimState {
  return { mode: 'INSERT', insertedText: '' }
}

2. motions.ts — 光标移动(82 行)

动作说明
h左移字符级
l右移字符级
w下一个词首词级
b上一个词首词级
e当前词尾词级
0行首行级
$行尾行级
^首个非空字符行级
gg文档开头文档级
G文档末尾文档级

3. operators.ts — 操作符(556 行)

操作说明
d删除dw 删除一个词
c修改cw 修改一个词(进入 INSERT)
y复制yw 复制一个词
p粘贴粘贴寄存器内容
x删除字符删除光标下字符

4. textObjects.ts — 文本对象(186 行)

对象说明
iw内部词不含周围空格
aw一个词含周围空格
i"引号内双引号内容
a"含引号含双引号本身
i(括号内圆括号内容
a(含括号含圆括号本身

5. transitions.ts — 状态转换(490 行)

这是一个完整的状态机实现,处理 NORMAL 模式下 11 种 CommandState 之间的转换。

INSERT 模式
  └── Escape → NORMAL (idle)

NORMAL 模式 (CommandState 状态机)
  idle
    ├── i/a/o/A/I/O/s/S/C → INSERT
    ├── 数字 → count
    ├── d/c/y → operator
    ├── f/F/t/T → find
    ├── g → g
    ├── r → replace
    ├── >/<  → indent
    └── h/l/w/b/e/0/$... → 执行 motion

  count
    ├── 数字 → count (追加)
    └── 操作符/motion → 带 count 执行

  operator
    ├── 数字 → operatorCount
    ├── f/F/t/T → operatorFind
    ├── i/a → operatorTextObj
    ├── g → operatorG
    └── motion → 执行 operator+motion

注意:不存在 Visual 模式和 Command 模式。Vim 实现仅覆盖 INSERT 和 NORMAL 两种模式。


设计说明

  • Vim 模式仅作用于 PromptInput 输入框,不影响对话记录的浏览
  • 使用 discriminated union 实现类型安全的状态机
  • CommandState 的 11 种状态确保了 TypeScript 的穷举检查
  • PersistentState 支持 dot-repeat(. 重复上次操作)和寄存器
  • 初始状态为 INSERT 模式(与传统 Vim 不同,因为终端输入框默认需要输入)