Bram Moolenaar

2000年11月

如果你花很大量时间处理纯文本,写程序或者HTML,选则并高效使用一个好编辑器可以节省你很多时间。 这边文章会为快速工作和减少犯错给出一些引导和提示。 我将使用开源编辑器Vim(Vi IMproved)来展示关于高效编辑的一些观点,当然其他编辑器也同样适用。 高效编辑的第一步就是选择一个正确的编辑器。篇幅有限,关于哪个编辑器最好的话题就不做讨论了。 如果你不知道该用什么编辑器,或者觉得你现在正在用的编辑器很龊,试试Vim吧,你不会失望的。

Vim的命令和选项会以这种字体command展现:

第一部分:编辑一个文件

1.快速移动

(编辑工作)大部分时间其实是花在阅读,检查错误和决定正确的编辑位置上的,而不是插入新文本或改什么东西。 在文本内移动是十分常用的,所以你应该学会怎么快速在文本内移动。

一个十分常用的功能是搜索一段文字,或者查看一个词在哪些行被用到了。 一个简单的方法是用/pattern命令来搜索,但是有一些更智能的方法:

  • 如果你看一个单词,你想搜索这个单词其他的出现位置,可以使用*命令。这个命令会提取光标下的单词,然后去搜索。 (译注:是单词(word),英文文本比较好使,夹杂在中文文本里面的英文单词也能正常提取, 对中文会提取光标下的一整句话,基本这个功能就废了。其他语言不清楚,估计字母形式的语言都好使)

  • 如果你设置了incsearch选项,Vim在你还在输入的时候就会显示第一个匹配到的位置。 这可以让你很容易发现模式字符串里面的错误。

  • 如果你设置了hlsearch选项,Vim会将匹配到的文本以黄色背景高亮显示。这能让你很快知道那些文本被搜索到了。 在编程的时候,这个功能能展示变量在哪里被使用到了。你甚至都不用移动光标就可以看到。

在一些结构化文本里面,快速移动就更方便了。Vim对C程序有一些特定的命令(对C系列的C++和Java也适用):

  • %命令可以在一对匹配的括号间跳转。或者一对对应的“#if”和“#endif”。 事实上,%命令可以在很多匹配项间跳转。这个功能在检查()和{}等是否匹配方面很有用。 (译注:在普通文本里面用%也可以在匹配的(和)间跳转的,但是貌似全角的(和)不能匹配-_-||)

  • [{命令跳转回当前代码块的{处。

  • gd命令跳转到变量的局部定义处。 (译注:当然这个功能不是很强大,不要指望它在所有情况下都能正常工作,比如说,头文件里面定义的)

当然还有很多。重点是你得知道这些命令。你可能要反驳我:“怎么可能把这些命令全学会,起码好几百个命令呢! 有些简单,有些智能。这不得学好几个星期啊!”好吧,其实你没必要学那么多的。相反,你只需要知道自己独特的编辑方式, 然后只学那些能帮助你提高编辑效率的命令。

三个基础步骤

  1. 当你编辑的时候,留意一下你经常重复的,或者相对耗时的那些动作。

  2. 找找有没有命令能让这些动作更快完成。阅读文档,问朋友或者看其他人是怎么做的。

  3. 训练自己使用这些命令。直到你想都不想就可以敲出来的地步。

来个例子看看效果:

  1. 你发现编C程序的时候,你经常花时间找函数定义的位置。你现在使用*命令查看函数名出现的位置, 但是绝大部分匹配到的位置是该函数被使用到的位置而不是定义的位置。你觉得肯定有更快的方法。

  2. 通过阅读快速参考手册,你发现里面有提到跳转到tags。手册展示了怎么通过这个功能实现跳转到函数定义的方法, 这正是你要找的。

  3. 通过多次试验Vim一起的ctags程序产生tags文件,你学会了使用ctrl-]命令, 并且发现这个命令能省下很多时间。为了更加方便,你在Makefile里面加了几行自动生成tags文件。

使用这三步的一些注意事项:

  • “我需要把工作做完,又没有时间去看文档学新命令”。如果你这么想,你会一直停留在计算机的石器时代。有一些人干什么都用Notepad, 然后纳闷为什么别人能用一半的时间就把活干完了……

  • 不要太过分。如果你无论做什么都去试着找一个最好的命令,你就没时间去想你现在做的工作了。挑一些本不必要耗时的命令, 训练自己直到不用思考就能使用它们。然后你就能更多地留意你在编辑的文本。

接下来的章节对一些大部分人都要使用到的动作提了一些建议。它们能在你使用上面三个基础步骤的时候给你一些启示。

2.不要重复输入

我们输入的单词是一个有限的集合,甚至只是有限的一些短语和句子,特别是在计算机编程方面。 很显然,你不希望重复输入一些东西。

一个经常要做的事是把一个单词替换成另外一个。如果这个要做全篇替换,你可以使用:s(substitute)命令。 如果只需要做部分替换,一个快速的做法是使用*命令查找下一个出现位置,然后使用cw命令替换。 然后用n命令跳到下一个出现位置,使用.命令重复cw命令。

.命令重复最近的更改。一次更改指对当前文档的插入,删除或者替换行为。重复这个可是个相当牛逼的机制。 如果你好好组织你的编辑顺序,很多更改就只需要敲个.就行了。不过这之间要注意别做其他的更改,因为这会替换.代替的行为。 另外,你可能想用m命令标记当前位置,继续重复更改动作,然后跳转回来。

有些函数和变量名字输入起来很恶心,在不看着函数名的情况下你能正确无误地输入“XpmCreatePixmpFromData”吗? Vim有一个补全机制来简化这类操作。它会查看你正在编辑的文件和#include里面的包含的文件。你输入“XpmCr”后,敲击 CTRL-N,Vim会帮你把它补全为“XpmCreatePixmpFromData”。这个功能不仅能节约很多输入的时间,而且还能避免犯错和 在编译器编译报错是回来修复错误。(译注:自动补全有很多可以设置的,还有很多插件可以提供更牛的补全功能)

当你需要重复输入一个短语或句子很多次时,有一个更快的方法。Vim提供一个录制宏的机制。通过输入qa来开始录制 并注册到‘a’,然后你只管照平时一样输入命令,最后在此敲击q来停止录制。当你想重复录制的命令时,你只需要输入 @a。有26个寄存器来寄存录制的宏(译注:应该就是a-z了,译者木有试过这么高级的功能的说-_-)。

有了录制功能,你能做很多重复的动作,而不只是插入文本。当需要重复某些东西时,你可以考虑一下这个。

录制的时候只有一个需要注意的地方,那就是这些命令会原封不动地照你输入的顺序再运行一遍。当前后移动的时候, 你就需要考虑一下宏执行的时候移动过的文本可能与你输入的时候不一样。你录制时可能向左移动4个字符就够了, 但宏执行时可能需要移动5个字符。通常需要使用那些能跳过文本块(单词或句子)的命令或者移动到特定的字符。

当你需要执行的命令变得越来越复杂,一次成功输入就变得越来越难。这个时候你就需要直接编写一个脚本或者宏,而不是去录制一个。 这个在做代码模板的时候很有用,比如说,一个函数头。你想让它多智能,它就有多智能。

3.有错就改

输入时犯错是很正常的,没人能避免。这个技巧是快速定位并更正错误。只要你告诉编辑器什么事错误的,什么是正确的, 它应该能够帮你做这个事。

通常你会重复犯同一个错误,你手指就是没有正确输入你想要的。(Vim里面)错误可以用缩写(abbreviation)来自动更正。看几个例子:

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

这些单词在你输错时就会被自动更正了。

这个机制还能用来快速输入一个很长的东西。特别是那些个很难输入的单词,这可以避免输错。例如:

:abbr pn penguin
:abbr MS Mandrake Software

然而,当你不需要的时候,它也会帮你扩展,这就让插入“MS”变得很难,所以最好使用一些没有意义的短词语。

为了寻找文档中的错误,Vim提供了高亮机制。这个本来是用来为程序做语法高亮的,但是它也可以用来捕获错误并高亮显示。

语法高亮会用彩色来显示注释。这个听起来不是什么重要的功能,但是一旦开始使用,你就会发现它真的很有帮助。 你能迅速定位那些本应该是注释,却没有高亮的部分(可能你忘了注释符号了),或者一行代码被高亮显示为注释了(忘了插入“*/”了)。 这些错误在黑白显示的文本里很难被发现,在调试代码时可能会浪费大量时间。

语法高亮也能发现未匹配的括号。没匹配的“)”会高亮显示为亮红色背景。你能用%来看他们是怎么匹配的,并且在正确的位置插入“(”或“)”。

另外一些常见的错误也能快速定位,例如:使用了“#included ”而不是“#include”。 在黑白显示的文本里,这些错误很容易被忽略,但“include”会被高亮而“included”不会就很容易定位这类错误了。

一个更加复杂的例子:对于英文文本来说,有一个很长的列表记录所有被使用到的单词,任何不在单子里的词都可能是错误。 通过一个语法高亮文件,你可以把所有不在列表里面的词高亮。你还可以通过一些额外的宏来为列表添加单词,这样他们就不会被标识为错误了。 这和你需要的文档处理软件里的某些功能很类似。在Vim里,这些都是用一些脚本来完成的,你可以根据自己的工作需要做一些调整:例如, 仅仅检查程序注释里面的拼写错误。

第二部分

4.不常使用的文件单独处理

人们不可能只处理一个文件。大部分情况你需要接二连三处理很多相关的文件,甚至需要同时处理好几个文件。你应该充分利用你的编辑器 来提高同时处理多个文件的效率。

前面提到的tag机制在文档间跳转也适用。通常的方法是为你的项目生成一个tags文件,这样你就可以在项目里所有文件间跳转查找函数, 结构体和数据类型等的定义处。相比手工查找,这个方法节约的时间是相当可观的。我看程序做的第一件事就是生成tags文件。

另外一个牛逼的机制可以查找某个字眼在一堆文件里所有出现的位置,那就是:grep命令。 Vim会列一个所有匹配结果的列表,并跳转到第一个结果。:cn命令能跳转到下一个匹配结果上。 这个功能在你想更改函数的调用的参数个数时很有用。

包含的文件里有很多有用的信息。但是查找包含你想要的定义的那个文件会花费很多时间。Vim知道包含了那些文件,并且可以在这些文件里 搜索你查找的单词。最常见的应用就是查找函数原型,把光标定位在你文件里的函数名上,输入[I:,Vim就会显示一个列表, 里面是所有包含的文件里面能与函数名匹配的结果。如果你想看更多内容,你可以直接跳转到定义上。一个相似的命令能够用来检查你是否 包含了正确的头文件。

在Vim里,你可以把文本区域切分成几部分来编辑不同的文件。这样你就可以比较两个或多个文件的内容,并且在他们之间复制粘贴。 有很多命令可以开启关闭窗口、在窗口间跳转,临时隐藏文件等。你要再一次使用那三个基本步骤来选择你需要学习的命令。

多窗口功能有很多其他作用。预览标签机制是个很好的例子,这个机制会打开一个预览窗口,光标仍在你编辑的文件里。预览窗口里展示的 文本可以是很多东西,比如光标下函数的定义。如果你把光标移到其他名字上面并且停留一会儿,预览窗口里就会出现那个名字的定义。 这个文本也可能是包含文件里面定义的结构体或者函数。

5.和其他程序一起工作

编辑器就是为编辑文本而生,就像email程序是收发邮件的,操作系统是运行程序的一样。每一个程序有他自己的任务,并且这应该是他的擅长。 威力来自于让程序结合起来工作。

一个简单的例子:选择列表里一些文本并排序::!sort。外部的“sort”命令就是用来过滤文本的。很简单,不是么? 排序功能其实可以被包含在编辑器中,但是看一下“man sort”,它有很多参数。可能实现的算法非常精妙。你想把他们全部包含到编辑器中么? 还有很多其他的过滤命令?那编辑器就变得太臃肿了。

Unix的精神一直是让不同的程序做好自己的事,然后让他们一起去做一个更大的工作。不幸的是,大部分的编辑器在与其他程序一起运作方面 很欠缺,例如你不可以替换Netscape里的email编辑器,你只能用那个很龊的。另一种趋势是把所有功能囊括到一个编辑器里,这方面Emacs 做到了机制。(有些人说Emacs是一个可以用来编辑文本的操作系统。)

Vim也试图与其他程序进行整合,但仍然在努力。现在MS-Developer Studio和Sniff里面已经可以使用Vim做编辑器了,一些支持外部编辑器 的email程序也可以使用Vim,比如说Mutt。和Sun Workshop的整合正在进行中。大体说,这是不久的将来Vim需要改进的地方。 只有这样我们才能得到一个比各部分简单集合更好的系统。

6.结构化的文本

也许你经常处理某些结构化的文本,但又和现有命令支持的不同。那么你就需要回到编辑器的“构建块”,创建你自己的宏和脚本来处理相应文本。 这里谈到的就是更复杂的功能了。

一件简单的事情就是要缩短“编辑-编译-修复”的周期过程。Vim有:make命令可以开始编译,捕获产生的问题,并让你跳转到错误位置 去修复。如果你用了不同的编译器,错误信息将不会被识别。不同于老的“写下来”系统,你可以更改“errorformat”选项, 告诉Vim你的error信息长什么样,并且怎么从中提取文件名和行号。对于复杂的gcc错误信息,他都能处理,因此,你应该可以让他对付几乎所有的 编译器。

有时,调整到一个特定类型的文件只需要改一些参数或者写一些宏命令。例如,跳转到手册页面,你可以写一个能获取光标下单词的宏,清理当前 缓存,读取那个单词的手册页并写入当前缓存。这是一个简单有效的查看交叉引用的方法。

使用前面的三个基本步骤,你可以高效处理各种结构化文件。只需要考虑你需要对文件做的事,寻找合适的编译器命令,然后开始使用。 听起来确实很简单,只需要去做就可以了。

第三部分

7.形成习惯

学开车需要花精力,但那是让你(放弃学车而)继续骑车的理由么?不是,你意识到你需要花些时间来学习新技能。文本编辑没什么不同, 你需要学习新命令,让后把他们变成习惯。

另一方面,你不应该尝试学习编译器提供的所有命令。那完全是浪费时间,大部分人只需要为他们的工作学习10%~20%的命令。 但对每个人来说,这些命令集合又不同。这需要你时常回头想想那些能自动完成的重复性的工作。如果某些工作只需要做一次,以后不会再做, 那么久别想着去优化。但你可能意识到最近一个小时重复了某件事很多次。那么就去手册里找一个更快的命令吧,或者写个宏。如果是一个很大 的任务,比如列出某种特殊类型的文本,你可以在讨论组或者上网搜搜看是否已经有人解决这种问题了。

最后一点是最重要的。你可以想象一个重复的任务,找到一个好的解决方法,但过了一个周末就忘了。这可不行,你需要重复这个方法直到 你的手指能自动完成。只有这样才会达到你想要的效率,不要想着一口气吃成胖子,一次只学几个命令效果最好,一些你很少用到的技巧 你可以写下来一遍以后查看。如果你一直把这个目标放在心上,你会编辑得越来越高效。

最后一点要提醒的,人们经常会忽略的问题:我经常看到有人在显示器前坐老半天,看着屏幕,用两个手指向下翻屏,然后向上翻屏等, 还疑惑为什么这么累……用是个手指啊,亲!不仅仅是更快,还不容易疲劳。就算一天只用一个小时电脑,也就只需要几个星期来学会指法。

结语

标题的灵感来自Stephen R. Covey的一本很成功的书《高效人群的7个习惯》(“The 7 habits of highly effective people”)。 我建议每个想要解决个人和专业问题的人(谁不需要呢?)都看看。你们也可能说这是来自Scott Adams的《重度缺陷的人的七年》(“Seven years of highly defective people”)(这个也推荐!)。查看 http://iccf-holland.org/click1.html,点击“recommend books and CDs”. (译注:这都多少年了,链接还在,推荐的书和CD那个已经不在了)

关于作者

Bram Moolenaar是Vim的主要作者。他编写了Vim的核心功能代码,并且决定别人提交的代码哪些可以被包含到Vim里面。 他毕业于台夫特科技大学(the Delft Technical University),是个计算机技术牛人。现在他主要从事软件方面的工作, 但也知道怎么用烙铁。他是国际儿童保健基金荷兰支部(ICCF Holland,International Child Care Fund)的创办人和财务总管。 该支部主要工作是帮助乌干达的孤儿。他是一个从事自由职业的系统架构师,但其实他大部分时间都花在Vim上。 他的邮箱是:Bram AT Moolenaar.net。