背景

我大概从 2020 年开始使用 Doom Emacs,但是在今天之前从来没有想过要攒一套自己的 Emacs 配置。原因有很多,主要考虑到没有足够的时间,而且自己攒的未必能比一些发行版做得更好。

但是最近我开始重新考虑这件事情,因此记录下来自己的一些想法。

为什么

我发现自己对 Emacs 本身缺乏理解。我的快捷键是 evil + general + 原生 Emacs 混合起来的,我配置包的方式是 Doom Emacs 在 straght.el 的基础上封装的,并且很多包经过了发行版内部调整,用了很多私有变量和方法。

如果不去看源码,我是不知道他们是如何配置出来的,面对茫茫多的快捷键组合,我也不知道哪些是我需要的,哪些是“我不知道的”。

这么说来我实际上用的是 Doom Emacs 而不是 Emacs 本身。从快捷键到包管理,从主题界面到 LSP 服务器,实际上使用的是经过重重封装的 Doom Emacs。而这导致我并不知道如何配置完善的 react 开发环境,碰到问题也很难去修复,因为我实际上并不懂 Emacs 的机制,也不懂 Emacs Lisp。

新技术的适配需要等待作者来实现。例如更换性能更好的包管理工具、获得更好的 treesitter 配置。当然作为开源项目我可以提交 PR,但是因为前两个问题的存在,我并不具备给 Doom Emacs 仓库提交 PR 的技术能力。

当然促使我去考虑自己攒配置的事件是,有一天我升级了配置和若干个包,发现很多功能无法使用,导致我不得不打开 WebStorm 来开发项目,并且我的大量 org-mode 笔记也无法打开。这让我头一次产生对生产力工具失去稳定性的恐惧。

我终于意识到,对于一个开发者工具而言,稳定性、性能、个性化程度是不可能三角。稳定性和性能永远是第一位的,而要同时匹配自己的需求,在既要又要的需求下,只有靠自己花时间精力动手攒一套自己的配置。

意见

我罗列了一些网友们的意见。

  • Emacs 只是完成任务工具,应该将精力优先放在事情本身上

  • 对于新手来说,应该先使用一些知名的配置先用起来,等自己明白需求,提升了对 Emacs 的了解后,再可以考虑攒自己的配置

  • 让配置尽可能稳定,满足日常使用需求

这些观点大多在说明,新手可以先不急着自己从零攒配置,而是要先用起来,体会 Emacs 好处之后,再去考虑自己攒配置。

我观察到 Neovim 用户中,也会基于一些流行的配置,做一些自定义,而不会上来就自己从零写。

我觉得这些观点是对的,作为工具应当有能力保持稳定,保持结果的可预测,最终为完成自己的任务服务

收益

使用 Doom Emacs 的收益:

  • 不必从零开始攒配置。能够有一个默认开箱即用的环境,自己只需要少量的配置就能做好工作准备。

  • 减少选择包的精力消耗。很多功能需要使用 package 来补充完善,这方面需要大量的调研,判断哪些包符合自己的需求。

  • 发行版已经处理了很多细节问题。众所周知 Emacs 是一个非常古老的软件,有很多默认设置其实并不符合当前开发者的需要,因此会需要写大量的 elisp 代码来覆盖默认行为/样式。

自己攒配置的收益:

  • 能够完全符合自己的需要,代码利用率非常高
  • 减少自己的配置跟 Emacs 本体之间的抽象层级,降低复杂度
  • 避免了 Doom Emacs 做的抽象层,能了解真实的 Emacs 是怎样的
  • 提升了稳定性,因为只有自己会该这份配置,不会跟别人的冲突

总而言之,如果说维护一套配置也需要花费很多精力,那使用别人的配置似乎是一个可以在前期快速入门的好办法。但是后期要加深理解就需要去看配置的源码、甚至自己经历一遍攒配置的过程。

成本

使用 Doom Emacs 的成本:

  • 更多的抽象层级。需要理解 Doom Emacs 做的那一层抽象,并且需要看它的源代码才能更好地掌握和使用
  • 更新导致不可用。如果经常去跟随作者的更新,也就是经常执行 doom upgrade 并且不加审查的话,可能导致配置不可用。
  • 排查问题需要学习。
  • 自行修改的配置与现存配置的冲突

自己攒配置的成本:

  • 需要处理非常多的细节问题
  • 需要自己选择使用哪些工具
  • 有相当一部分形成习惯的配置需要从 Doom Emacs 中迁移过来
  • 大量的快捷键配置。键位设置在 Doom Emacs 中已经习惯了,要迁移到自己的配置很花时间
  • 会消耗大量的时间
  • 会有一段配置不可用的时间,直到自己完善了这份配置

作为发展多年并且比较流行的框架,Doom Emacs 在性能和功能丰富度上是超过自己写的配置的,自己的配置优势在于能够完全符合自己的需要,并且结构和逻辑比第三方的配置要简单。减少中间的抽象层。

甚至因为只需要服务自己,可以随时采用最新的方案,做大重构也不需要考虑兼容性,会更加自由。

分裂

Emacs 的自由性和每个人需求的差异导致很难汇聚一个共识上最优的方案。

这时候用户将需要在现有基础上定制,紧接着会遇到定制上的问题和学习成本,这时就该学习深入 Emacs 了。

也就是一个 Emacs 新人必须先从已经成型的 Emacs 配置入手,通过亲身使用和参考现成的配置来形成自己的配置方案。

但是如果每个入门 Emacs 的新人都需要自己攒配置,那可能导致大量的去解决重复问题,最终导致社区方案的分裂。当然现在很多问题已经通过 package 的形式解决了,但是在大块的问题之间,仍然有类似如何使用这些包、如何跟现有的工作流结合起来 等这类问题需要解决。

自己定制的方案由于是跟自己的配置耦合的,跟发行版的写法可能完全不同,很难在没有发行版使用基础的情况下回馈仓库。

最终每个人解决的问题都只能通过文章来传播,新人不得不通过参与 Reddit 社区、查看 Emacs dev 邮件组讨论的形式获得这部分知识。不过或许这就是开源的魅力之一,参与社区讨论也是参与开源的一种方式。

其他人的配置

列出一些对实现自己的配置有帮助的链接,参考他人的实践。

一些从零配置的教程

知名的发行版配置

其他开发者的实践

总结

我从前认为 Emacs 圈子大家应该都使用同一种包管理器、同一种补全搜索框架、同一种 LSP 方案。这样可以更好地利用前人的积累,从而推动生态发展。

但是实际上为了解决同一个问题,会有五花八门的选择出现,光包管理就有好几套:package.el,straight.el, borg, elpaca 等等。令人难以选择。

我想,现阶段使用 Doom Emacs 的优势是功能强大,并且我自己已经引入了很多包了来适配自己需要了,这部分配置是经过精心配置的结果,显然不能立马放弃。

而且新编写的配置在短期内可能无法承担日常使用,需要有一段发展的时间。

因此需要有让这两个方案并存的方法。正好 Emacs 最近的版本支持指定配置文件目录: --init-directory=xxx ,可以实现同时启动多个配置。

那么我们可以将 doom emacs 的配置和自己攒的配置放到两个目录中,然后使用应用启动工具如 Alfred 来配置两个启动命令:

  • 启动 Doom Emacs:
emacs --init-directory="/Users/dev/.config/emacs"
  • 启动自己的配置:
emacs --init-directory="/Users/dev/.config/simplemacs"

这样可以在 Doom Emacs 中编写新配置,逐步从各个地方摘抄自己需要的代码片段,直到自己的配置能够符合自己的需要。

这个过程我预计需要花半年到一年。好像有一点漫长,但是想起来我从 2020 年决定尝试一下 Doom Emacs 开始,被它的流畅性惊讶到,距今为止的 5 年时间好像也是弹指而过。

总而言之,自己的配置要攒,这样可以加深对 Emacs 的理解。但是 Doom Emacs 也要用,这样不耽误日常使 用。我觉得这是目前最好的方案了。