Vim 是一个流行的文本编辑器,原作者是 Bram Moolenaar (1961 ~ 2023-08-03)。

2000 年 11 月,Bram Moolenaar 有一篇文章:高效文本编辑的七个习惯,专门讲述文本编辑的技巧和策略。2007 年 2 月,他在谷歌演讲,题目是 高效文本编辑的七个习惯 2.0,B 站有录制的现场视频。

提升文本编辑效率分三个基本步骤:

  1. Detect inefficiency 发现低效操作
  2. Find a quicker way 找到更快的方法
  3. Make it a habit 形成习惯

编辑一个文件

1. 快速移动

程序员的大部分时间是在阅读代码、查找错误、寻找最佳修改位置,相比之下,真正插入新代码的时间不多。

在 Vim 中,/pattern 随时启动一次查找。n 在匹配字符间跳转。

如果你想查找光标下的单词,执行 * 命令。

如果开启了 incsearch 选项,Vim 会先匹配命中的第一个位置,随着输入不断变化。这种快速反馈让你很轻松就能发现错误。

如果开启了 hlsearch 选项,Vim 会使用黄色背景高亮显示命中的位置。

在结构化文本中,Vim 提供了更多跳转选项。比如,在 C 语言中,% 可以在配对括号间跳转,或者在 #if 和匹配的 #endif 间跳转。其实,% 可以在很多不同的匹配符号间来回跳转。

使用 [{ 可以跳转到当前代码块的开始括号 { 位置处。

使用 gd 命令,可以跳转到变量的局部声明的位置。

类似的移动命令还有很多,全部掌握需要投入时间。关键是时刻关注你的编辑操作,如果发现需要提高效率,就去学习,并内化为自己的习惯。

比如,编辑 C 语言代码时,经常需要查找函数的定义。一开始,你可能使用 * 查找,但是这会造成大量的无效跳转。

通过查找手册,你发现可以使用标签跳转功能。 然后你尝试使用 Vim 自带的 ctags 程序,生成标签文件,学着使用 Ctrl-] 跳转指令,就能感受到效率极大提升。

在 Makefile 中增加一些指令,自动化生成标签文件,可以让效率进一步提升。

2. 避免重复输入

如果想在一个文件内,把一个文本替换为另一个,可以使用 :s 替换指令。

如果需要替换的位置较少,可以使用 * 定位,使用 cw 替换。然后使用 n 继续查找下一个,使用 . 重复指令继续上一次的编辑操作。

. 会重复上一次的修改操作。如果修改操作组织得当,可以用 . 代替大量的重复操作。

如果在重复操作中,需要进行其他的操作,可以使用 m 标记一下位置,等完成所有重复操作再回来特殊处理。

有些函数名字很长,难以记忆和输入,比如 XpmCreatePixmapFromData。Vim 提供了自动补全功能,你输入前几个字母,比如 XpmCr,然后输入按键 CTRL-N,Vim 会从当前文件中查询字符串,并自动扩展为完整的字符串。

如果你需要反复输入一些段落,Vim 的宏(macro)更方便。执行 qa,开始录制宏,接下来的操作序列将存储到寄存器 “a” 中。再次按下 q 会结束宏的录制。当你想重复宏的操作,执行 @a 即可。这样的寄存器有 26 个。

3. 修复错误

人非圣贤,谁能无错。编辑器应该可以帮你修正错误,前提是要提前告知它何为对,何为错。

通常,同样的错误会一犯再犯。使用简写功能可以帮忙修正这类输入错误:

:abbr Lunix Linux
:abbr accross across
:abbr hte the

当你输入错误时,它们就会被即时修正。 同样的机制也可以用来输入超长单词。

:abbr pn penguin
:abbr MS Mandrake Software

编辑多个文件

4. 文件通常有多个关联

人们通常不会只编辑一个文件,而是同时编辑多个文件。

前面提过的标签机制,也可以在多个文件之间跳转。常规做法是为一个项目创建标签文件,然后就能在多个文件间跳转。

另一个强大的机制是在多个文件中搜索关键字,使用 :grep 命令。Vim 会把匹配项组成一个列表,并跳转到第一个匹配项。使用 :cn 跳转到下一个匹配项。

Vim 可以拆分窗口,在不同区域编辑不同文件,方便对比、复制等操作。

多窗口还有很多功能,比如预览标签(preview-tag)机制,它会打开一个特殊的预览窗口,光标位置依然在原始文件中。预览窗口中可以包含光标下函数的函数定义等上下文内容。

5. 协同工作

编辑器用来编辑文本,邮件客户端用于收发消息,操作系统是运行程序的,每个程序都有自己的任务,它们协同作战,能力加倍。

比如,你在编写总结,要求不能超过 500 字。你可使用 vip 选中当前段落,并写入到 wc 程序:vip:w !wc -w,其中的外部命令 wc -w 用来统计单词数量。

再比如,如果想执行当前编辑的 Python 文件,可以执行 :!python3 %,其中的特殊变量 % 表示当前文件名。

Unix 的精神是每个程序做好自己的份内事,然后通过组合完成更大的任务。

6. 文本是有结构的

通常我们处理的文本都有一些结构,但是这些结构可能和现有的命令要求的不一样。此时,你需要利用编辑器提供的“基础块”,搭建自己的宏或脚本,处理自己的文本结构。

比如,Vim 自带的 :make 命令,可以编译 C 语言,捕获可能发生的报错,我们可以跳转到错误所在的代码位置。如果你使用不同的编译器,错误信息可能不同,你可以调整 errorformat 选项,告诉 Vim 你的错误信息长什么样子,如何提取文件名、行号等关键信息。通过这种方法,你应该可以处理所有的编译器错误。

适配一种新的语言,通常就是设置一些参数,增加一些宏,仅此而已。

打磨工具

7. 内化为习惯

学习开车需要大量练习,学习任何技能都需要投入时间,文本编辑也不例外。我们需要学习新的命令,不断练习,内化为习惯。

但是,你并不需要学习编辑器提供的所有功能,这是一种浪费时间的行为。大部分人只需掌握 10% 到 20% 的命令,就能很好的完成工作。只不过每个人掌握的命令并不相同。