去年偷闲的时候,挖了好多大坑(这里这里这里)怎奈挖坑容易填坑难……客观原因自然是“认真的写作有如雕刻”云云,主观上嘛,“懒”大概是逃不脱的一个字吧。

Wait,是谁说过,“懒惰是程序员的美德”来着。秉承这种美德,耗了将近两个月的业余时间,尝试了不下 50 个 el-get package,并且认真读了不下 10 个 package 的 manual,遂成 oh-my-emacs.

一切缘起于两个月前的某一天,我忽然心血来潮,想要整理下那一坨 "just works" 的 .emacd.d 。我几乎尝试了所有 github 上比较流行的 .emacs.d ,但是没有一个满足我的需求。“因为所以,科学道理”,Reinventing the wheelNot invented here 大概是每个程序员必修的一课吧。索性不管那么多了,代码写的不好,又不输房子不输地,坑挖的不好,大不了留着自己用就是。

Oh-my-emacs 着重解决的问题是(引用自 oh-my-emacs 的 README):

  • Better default settings with various eye candy, powerline, scrollbar, color-theme, fonts, etc.
  • Adopt el-get as the default package manager for Emacs, instead of the default builtin package.el, say goodbay to ./configure; make; make install and explicitly mananully management of load-path. el-get also provides automatic documentation management, customizable user's recipe support, etc.
  • Self-adapted, only install necessary packages when it satisfy the prerequisities. You need to install clang for auto-complete-clang, for example.
  • Modular, only load necessary packages as you need.
  • Literate, each package have comprehensive documentation or even a tiny tutorial with it, together with necessary web links. Say goodbye to old, out-dated emacs lisp code from Google.
  • Work as expected, completion every where when possible, semantic code completion through auto-complete with various ac backend, helm for minibuffer completion, etc.
  • Full-blown, oh-my-emacs is not another starter kit, it is hacker kit.

这其中,补全、文档、自适应性,是我特别看重的三点。补全自不必说,作为上古大牛也许是不需要补全的,但是对于我这样 21st Century 成长起来、尝试过 Visual Studio 强大补全甜头的程序员来讲,补全是最为迫切的需求。而 Emacs/Vim 作为 General Purpose Editor,其最大的使用不便就是没有代码的语义补全 (semantic completion)。Emacs 有一个内置的 Semantic,来源于 Emacs 社区鼎鼎大名,目标远大的 CEDET,但是 Semantic 的使用和配置都很复杂(参考 emacser.com 的 文章),而且很慢,有时会让 Emacs 卡住。究其原因,我认为 Semantic 的思路是不对的。用性能本就不怎么好的 Elisp 去实现复杂如 C++ 这类语言的 Parser,其本身就是浩大的工作量。正确的思路是,对于不同的语言,依赖于不同的 backend,然后用 Elisp 写相应补全的 interface。所以我认为, auto-complete 的思路是正确的。Oh-my-emacs 利用已有的各种 auto-complete 的 backend(如 ac-slime, auto-complete-clang 等)基本上实现了对 C/C++,Python, ELisp/Common Lisp/Clojure的语义补全。

第二点是文档,Emacs 的世界从来不会缺乏选择, M-x el-get-list-packages ,2500 个 package,其中有很多 package 要么是已经过时,要么是年久失修,要么是语焉不详,看上去一片繁华的 Emacs 世界,实则荆棘密布。如果你没有一点 Elisp 的功底,想开箱即用,那几乎是不可能的。单拿 Python 来说,Emacs 和 Python 社区就有两套不同的 python.el ,这给很多 Python 和 Emacs 的初学者造成了困惑。Google: Python Emacs,其首页的几套解决方案,采用的是不同的 python.el……你说对于一个好容易学会翻墙,开始习惯用 Google 搜索技术文档的计算机初学者而言,看完这些文章,不晕菜才怪呢。稍微复杂一些的配置,比如 TeX Live,在比如 Common Lisp 的各种实现和 SLIME,想要得到一个比较舒适的环境,不但要配置好 Emacs,还要配置好系统环境,这又是一大难题。 Oh-my-emacs 借助 org-mode Babel,采用 Literate 的方式1,将文档和代码写在一起,在文档中尽量给出每个模块所需要的系统环境;对于有多个选择的情况,文档中尽量给出为什么选用 package A 而不是 package B 的理由和权衡过程。有一部分文档甚至可以当作 Tutorial 来看。Literate 方式最大的好处是保持文档和代码的同步,这样,oh-my-emacs 即可以用作是“开箱即用”的 .emacs.d ,也可以当作是手把手的 Emacs 配置教程(统计下来,oh-my-emacs 中文档和代码的 LOC 比例约为 3:1 左右)。另外,操作系统的环境千差万别2,因此 oh-my-emacs 基本上在每个相关模块的文档里面都指明了使用这个模块所需的系统环境,这也可以看做是我为了填去年的坑所做的一点努力吧。

第三点是自适应性。这又是一个很宽泛的话题。什么叫自适应性?是支持多个操作系统吗?不是的,至少我没有打算让 oh-my-emacs 很好的支持 Windows,一方面是因为 Windows 没有一个好的类似于 apt-get 这种类型的 package manager3,oh-my-emacs 依赖的很多底层软件如 SSH,GCC/Clang,TeX Live 等在 Windows 上配置起来都很麻烦,远不如 apt-get/yum/pacman/homebrew 这种一条命令来的方便。我这里讲的自适应性,主要包括:

  • 采用 el-get,自动化管理 load-path,以及 info 文档等,say goodbay to git submodule
  • 如果系统环境不满足某个 package 的要求,就不要安装这个 package,免得装完了不能用。比如 auto-complete-clang 依赖于 clang,如果系统中没有安装 clang,那么 oh-my-emacs 在启动的时候就不会安装 auto-complete-clang。反之,如果你意识到这个问题并安装了 clang,那么可要重启 Emacs,auto-complete-clang就应该可用了。
  • 尽量借助工具和代码获取相关配置,而不是在代码中写死。比如,oh-my-emacs 大量使用 Elisp 中的 executable-find ,这需要依赖于操作系统的 package manager 设置好相关的 $PATH ,这样带来的好处就是 oh-my-emacs 能够无缝的适应很多环境。
    • 比如 AUCTeX 需要 PDF 阅读器作为 LaTeX 文档的 Viewer,oh-my-emacs 采取的策略是优先采用 Okular,其次是 Evince,如果操作系统上即没有装 Okular 也没有装 Evince,那么 oh-my-emacs 会 fallback 到 xdg-open,这样可以用可移植的代码获得最大限度的灵活性和自适应性4
    • 再比如 SLIME支持多种 Common Lisp Implementation,oh-my-emacs 采取的策略是同时支持 SBCLClozure CLCLisp,也就是说,只要你安装了 SBCL/Clozure CL/CLisp 其中的一个,oh-my-emacs 的 Common Lisp 设置就应该是可以工作的。
    • 针对 auto-complete-clang, oh-my-emacs 可以利用 pkg-config 检测并设置正确的 ac-clang-flags ,可以对系统中可用的任意 C/C++ lib 提供语义补全。比如,你可以用 M-x ome-pkg-config-enable-clang-flag "QtGui" RET 来获得 QtGui 库的补全支持,效果如下:

Oh-my-emacs 目前已经包含了对 C/C++/Python/Common Lisp/Clojure 的支持,基本上都提供了较好的语义补全。其他方面,设置了更友好的字体,powerline,color-theme。启用了一些比较好的内置 mode,诸如 recentf/savespace/uniquify。对 LaTeX 编辑提供了完整的支持,默认采用 XeTeX。

Oh-my-emacs 的名字来源于 oh-my-zsh,用意嘛,自然是希望能将 oh-my-emacs 打造成 oh-my-zsh 那样。大话止于此,看行动。

最后放张图,更多美照在这里 。Enjoy emacs, and, your life.


  1. Literate programming 的概念来源于祖师爷 Donald Knuth。没记错的话,大名鼎鼎的 TeX 早期也是用 literate 的方式写成的。 Org-babel 提供了所谓的 "active code in Org-mode",还有专门的 Paper 论述 Org-babel 的 workflow。Oh-my-emacs 这方面的灵感主要来自于 emacs24-starter-kit

  2. 也许正是如此,Puppet/Chef 这类工具才会大行其道吧。

  3. chocolatey 也许是个不错的选择,但是我没有用过。

  4. 这个 PDF 阅读器的例子主要是在 Linux 下面测试的,我手头没有 Mac 的环境,so, patches are always welcome。