Emacs 101 新手求生指南是我看过的第一个把 emacs 的本质讲清楚的教程,是我入坑最大的勇气来源,也是我写这个系列的初衷。

作者在首页提到了作者已退坑,TA 的选择有自己的时代原因。

我以此为切入,梳理一下 2020 年的今天 Emacs 软件环境的现状。

1 回应

跳到 VSCode 三個月後,我的日常工作裡 Emacs 只拿來做寫程式以外的任務(Magit, serial-term 之類的)

同感, Magit 过于优秀,作为 git 前端根本无可替代。

……就讓我幹譙一下 Emacs,目前在 Emacs 裡面搞過 C++, Python, JavaScript, TypeScript 的自動補全與重構(其實搞過的開發環境不只這幾種語言,但這幾種語言我都有寫了一定的時間比較理解),都很難搞

巧了,这几种我都搞过,无一例外地好搞,因为 LSP 出现了。赞美微软, LSP 解放了所有编辑器开发者和所有语言开发者,实现了IDE前后端真正的 解耦。作者生不逢时,2018 年的 LSP 环境远没有现在这么成熟和开箱即用。

先看配置,直接摘自我的配置文件。这种程度的就足够了:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
(use-package lsp-mode
:commands (lsp) ;; 懒加载
:hook ((ruby-mode ;; 设置哪些 major mode 里启动 LSP
        php-mode
        ;; python-mode ;; <- handled in nema-python.el
        js-mode typescript-mode js2-mode rjsx-mode
        go-mode
        rust-mode
        ;; c-mode c++-mode objc-mode ;; <- handled in nema-c.el
        ;; swift-mode ;; <- handled in nema-swift.el
        dart-mode
        elixir-mode
        java-mode
        ng2-html ng2-ts
        ;; plain-tex-mode latex-mode ;; <- handled in nema-latex.el
        ) . lsp)
:init
(setq lsp-enable-snippet t    ;;使用 LSP 提供的代码片段
      lsp-auto-guess-root t   ;; 自动猜测项目根目录位置
      lsp-response-timeout 20 ;; 前后端通信的超时时间
      lsp-auto-configure t
      lsp-prefer-flymake nil ;; 我们用 flycheck
      lsp-session-file (expand-file-name ".cache/lsp-sessions" user-emacs-directory) ;; 改个临时文件的保存位置
      )
:config
(use-package lsp-java) ;; Java 的 LSP 是个独立包,额外安装
(require 'lsp-clients)
(dolist (dir '("[/\\\\]builddir$"
               "[/\\\\]\\.elixir_ls$"
               "[/\\\\]_build$"
               "[/\\\\]\\.ccls-cache$"
               "[/\\\\]deps$"))
  (push dir lsp-file-watch-ignored))) ;; 项目根目录的判断依据:找文件夹名

然后照着 lsp-mode 的官方文档把对应语言的 LSP 服务端装起来就行了,基本上都是一两句话。

再看效果,请看 lsp-ui 的截图,是不是已经和 VSCode 差不多了?悬浮文 档、引用、跳转、重构、右侧快捷命令、自动补全、模板……应有尽有。

而且最終弄出來的效果也都沒有 Qt Creator / PyCharm / VSCode 好

Qt Creator / Xcode / Android Studio 有 UI designer,没啥好比的, Emacs 是不行。后两个我持保留态度,至少 Emacs 能持平 VSCode,因为 后端都是微软写的……

就算只是想寫個 web,vue, scss, pug / jade 和 stylus 這幾個需要的 major-mode 我都直接自幹要不然也 hack 過,現有的都超難用要不然就是 bug 滿天飛

哎这里我就要 diss 一下 web 界了,妖怪 DSL 满天飞。

都 2020 年了,谁还用 vue 啊,赶紧换 Angular 啦σ`∀′) ゚∀゚)σ

说到 pug, 这个点挺疼的。Emacs 的 parser 相当弱(低估了未来的语言 有多妖),性能也一般,还是同步的。

tree-sitter 提供了一套渐进式 parser,不过要把 Emacs自带的 parser 替换成它还有相当长的一段路要走。如果真的能替换,那么 Emacs 就会真 正成为一个语法树编辑器(而不是文本编辑器)。

另外 LSP 还有个姊妹项目叫 semantic highlighting protocol ,由 LSP 服务器告诉前端如何高亮代码。也可以期待一下。

搞了兩三年發現用 VSCode 隨便滑鼠點一點裝好 plugins 還不用動設定的開發環境都比目前Emacs上各式現有package與自己土炮出來的好用太多

综上,生不逢时……现在编辑 Angular 项目不要太酸爽。

C/C++ 支援就是沒有 QtCreator 或 VisualStudio 那樣的行雲流水(更別說現在有 clang 語意分析加持的 QtCreator 跟那好用到爆的 UI 搭配)

还是生不逢时。C 项目因为历史遗留原因,per-project 的环境都大不一样。 不过鉴于现代项目都用 CMake 了,其实这个配置也不麻烦,只要生成这个 JSON 放在项目根目录里, ccls 就能完美工作了。我的键盘固件、算法题 和路由器固件项目都是用 ccls 做 LSP 的,全程如预期。

你可能會說這些本來就不是編輯器該做的事情、Emacs 不是 IDE…但畢竟我是要工作寫程式不是在玩遊戲啊,工作效率才是最重要的,我根本不想管 Emacs 定位是編輯器還是 IDE。

综上,Emacs 就是个 IDE。除了 LSP 之外,Emacs 还能对接 Debugger 协议 DAP

不过对接 debugger 本来就是 Emacs 的传统强项,比如 gdb……

後來試試 VSCode,一裝好,哇好流暢的自動補全啊(Company 實在有夠慢)

如果 Emacs 突然特别吃 CPU ,可以 M-x profiler-start RET cpu ,然后执行高负荷操作,然后 M-x profiler-report 看哪个函数在吃 CPU 时间。向包作者汇报 Bug 时是个相当有用的信息

哇code 不用外掛就可以折疊耶

🤔️说来奇怪,我在用 Vim 的时候也是个重度折叠爱好者,但用了几年 Emacs 之后我丝毫不怀念这个功能……估计是导航太方便了?比如 lsp-ui-imenu

现在我只会在 org-mode 里用折叠。

哇 TypeScript 補全超聰明還會自動 import 耶

lsp-ui 右侧的快捷操作里有自动 import ,这是 LSP server 给的 suggestion。黄色的字都是可以点击 / 快捷键触发的,相当于 IDE里的 「💡️」。

哇寫 Vue 時編輯器可以直接理解 < script > 裡面的 TypeScript 語意耶

??2017 年可以做到啊……

媽呀找Reference的UI也太方便了吧……

你说 UI 不好看我同意,至于方便嘛…… lsp-ui-doc直接调用 webkit 内核渲染文档,和 VSCode 平起平坐了吧至少?

2 现状

上文所抱怨的东西我都理解并经历过,我刚使用 Emacs 是 2017 年,那时 LSP 还不是很成熟,语言的支持并不多,不值得折腾,颇有「编辑文件猛如 虎,一进项目二百五」的感觉:JS 有自己的补全包、Ruby 有自己的补全包、 Python 有自己的补全包,一个软件包一套配置,十分费劲不说,项目内互 动还不好(当时只有 Java 好些,一是语言比较显式,二是 Eclipse 定下 的那套已经成为事实标准了)。

第一次尝到 LSP 甜头是 PHP 的 intelephense ,惊为天人,不夸张地说有 phpstorm 八成功力了,甚至还能有有限的类型推理,对一个动态语言来说 要啥自行车,遂立即卸载掉残废的 ac-php。也就是在这时(18年?)我才 感觉 Emacs 可以作为一个严肃的 IDE 来用了。

所以现状就四个字:能用、好用。