编程与开发 · 第 9 期 · 第二季开篇

自己写个文本编辑器,Vim 模式怎么实现

modal editing · 把按键变成状态机

Vim 难学不是因为古老,是因为它把按键变成了状态机。同一个 x 在 normal 是删字符、在 visual 是删选区、在 insert 是输入字母 x。模式 = 状态,按键 = 状态转移函数。理解这条,Vim 就不是玄学,是工程。
⏱ 约 10 分钟 🎯 用 Vim 但不懂它为什么这么设计的人 📦 源:build-your-own-x §5

01一个反共识:Vim 不是"快捷键多",是"状态多"

很多人放弃 Vim 是因为"快捷键太多记不住"。但 VS Code 的快捷键更多,没人因此放弃。Vim 真正的反常识是:同一个键,含义随模式变。

按键 x + 模式 → 动作

这是教科书级的有限状态机(FSM):当前状态 + 输入 → 下一状态 + 输出动作。普通编辑器是"一键一动作"的查表,Vim 是"一键一转移函数"的状态机。代价是要记当前在哪个模式,收益是按键空间被复用了 N 倍——26 个字母键在 4 个模式下等于 104 个动作,还不用按 Ctrl。

所以"Vim 难学"的真正原因是:你的肌肉记忆要从"按键→动作"升级成"按键→状态→动作"。一旦升级完成,效率是普通编辑器的几倍——因为手指不离开主键区。

Vim 不是快捷键多,
是状态多。
灏天文库 · 编程与开发 P.27

02模式切换演示:切 normal/insert/visual 看按键含义

点上面的模式按钮切换模式,再点下面的按键,看同一个键在不同模式下做了什么。光标(蓝色块)会移动,选区(蓝色淡底)会出现。

⌨️ Vim 模式状态机演示
简化版:normal/insert/visual 三态,h/j/k/l/x/i/a-v/Esc 等键。看状态怎么转移。
当前模式:NORMAL 光标位置:0 选区:无
操作日志: 点按键开始
提示:normal 下按 i 进 insert;insert 下按 Esc 回 normal;normal 下按 v 进 visual。

03从零实现一个模式编辑器:核心 30 行

剥掉所有花哨功能,一个模式编辑器的核心就是一个状态循环:

// 伪代码
state = "normal"; buf = ""; cur = 0
while true:
  key = read_key()
  action = transition(state, key) // 状态转移函数
  buf, cur, state = action(buf, cur) // 执行并可能切状态
  render(buf, cur)

关键设计:transition 是一张 (state, key) → action 的二维表,不是 if-else 堆。这样加新模式只需加一行表项,不用改主循环。这就是为什么 Vim 能扩展出几十种模式(operator-pending、command-line、select…)而不崩——它的内核是数据驱动的,不是代码堆出来的。

从零写一遍这个 30 行内核,你会突然理解 Vim 那些"奇怪"设计:为什么 d 后面要跟一个 motion(因为 d 是 operator,它等下一个输入决定删什么——这本身又是一个临时模式);为什么 Esc 回 normal 是"回到安全屋"(normal 是唯一一个不会误改文本的模式)。

模式编辑器的内核
是一张表,不是一堆 if。
灏天文库 · 编程与开发 P.28

04为什么"模式"是编辑器的未来,不是过去

有人觉得模式编辑是 1976 年的过时设计。但看看 2020 年后的新编辑器:Helix、Kakoune 全是模式编辑;VS Code 的 Vim 插件有上百万安装量;甚至 Emacs 的 evil-mode 把 Vim 模式搬进了 Emacs。模式编辑不是怀旧,是回潮。

原因有两个:一是键盘没变,主键区还是最高效的输入区,模式让 26 键复用 N 倍;二是 AI 时代,编辑器要处理"选区→指令"的语义操作(选中一段代码→"重构它"),模式天然把"选择"和"操作"分开,比鼠标拖拽更适合命令化。Vim 的 vi((选中括号内)+ c(改)这种组合,本质就是"语义选区 + 动作",和 AI 指令是同一个范式。

所以学 Vim 不是学一个老工具,是学一种把输入空间折叠进状态空间的设计思想——这种思想在 AI 编辑器时代只会更值钱。

05带走这套清单

✅ 模式编辑器 6 条可执行规则

  1. Vim 难学的真因是"按键→状态→动作"的三段式,不是快捷键多。
  2. 核心是 (state, key) → action 的二维转移表,加模式只加表项。
  3. normal 是安全屋:所有破坏性操作都在其他模式,Esc 回 normal = 急停。
  4. operator + motion(如 dw)是"临时子模式",理解它就理解 Vim 组合键。
  5. 从零写 30 行内核比背 200 个快捷键更能让你"懂" Vim。
  6. 模式编辑在 AI 时代回潮:语义选区 + 动作 = 自然语言指令的雏形。
造过模式编辑器,
Vim 就不反人类了。
灏天文库 · 编程与开发 P.29