Emacs 修炼之道

“Don’t panic.”
— The Hitchhiker’s Guide to the Galaxy

作为一个 Emacs 控,在办公室我也积极的向别人推荐 Emacs,有时候会需要向别人介绍和解释 Emacs,比如它能够做什么,与其它编辑器有什么不同,如何使用它等。Emacs 是一个很大的话题,而且网上关于 Emacs/Vim/其他编辑器的各种圣战中飞扬的口水已经太多了,所以这里我把这篇内容缩小到 Emacs 的修炼这一点上,因为对于那些真正对 Emacs 感兴趣并准备起锚出发的 Emacs 初学者,如果有一个详细的指南,它记录了从入门到进阶等各个阶段,以及前进的道路上有哪些可以借力的资料或资源等,这是很有帮助的。于是我有了写此文的打算,作为一个过来人我就斗胆写一下 Emacs 的修炼之道。

一般来说,那些决定不用系统自带的文本编辑器,而专门花时间学习 Vim/Emacs 的人都需要在文本上做比较多的工作,他们希望在工具这一块上做长期的投资——即使 Vim/Emacs 的入门需要一些精力和时间,但熟悉之后能提高工作效率并长期发挥作用,当然这些人之中有很多是程序员。如果你像我认识的一些朋友一样,对系统自带的文本编辑器,比如 windows 下的 notepad,保持 100%的满意,那么就不用接着往下看了,尽可跳过下文并继续留在那个与世隔绝的默认编辑器的桃花源里,这种说法好像比较鄙视 notepad,但其实它主要是说:如果编辑需求复杂多变,那么编辑器相应的也需要变得复杂强大。

接下来这一个 Emacs 之道会有点长,因为 Emacs 被设计成能提供各种复杂多变的编辑功能,甚至是文本编辑之外的,例如玩游戏或收邮件等其它功能,所以 Emacs 才会有“伪装成操作系统的编辑器”这一别称,而且学习曲线会变得非常的,呃,奇怪[1]。尽管下文有点长,但是记得带上你的毛巾[2],无论遇到什么情况,最重要的是,Don’t panic。

我把 Emacs 修炼的道路分为几个主要的阶段:

1. 入门小徒

初学 Emacs,首先要了解 Emacs 的基本操作,Emacs 自带的 tutorial 文档就是为零起点的新手而写的,它介绍了窗口(window),文件,缓冲区等概念,并一步一步的指导初学者学习光标移动,插入修改,搜索,保存退出等基础功能,是最好的入门指南。默认的键绑定下在 Emacs 中使用 C-h t 可以打开这个 tutorial 文档,也有对应的中文译版叫《Emacs 快速指南》,文档不长,整个看完并按文档指引练习一下,之后就可以用 Emacs 完成简单的文本编辑。

接下来可以阅读《Learning GNU Emacs》,这本由老牌黑客 Eric Raymond 参与编写的书是学习 Emacs 的经典书目,内容很多也很全面,它介绍了从用 Emacs 做基本的文本编辑,到用 Emacs 收发邮件阅读网页,到定制编辑宏以及做程序开发等各种功能。初学者可以只读前 5 章,对 Emacs 的环境及常用操作做一个比较细致的了解。这本书的原英文第 1 版讨论的是 Emacs 的 18 版本,之后第 2 版出版,讨论的是 Emacs 的 19.30 版,而 2004 年出版的第 3 版,则随着 Emacs 的版本升级把内容更新到 21.3 版,到 2013 的今天,Emacs 的主版本号已经升到 24,虽然这本书在过去一段时间也算是与时俱进,但从版本上来远远落后于 Emacs 更新的速度,不过,很多内容在 Emacs 中保持稳定,还是很有价值的,只是阅读的时候要注意一下版本变化。这本书也有中文译本,已经绝版,但对应的只是较旧的英文第 2 版,译文流畅印刷错误也少,译本质量尚佳,因为是针对初学者而写的入门书,讲解详细,辅以图示截屏帮助理解,读来比较轻松。

进一步学习的话,则根据各人的需求而选择了,需求不同则学习的内容也不同。希望使用 Emacs 来做大量重复编辑的人可以学习定制编辑宏,用来写笔记的可以学习 outline-mode 或 org-mode,用来收邮件的可以学习 mew 等邮件客户端的用法。考虑到使用 Emacs 的人当中有很多的程序员,那么也根据编程语言的不同,学习的编辑模式也不同,Emacs 对于多种编程语言都有着很好的支持,如 C, C++, Java, Shell, Python, Perl, Erlang, Lisp……还有常见标记语言如 Html, XML 和排版用的 Tex, LaTeX 和 Troff 等。此外你可能会需要一些特别的功能,这些功能在其它的编辑器/IDE 也有,比如显示行号,在编写代码时的自动补全,全文格式化,代码折叠与展开,实时显示代码错误等,Emacs 还有一些比较独特好玩的功能,如 hungry delete。学习这些内容,除了《Learning GNU Emacs》这本书第 5 章后面的多个章节之外,网上也有很多的资料,不过就比较分散了,要找到 Emacs 是否有满足你特定需要的扩展,或者这些扩展怎么使用,google 是一个很好帮手。

这个时候你已经很熟悉 Emacs 日常使用,以及为自己的编辑需要加了一些扩展和定制,在配置文件不断变大的同时,你可能也知道一点简单的 Emacs Lisp 写法,但对 Emacs Lisp 还没有深入的了解。

由于各人的编辑需求不一样,这个寻找某种特定功能并定制使用的过程可长可短,了解 Emacs 在各种编辑模式下的功能有助于进一步学习 Emacs Lisp 及 Emacs 的内部实现,但这不是必需的。即使你很快的进入下一阶段开始系统学习 Emacs Lisp,但如果时不时会遇到新的编辑需要,还是会重复上述的扩展定制过程。以像我自己为例,因为需要编辑的代码种类越来越多,如后来的 Markdown, Erlang,所以也对应的添加了 markdown-mode, erlang-mode 的定制代码。

2. 登堂入室

在接触 Emacs 的过程中,很多新手都会注意到一个事实:Emacs 是用一种叫做 Emacs Lisp 的 Lisp 方言写的,如果不懂 Emacs Lisp 是无法进一步走入 Emacs 的殿堂的。所以在这里我把“开始系统的学习 Emacs Lisp”做为进入到第 2 阶段的标志。

在 Emacs 自带的 Info 文档中,对 Emacs 的描述是:

Emacs is the extensible, customizable, self-documenting real-time display editor.

可以看到,可扩展性,可定制性和自文档化是 Emacs 三个特别强调的特点,前两个特点或者其它编辑器也有,比如 Vim,但自我文档化这一点,可算是 Emacs 的一个独门绝技,是的,在 visual studio 中也有帮助系统,不过与 Emacs 的自文档化比起来,还是差得太远了,这方面可以比肩 Lisp 的编程语言不多,Python 是其中一个,自文档化与交互式编程结合起来,整个编程环境会让写代码的人相当舒服。

要开始 Emacs Lisp 之旅,最好的学习资料也是 Emacs 自带的文档,在 Info 中有一个 Emacs Lisp 的入门教程《An Introduction to Programming in Emacs Lisp》,这个文档由另一位老牌黑客 Robert Chassell 所写,由浅入深地详细介绍了 Emacs Lisp 中的列表操作,函数,缓冲区操作,窄化,剪切粘贴,正则表达式,代码调试等内容,由于把读者定位为没学过编程的人,所以行文比较啰嗦,程序员读起来可能会有点不耐烦。它也有中文翻译版,书名叫做《GNU Emacs Lisp 编程入门》,不过也比较旧了,是 2001 年由 FSF 中国组织翻译并出版的,年代久远,对应的 Emacs 版本是 19,这本中译版也已经绝版,不过网上可以找到电子版。虽然后来大师洪峰在他某次答问中说这本中译版质量很高[3],我个人看过纸版全书之后觉得其实翻译和出版的错误也不少,像他读过那么多书的人肯定清楚一个译本的质量怎么才算是“很高”,不过此书的中文翻译是他组织的,有点敝帚自珍也是人之常情。

特别值得一提的是,在这本书的前言里,作者 Robert 说“希望读者养成阅读源代码的习惯”,并把 Emacs 当成一个代码的宝藏,学习其工作机制。书中的内容多是具体的代码细节,看过之后是会忘记的,但“深入代码”这个习惯一旦养成,受用无穷。我个人认为也可以依据同样的标准来定义玩 Emacs 的程度,真正 Emacs 玩得好,不是说要用过多少个扩展,用得有多么的熟悉,而是深入到源代码去了解其内部实现。

在读完《GNU Emacs Lisp 编程入门》的基础上,可以找一些其它的 Emacs Lisp 入门级资料来看看,比如 wiki 上的 Emacs Lisp Cookbook,上面就有常用的各种数据结构,文件目录操作等的代码示例。经过学习之后,到网上一些站点,比如 Emacs 中文网李杀网,看一些文章通读其中简单的 Lisp 代码已经没有困难。

同时,可以阅读一些 Emacs 中常用小功能的源代码,比如自动高亮括号的 paren.el,高亮当前行的 highlight-current-light.el,显示行号的 linum.el,自动插入括号对的 skeleton.el 等,在读源代码的过程中有时会遇到未知的库函数和新的概念,通过查询 Emacs 的自带文档一般可以解决问题。

通过前面的学习,在前一阶段的基础上你已经掌握大量的 Emacs Lisp,在阅读源代码上有了不少的积累,但由于没有全面系统的学习 Emacs Lisp,有时候读起源代码来不懂的地方太多,会有种力不从心之感,这时候就可以开始进入第 3 阶段。

3. 武林高手

对于学习 Emacs Lisp,最权威的两个文档当然是 Emacs 自带的 Info 文档《The Emacs Editor》和《The Emacs Lisp Reference Manual》,前者主要介绍作为编辑器的 Emacs 概念和机制,比如 kill-ring,display, key-binding, 各种 mode 等,重点在使用,后者则全面系统的介绍了 Emacs Lisp 这门编程语言,比如各种数据结构及操作,宏,文加载等,重点在于编程,Emacs Lisp 作为 Emacs 的实现语言,当然两个文档会有标题或内容看起来很类似的章节,但由于两个文档重点不一样,两者互为呼应补充而非重复。这两个都是大部头,要读完的话甚费时日,但其内容并不艰深,读起来还算轻松,耐心读完的话,会功力剧增,对 Emacs 的理解有很大的提高。虽然我在这里把两个文档一起列出,但其实阅读顺序和阅读习惯可以按各人的习惯自由安排:可以先读前一本,读完再读后一本;也可以先读后一本,在遇到新概念的时候再回头看看前一本的对应章节。这两种都是比较有效的读法。就像电影《黑客帝国》第一部所讲的,在 Neo 知道 Matrix 不是看起来那样的真实之后,进入 Matrix 中能看到一些不真实的事物,读完这两本书之后,你再进入 Emacs 的时候,看着界面的 buffer,高亮的代码块,mode-line 等,不再只是看到它们显示出来的样子,而且透过表面看到了里面运行的模块和流动的代码。

作为读书的补充,可以适当的找一些源代码来看,一些常用的扩展如 auto-complete, yasnippet 等代码目录结构不算复杂的都合适。我个人建议以兴趣和熟悉程度为出发点,以你熟悉的 mode,或最感兴趣的扩展来作为开始,因为对外部功能了解越多,越有助于理解其内部代码,就像熟悉 Linux 的库和系统接口,有助于阅读内核源代码一样。

到此,你已经全面系统的学习过 Emacs 和 Emacs Lisp,在阅读源代码上也有了大量的积累。在正式变为高手之前,还有需要做一件事情:写至少一个扩展,并奉献出来。在开源文化或黑客伦理中,一个人成为高手或黑客,不仅因为他技术高超,而且因为他有很好的奉献精神。写一个扩展需要很多的劳动,写一个规模大而且质量好的扩展更是辛苦。虽然在前面的学习过程中,你已经读过一些扩展的源代码了,但在开始正式自己写扩展之前,或者你有兴趣阅读一下《Writing GNU Emacs Extensions》这本书,了解一下如何从头到尾写一个扩展。这本由 Bob Glickstein 写的书于 1997 年由 O’Reilly 出版,虽然内容很好,但是真的远远落后于时代了,对应的 Emacs 版本是 18,目前能找到的电子版印刷错误也较多。

4. 飞升成仙

到了这个阶段,进一步提升自己的方向有两个,一曰深度,一曰广度。

深度方面,可以全面阅读 Emacs 的源代码,学习其底层的 C 核心,Emacs Lisp 解释器的原理,学习 Emacs 的启动/运行过程,事件机制,与外部进程的接口,等等。还可以找一些较复杂较庞大的扩展代码来看,例如广为人知的巨兽 CEDET 等,除了熟悉如何用 Emacs Lisp 来实际编写大项目之外,还需要懂得很多与具体应用紧密相关的内容,例如对于 CEDET,就需要知道编程语言的词法文法解析过程。这种复杂项目对基础知识的要求较高,读起来较为艰深,需要做好“深挖洞,广积粮”的准备。

广度方面,可以广泛涉猎其它 Lisp 方言,学习 Lisp 的实现,历史及著名项目等,甚至可以弄一个 Lisp Machine 来玩玩,或者学习其它的函数式编程语言。这个话题太大,但我还是尽力尝试提供一点帮助信息。最大的两个 Lisp 方言当然是 Common Lisp 和 Scheme,如果详细叙述如何学习 Common Lisp 或 Scheme,那么可以需要写的篇幅比本文长得多,或者将来在我的博客上会出现《Common Lisp 修炼之道》或《Scheme 修炼之道》,但至少暂时是既无能力也无计划。这里只是简单列一下可供参考的书目:

《Structure and Interpretation of Computer Programs》,中译本《计算机程序的构造和解释》
《Ansi Common Lisp》,目前网上有在线中文翻译版本,前几章翻译得还不错
《Practical Common Lisp》, 伞哥(田春)翻译了中文版,2011 年出版,有的地方读起来比较生涩
《On Lisp》,伞哥和其他人合作翻译,网上有电子版,翻译质量很高,就像前文所说,“很高”这两个字不是随便用的
《Paradigms of Artificial Intelligence Programming: Case Studies in Common Lisp》,由 AI 大牛 Peter Norvig 所写的,书名看起来只是 AI 方面的书,但其实也是一本很好的 Common Lisp 教程
《Common LISP The Language, 2nd》,描述 Common Lisp 的语言标准

还有很多 Lisp 好书都没有一一列出,此外函数式编程语言也不少,虽然有时学习曲线陡得像是悬崖峭壁,但如果你真的到了这一步,相信会有足够的兴趣和技能支撑你继续走下去,总之可以选择的方向太多,这篇小文只谈 Emacs 修炼,适可而止。

到了这个层次,当然你也要注重发光发热,提挈后辈,可以在社区或邮件组多活动活动,奉献代码,解答疑问。不过这个也是大话题了,网上组织众多各人习惯不同,非三言几语能够说得清楚,按下不表。

如果以上提到的这些内容你都已经深入钻研,深到地球核心,又广到天际之远,那么恭喜恭喜,你可以正式宣称“神丹炼成,择日飞升”,到这个时候,你所需要的只剩下《颈椎病和鼠标手康复指南》。两千年前庄子就说了,“吾生也有涯,而知也无涯。以有涯随无涯,殆已;已而为知者,殆而已矣。”喜欢折腾 Emacs 的朋友们,人生短暂,还是悠着点吧。

注:
[1] 《主流文本编辑器学习曲线》这里有各种编辑器的学习曲线图示,Emacs 的曲线比较奇怪。
[2] 《银河系漫游指南》中毛巾这个词条有一些特别的解释。
[3] 这个问答后来被整理成为《你是如何成为 Lisp 程序员的》一文,在网上可以找到。

Comments