高效文本编辑的七个习惯

(很久以前翻译的这篇文章,转成 org-mode 贴出来给大家分享。原文在 http://www.moolenaar.net/habits.html

如果你花很多时间输入文本、写程序或网页,通过使用一个好的编辑器并且高效 的使用它,你可以节约很多时间。本文将帮助你掌握更快更好的完成你的工作的 技能。

我会用开源文本编辑器Vim(Vi IMproved,Vi加强版)来展示关于快速编辑的概 念,但是这些概念对其他编辑器也是同样适用的。事实上选一个对的文本编辑器 是高效编辑的第一步。讨论哪个编辑器最适合你会占去太多的篇幅,所以我们 这里不讨论它。如果你不知道用哪个编辑器好或者对你现在用的编辑器不满意的 话,试一试Vim吧;你不会失望的。

[Vim命令和选项会以 粗体 显示]

1 编辑一个文件

1.1 好习惯一:快速移动

大多数的时间是花在阅读、检查错误以及寻找正确的地方开始工作,而不是插入 新的文本或修改它,在文本中移动是经常要做的事情,因此你应该学会如何快速 地移动。

非常经常性地,你会想要搜索你知道肯定存在的一段文字。或者查看包含某一单 词或词组的所有行。你可以简单地使用 /pattern 来找到那段文字,但是 我们有更好的办法:

  • 如果你看到一个特定的单词,你想搜索该单词出现的其他位置,你可以 使用 * 命令。该命令会使用当前光标下的单词去搜索下一个。
  • 如果你设上‘ incserach ’这个选项,Vim会在你输入匹配模式的 同时,显示该模式第一个匹配的地方。这能帮你快速发现你输入的搜索 模式中的错误。
  • 如果你设上‘ hlsearch ’这个选项,Vim会把你的模式匹配上的 地方都用黄色的背景色高亮显示出来。这使你能对搜索命令会让你跳到哪儿 一目了然。在程序代码里用这个功能可以帮助你发现一个变量在哪里被使用 了。你甚至不需要移动你的光标就可以发现哪里有你要找的东西。

在结构化的文本中你能更方便的快速移动。针对C语言(以及类似的如C++和 Java),Vim有特定的命令:

  • 使用 % 从一个开括弧跳转到与它对应的闭括弧。或者从一个 “#if”跳转到对应的“#endif”。事实上, % 可以跳转到很多不同的 互相匹配的东西上。这对检查()和{}是否正确的嵌套非常有用。
  • 使用 [{ 来跳回到当前代码区块的“{”处
  • 使用 gd 来从一个本地变量被使用的地方跳转到它被声明的地 方。

当然了,还有很多这样的命令。我们的重点不是说你必须知道这些命令。你可能 会抗议说你不可能学会所有这么多的命令—总共得有几百条不同的移动的命令, 有些很简单,有些很费脑子—不花上几个礼拜的时间训练想把它们全记住是不可 能的。可是,你用不着也不应该那么做;相反,你应该意识到属于你一个人的编 辑方式是怎样的,进而只学习那些会使你的编辑工作更高效的命令。

这里有 三个基本步骤

  1. 当你在编辑时,特别注意一下那些你经常重复以及/或者要花很多时间的 操作。
  2. 寻找是否有一条编辑器命令能帮你更快执行这个操作。读文档、问朋友、 或者就是去“偷看”一下别人是怎么做的。
  3. 对这条命令进行训练。不停地练习直到你的手指能不通过脑子就把它输入 进去。

让我们通过一个例子来说明这是怎么工作的:

  1. 你发现当你编辑C语言程序文件时,你经常花时间寻找某个函数是在哪儿定 义的。目前你是用 * 命令去搜索这个函数名还出现在别的什么地方, 但是结果你却找到很多这个函数被调用而不是被定义的地方。于是你就想,肯 定应该有一个更快的方法来做这件事。
  2. 通过浏览Vim的快速参考手册你发现一条关于标签之前跳转的评论。文档里 说通过这个可以跳转到函数定义的地方,恰好是你需要的!
  3. 通过使用Vim自带的ctags程序,你做了一个生成标签文件的小试验。你学 会了怎么使用 CTRL-] 命令,并发现使用这个新命令你能比以前节约很 多时间。为了使这个过程更容易,你往你的Makefile文件里加了几行,以 便以后自动的生成这个标签文件。

你在使用这三个步骤的时候必须注意几件事情:

  • “我希望快点把工作干完,我没有时间去查阅文档去学习新命令”。如果 你这样想的话,你会被陷在计算机的石器时代。有些人用Notepad编辑任何东 西,一边却在奇怪为什么别人能用一半的时间干完同样的工作呢…
  • 别做过头了。如果你总是想去找到那条最完美的命令来做你的任何小编 辑工作,你的脑子会没时间去思考你真正应该去做的工作。你应该挑出那些 花不必要长时间的操作,针对这些命令进行训练直到你的潜意识里接受了 它,以后想都不用想就能把它们在键盘上敲出来。接下来你就应该把精力放 在你要写的东西上。

接下来的小节中会讲到大多数人都需要面对的一些操作,你可以从这些操作中获 得启发,以后在你自己的工作中作用这三个步骤。

1.2 好习惯二:别输入两次

我们会输入的单词是一个有限的集合。甚至短语和句子也是有限的。尤其是对计 算机程序来说。显然,你不希望把同一件事输入两次。

你经常会需要把一个单词换成另一个。如果是在整个文件中要作这个操作,你可 以使用 :s (substitute,替换)命令。如果只有几个地方需要替换,一 个快速的方法是使用 * 命令找到该单词下一个出现的地方,使用 cw 来替换这个单词。接着打 n 找到下一个地方,打 . (dot,点)来重复上一条 cw 替换命令。

. 这个命令会重复上一个改动。这里所说的一个改动,意思就是插入、 删除或替换文本。能够重复这个是一种很强的机制。如果你围绕这个来组织你的 编辑工作的话,很多工作变成只要打一个 . 键就好了。注意在两次使用 重复命令之间的编辑操作,因为这有可能改掉你想重复的操作。在这种情况下你 可以打个 m 来记录来这个位置,重复你的改动,最后再回到你记下的那 个书签位置做你想做的编辑。

一些函数或变量名可能很不好输入。比如“XpmCreatePixmapFromData”,你能快速 的不查声明不犯错的输入它吗?Vim有一个补齐机制能让这种操作变得容易很多。 它会在你当前编辑的文件以及你 #include 的头文件里检索单词。你可以只输入 “XpmCr”,然后按 CTRL-N ,Vim会帮你把它展开成 “XpmCreatePixmapFromData”。这不仅省下很多键盘输入,还可以避免打错字而不 得不在编译器输出出错信息的时候再回头来修改。

当你在多次打一个短语或者句子的时候,我们有甚至更快的办法。Vim有一个录制 宏的机制。你打 qa 来往‘a’寄存器中录制一个宏。然后就像平时一样开 始输入你的命令,最后打 q 命令来停止宏记录。当你想重复你记录下来 的那些操作命令的时候,你就打 @a 。一共有26个寄存器可供你记录。

使用宏记录你可以重复许多不同的操作,不仅仅是插入文本。下次当你需要重复 一些操作的时候希望你能想到宏命令。

在使用宏命令时要特别注意的一件事是,当你重放这个宏的时候,你记录的命令 会被原封不动地重复出来。所以当你移动的时候你必须记住你跳过的那些文本可 能与你重放这个宏时跳过的文本不同。向左移4个字符可能在你记录宏的时候完成 你想要的修改,但是当你重放的时候可能需要移5个字符。我们经常需要使用针对文 本对象(单词,句子等)进行移动的命令,或移动到特定的字符上。

当你需要重放的命令变得越来越复杂的时候,想把它们一次就打好也会变得越来 越困难。这时候你应该放弃用录制宏的方法,而是去写一个脚本或宏。这对针对 你部分代码写一个模板非常有用;比如,一个函数的头。这些你想要有多灵活你 自己就可以做得多灵活。

1.3 好习惯三:有错就改

在打字时打错是正常的。没有人能避免。技巧在于快速地发现并纠正它们。编辑 器应该能在这点上帮助你。但是你得自己告诉它什么是错的什么是对的。

经常你会一次又一次地犯同样一个错误。你的手指就是不听你的使唤。这时候缩 写就派上用场了。几个小例子:

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

Vim会自动地当你打错这些单词帮你纠正回来。

同样的机制还可以用来通过少少的几个字符输入一个长长的单词。对那些你发现 很难输入的单词尤其有用,同时这也可以防止你打错。例如:

:abbr pn pinguin
:abbr MS Mandrake Software

但是,这些在当你不希望它们自动展开的时候给你带来麻烦,你在你的文本里就 很难输入“MS”了。所以最好用那些自身没有意义的短短的组合。

为了更好的在你的文本中找到错误,Vim有一套漂亮的高亮机制。这个本来是用来 对程度语言作基于语法的高亮显示的,但是它也可以帮你找到并高亮出错误来。

语法高亮会用特定的颜色显示程序中的注释。这听起来不像是一个很有用的特性。 但是一旦你开始使用它,你会发现它很有帮助。你能很快地发现本来应该是注释 的文本可是却没有按照注释来高亮(可能因为你忘了加一个注释标记)。或者看 见一行代码却被像注释一样高亮了(可能因为你忘了“*/”)。这些错误在一个 B&W(Black & White,黑白)文件里很难发现并且会浪费掉你很多时间去纠错。

语法高亮还能帮助你找到各种括弧的不匹配错误。一个没有被匹配的“)”会被用 亮红色的背景高亮出来。你可以用 % 命令去看它们是怎么匹配的,然后在正 确的位置插入一个“(”或者“)”。

其他的一些常见错误也能很快被发现,比如 #included <stdio.h> 而不是 #include <stdio.h> 。在黑白显示的编辑器里你会很难发现这个错误,但是 在Vim里很快就会发现“include”是高亮的,而“included”则不会被高亮。

一个更复杂点的例子:在英语文本中我们可以有一个所有正确单词的列表。任何 不在这个列表里的单词都是一个错误。通过一个语法文件你可以把任何不在列表 里的单词高亮出来。通过一些额外的宏你可以往这个单词列表里加入新的单词, 之后它们就不会被标记为错误。这个工作起来就像你在文本处理软件里所期望的 那样。在Vim里这个是用脚本实现的,你可以进一步调整它以适合你自己的习惯:比 如,你可以只检查你的程序注释里的单词拼写错误。

2 编辑多个文件

2.1 好习惯四:学会处理多个文件

人们不会只跟一个文件打交道。通常会有许多相关文件,而你一个接一个的编辑 它们,或者甚至同时编辑好几个。你应该能够用好你的编辑器使同时处理多个文 件变得更高效。

之前提到的标签机制也可以用在文件之间的跳转上。通常的做法是对你当前工作 的整个项目创建一个标签文件。你可以在整个项目的所有文件之间跳转去查找函 数的定义、结构定义、typedef等等。跟你自己手工查找比起来这会给你节约N多 的时间;当我浏览一个程序代码时我做的第一件事就是创建一个标签文件。

另一个强劲的机制是查找一个名字在一组文件中出现的所有地方:使用 :grep 命令。Vim生成一个匹配的列表,然后跳转到第一个匹配之处。 :cn 命令把你带转到下一个匹配上。比如当你需要改变一个函数调用的 参数数目的时候会非常有用。

头文件中会包含很有用的信息。可是要找到包含了你想看的声明的那个头文件并 非易事。Vim知道头文件,可以帮你搜索它们你要查找的单词。最常见的操作是查 找一个函数的原型。把光标移到你的函数上并打 [I 命令:Vim会显示所 有头文件中与这个函数匹配的地方。如果你想看到更多的上下文,你可以直接 跳转到这个函数的声明上。一个类似的命令可以帮你检查你是不是包含了正确 的头文件。

在Vim中你可以把文本区域分割成几个“窗口”,在不同的窗口里编辑不同的文件。 之后你可以比对两个或多个文件之间的差异,在它们之前拷贝/粘贴文本。有很 多命令可以:打开或者关闭窗口,在窗口之间跳转,暂时隐藏一个文件,等等。 同样的你需要使用那三个基本步骤来选择你自己需要学会的那一组命令。

多窗口编辑还有很多其他的用处。标签预览机制是一个很好的例子。它会打开一 个特殊的预览窗口,同时光标还留在你当前正在编辑的文件窗口里。预览窗口里 的文本会显示,比如,当前光标下的函数名字的声明。如果你移动光标到另一个 名字上并在那停留一秒钟,预览窗口里会显示那个名字的声明或者定义。这个名 字可以是在你项目头文件里声明的结构或者函数的名字。

2.2 好习惯五:(与其他软件)协同工作

一个编辑器是用来编辑文本的。一个e-mail程序是用来收发消息的。一个操作系 统是用来运行程序的。每个程序负责它自己的任务,并且应该把它自己的任务干 得很出色。真正的威力来自于让这些软件一起协同工作。

一个简单的例子:选择一个列表里的结构化的文本,对它们进行排 序: !sort 命令。外部的“sort”程序被调用来对文本进行过滤排序。很简 单,不是吗?我们可以把排序的功能在编辑器里(通过编程)实现,可是看一眼 “man sort”吧,它有很多的选项。它可能用了很机灵的算法来实现排序。你还希 望把这些全都包括在你的编辑器程序里吗?还有其他的过滤软件呢?你的编辑器 会变得很庞大。

Unix始终如一的精神就是让不同的程序干好它们不同的工作,而让它们协同工作 去完成一个更大的任务。不幸的是,大多数的编辑器不能很好的与其他程序协同 工作—比如,你不能给Netscape的e-mail程序换一个编辑器。最终你只好使用一 个蹩脚的编辑器。另一个趋势是把各种各样的功能都包含在编辑器里;Emacs是这 个趋势最终会发展成啥样的好例子。(有人称Emacs是一个操作系统,只不过也可 以用它来编辑文本。)

Vim努力与其他程序进行集成,但目前为止还做得不够好。现在我们可以用Vim做 为微软-Visual Studio和Sniff的编辑器。一些e-mail程序可以使用外部的编辑器, 比如Mutt,它可以使用Vim。跟Sun Workshop的集成工作目前正在进行中。一般来 说这是我们最近希望有所提高的一个地方。只有那时我们才能有一个系统,这个 系统是比它的零件的简单相加要更好的。

2.3 好习惯六:学会利用文本的结构

你经常会需要处理特定有着特定结构的文本,但是它的结构与现有的命令所支持 的有所差异。这时你需要回到编辑器的基本机制,依赖它们来创建一些你自己的 宏和脚本来处理你的文本。现在让我们来谈谈这些更高级的东西吧。

一个简单的的例子是加快编辑-编译-纠错流程。Vim有 :make 命令,用 来启动你的编译,捕捉到编译输出的错误信息,让你能跳转到错误所在的位置上 去纠正这些错误。如果你使用一个不一样的编译器,Vim可能会认不得它的错误 消息。除了回到那老掉牙的“我先把它们记在本上”的方式,你应该去调整一下 Vim的‘errorformat’选项。这个选项告诉Vim你的错误消息看上去是啥样的,咋 样得到它们的文件名和行号。对于那么复杂的gcc的错误消息Vim都能处理,所以 你也应该可以让Vim能处理几乎任何编译器的错误消息。

有时处理一种类型的文件只是简单的设置几个选项或者写几个宏的小事情。比 如,为了在手册页之间跳转,你可以写一个宏来:捕获当前光标下的单词,清除 当前缓冲区,把当前单词的手册页读进当前缓冲区。这是一个查询交叉索引的简 单而有效的办法。

通过我们说的那三个基本步骤,你可以更高效的处理任何结构化的文件。只要思 考一下你对这些文件想采取什么样的操作,找到能完成这些操作的编辑器命令, 并开始使用这些命令。这真的就跟听起来一样简单,你所要做的只是开始这么干。

3 磨刀不误砍柴工

3.1 好习惯七:把它养成习惯

学会驾驶汽车需要你付出很多努力。这是你永远骑自行车的理由吗?不是的。你 应该意识到你需要投资时间去学会一项新技能。文本编辑也是一个道理。你需要 学会新的命令并把它们变成一种习惯。

另一方面,你不应该尝试去学会一个编辑器支持的所有命令。那完全会是浪费你 自己的时间。对大多数人来说,学会大约百分之十到二十的命令就足够完成他们 的工作了。但是对不同的人来说这个百分之十到二十也是不同的组合。这要求你 时不时地往后仰一下,停下来思考一下你是不是有一些重复性的劳动可以把它们 自动化起来。如果一个任务你只会执行一次,并且你有相当的理由相信以后不会 再做一遍,那你就别想着去优化它了。可是你可能会意识到在过去的一个小时里 你重复地做一件事情做了好几遍了。这时你应该去翻翻文档看看有没有一条命令 把它加速一下。或者自己写个宏搞定它。如果这是一个挺大的任务,比如要写一 种特定格式的文本,你可以去新闻组或因特网上查一下别人是不是已经帮你解决 了这个问题。

三个基本步骤里最关键的是最后一个。你发现了一个重复性的任务,找到了一个 很好的解决办法,可是过了一个周末你发现你忘记了这个办法。这可不行。你应 该不停地重复你的解决办法直到你的手指能够自动的执行它。只有那时你才能达 到你需要的效率并且不容易忘记它。别尝试一下子去学会很多东西。但是同时学 会几样东西是很可行的。对于那些你不足够经常用到的技巧你无法让你的手指头 记住它们,但你可以把它们记到本上,这样你以后查起来可以更快一点。不管怎 么样,如果你能记住你的目的是什么,你会找到让你的编辑变得越来越高效的途 径的。

最后说一说那些不理会我们上面给的所有建议的人是咋样的:我现在还能看见有 人坐在电脑半天,抬头看一眼屏幕,再低头看一眼他们的两个手指头,再抬头看 屏幕…然后他们在那儿想,我咋这么累呢?用十个手指打字!这不仅会更快,也 会更让人不那么累。即使你每天用电脑一个小时,几个星期后你也应该就能学会 盲打了。

后记

我这篇文章的标题源自那本Stephen R. Covey写的非常成功的书《高效人士的七 个习惯》。我向每个希望解决个人和职业问题的人(谁不希望吗?)推荐这本书。 虽然你们中有人会声称这个标题源自Scott Adams写的那本Dilbert漫画《高级有 病人士的七年》(同样推荐!)(译者注:高效原文是highly effective, 高级 有病原文是highly defective)。请上 http://www.vim.org/iccf/click1.html 看 一下“推荐书目和CD”。

关于作者

Bram Moolenaar是Vim的主要作者。他写了Vim的核心功能,并决定许多其他人提 交的代码是否被Vim接受。他作为一个计算机工程师毕业于Delft技术大学。现在 他主要工作是软件,但是还记得怎么使用电烙铁。他是荷兰ICCF的创建者,该组 织致力于帮助乌干达孤儿。他作为一个系统架构师做一些自由职业者的工作,但 是事实上大部分时间他花在Vim的工作上。他的邮箱地址:Bram@Moolenaar.net。