本入门指南至此结束。你已经掌握了足够的 Emacs Lisp 编程知识,可以设置变量值、为自己和他人编写简单的 .emacs 文件,以及为 Emacs 编写简单的自定义配置与扩展功能。
你可以在此处停下。或者,如果你愿意,也可以继续深入,自主学习更多内容。
你已经学到了编程的一些基础构件,但这只是一部分。还有大量易用的语法与机制我们尚未涉及。
你当下可以继续探索的方向,是阅读 GNU Emacs 源码,以及 GNU Emacs Lisp 参考手册。
Emacs Lisp 源码本身就是一场探索。当你阅读源码时遇到不熟悉的函数或表达式,需要自行分析或查阅其作用。
去查阅参考手册。它对 Emacs Lisp 的描述全面、完整且易于阅读,不仅面向专家,也适合像你这样具备当前知识水平的读者。(该参考手册 随标准 GNU Emacs 发行版一同提供。与本入门指南一样,它以 Texinfo 源文件形式发布,你可以在计算机上阅读,也可阅读排版后的印刷版。)
使用 GNU Emacs 内置的其他帮助工具:所有函数与变量的内置文档,以及可直接跳转到源码的 xref-find-definitions。
下面是我探索源码的一个示例。很久以前,我首先查看的是 simple.el,仅从文件名就能大致判断其内容。实际上,simple.el 中的部分函数较为复杂,至少初看时会觉得复杂。例如 open-line 函数看起来就比较繁琐。
你可以像之前分析 forward-sentence 函数那样,慢慢逐行阅读该函数。(See The forward-sentence function。)或者跳过该函数,查看其他函数,比如 split-line。你不必阅读所有函数。根据 count-words-in-defun 的统计,split-line 函数包含 102 个单词与符号。
尽管 split-line 篇幅不长,却包含我们尚未学习的表达式:skip-chars-forward、indent-to、current-column 与 insert-and-inherit。
以 skip-chars-forward 函数为例。
在 GNU Emacs 中,你可以通过输入 C-h f(describe-function)并输入函数名,来查看该函数的详细信息,获取其文档说明。
对于命名清晰的函数,比如 indent-to,你或许能猜出其功能;当然也可以直接查阅。顺便一提,describe-function 函数本身位于 help.el 中,它是一个较长但可读懂的函数。你甚至可以用 C-h f 命令去查询 describe-function 自身!
在这种情况下,由于代码是 Lisp 代码,*Help* 缓冲区会显示包含该函数源码的库文件名。将光标移到库文件名上并按下 RET 键(该按键在此场景下绑定为 help-follow),即可直接跳转到源码,效果与 M-.(xref-find-definitions)一致。
describe-function 的定义展示了如何在不使用标准字符编码的情况下自定义 interactive 表达式,同时也展示了如何创建临时缓冲区。
(indent-to 函数由 C 语言而非 Emacs Lisp 编写,属于内置函数。在配置正确的前提下,help-follow 与 xref-find-definitions 均可跳转到其源码。)
你可以使用绑定在 M-. 上的 xref-find-definitions 查看函数源码。最后,你可以在 Info 中打开参考手册,输入 i(Info-index)并输入函数名,或在印刷版手册的索引中查找该函数,了解手册中的相关说明。
同理,你也可以查阅 insert-and-inherit 的含义。
其他值得阅读的源码文件包括 paragraphs.el、loaddefs.el 与 loadup.el。paragraphs.el 中既有简短易懂的函数,也包含较长的函数。loaddefs.el 包含大量标准自动加载配置与键盘映射,我从未完整阅读过,只查看过部分内容。loadup.el 负责加载 Emacs 的标准组件,能让你深入了解 Emacs 的构建机制。 (更多构建相关内容,参见 See Building Emacs in The GNU Emacs Lisp Reference Manual。)
如前所述,你已经掌握了一些基础编程构件,但非常重要的是,我们几乎没有涉及编程的核心高阶内容:除了使用预定义的 sort 函数外,我没有讲解如何对信息排序;除了使用变量与列表外,没有讲解如何存储信息;也没有讲解如何编写能生成代码的程序。这些内容属于另一类书籍与另一种学习范畴。
你目前学到的知识,已经足以完成大量 GNU Emacs 实际应用工作。你已经成功迈出了第一步。这只是起点的终点。