| tags: [ Emacs Vim Lisp ] categories: [ Development ]
Lisp S-expression 编辑工具横评
写 Lisp 系语言(Common Lisp、Emacs Lisp、Clojure、Scheme、Racket 等)时,括号配对和 s-expression 结构操作是编辑效率的核心。本文横向对比主流的结构化编辑工具,帮助你按编辑器和习惯选型。
两大编辑范式
在深入具体工具前,先理解两种截然不同的思路:
结构编辑(Structured Editing):以 s-expression 为操作单元。移动、删除、复制都按"表达式"而非"字符"进行,括号始终自动平衡。代表:paredit 家族。
缩进推导(Indent-driven):以缩进为准,工具自动推断并维护括号结构。用户只管缩进,括号由算法补全。代表:Parinfer。
两者没有绝对优劣——结构编辑更精确可控,缩进推导更轻量直觉。
工具概览
| 工具 | 编辑器 | 范式 | 许可证 | 最新版本 | 最近活跃 |
|---|---|---|---|---|---|
| paredit | Emacs | 结构编辑 | GPL-3.0 | v26 (2022-11) | 稳定,低频维护 |
| smartparens | Emacs | 结构编辑 | GPL-3.0 | v1.11.0 (2024-03) | 活跃 |
| lispy | Emacs | 结构编辑 + 模态 | GPL-3.0 | v0.27.0 (2023-03 最后提交) | 停滞 |
| evil-cleverparens | Emacs (evil) | 结构编辑 + vim 模态 | MIT | v0.1.0 (2025-05 最后提交) | 低频维护 |
| vim-sexp | Vim/Neovim | 结构编辑 | MIT | 无正式版本号 (2021-02 最后提交) | 停滞 |
| vim-sexp-mappings | Vim (配合 vim-sexp) | 键位映射 | Vim | 无版本号 (~2015) | 休眠 |
| parinfer.js | 多编辑器 (JS 库) | 缩进推导 | MIT | 持续发布 | 活跃 |
| parinfer-rust | Vim/Neovim/Kakoune | 缩进推导 | ISC | 持续更新 (2025-01) | 活跃 |
| nvim-parinfer | Neovim (Lua) | 缩进推导 | GPL-3.0 | 2023-08 最后提交 | 低频维护 |
Emacs 阵营
paredit — 开山鼻祖
paredit 是 Emacs 上最早的结构化 s-expression 编辑器,定义了该品类的操作语义:slurp(吞入)、barf(吐出)、splice(解包)、raise(提升)等。核心原则是括号永远平衡——任何破坏平衡的操作都会被拒绝或自动修正。
- 优点:极简、可靠、零依赖;操作语义成为事实标准,后续工具都兼容其概念;学习一次终身受用
- 缺点:仅支持 Lisp 系模式;键位需记忆成本;不支持自定义配对符
- 适合:纯 Lisp 开发者,追求稳定的老派 Emacs 用户
- 安装:
(use-package paredit)或 MELPA
smartparens — 全能继任者
smartparens 在 paredit 的语义基础上做了大幅扩展:支持任意配对符(HTML 标签、Markdown 括号、引号等),提供 strict 模式(等同 paredit)和 non-strict 模式(允许临时不平衡),并内置了自动包裹、导航、删除等完整功能集。
- 优点:~1900 GitHub stars,社区最大;支持非 Lisp 模式;strict/non-strict 双模式;活跃维护,定期发版
- 缺点:配置项繁多,初始上手比 paredit 复杂;功能膨胀导致偶尔有边界 bug
- 适合:同时写多种语言的用户;想要 paredit 能力但不想被严格限制的场景
- 安装:
(use-package smartparens)或 NonGNU ELPA
lispy — 模态结构编辑
lispy 尝试将 vi 的模态思想引入 Lisp 编辑:在括号旁时自动进入"特殊键位"状态,单键即可执行结构操作(j/k 移动 sexp、c 复制、d 删除等),无需按修饰键。
- 优点:操作极为高效,熟练后速度超过 paredit;上下文感知的键位设计很优雅
- 缺点:~1300 stars 但自 2023 年起无更新,作者已转向其他项目;文档不够完善;键位与默认 Emacs 冲突较多,需要适应期
- 适合:追求极致编辑效率的 Lisp 重度用户;能接受维护停滞风险
- 风险:实质已被放弃,Emacs 版本升级可能带来兼容问题
evil-cleverparens — vim 键位 + 结构感知
为 evil-mode(Emacs 中的 vim 模拟层)用户设计的 minor mode。在 normal 状态下,vim 的 d、c、y 等操作自动按 s-expression 边界执行,不会破坏括号平衡。底层依赖 paredit 和 smartparens。
- 优点:MIT 许可证;让 vim 用户无需切换编辑思维即可做结构编辑;2025 年仍有提交
- 缺点:~227 stars,社区小;依赖链长(evil + paredit + smartparens);配置空间有限
- 适合:Emacs + evil-mode 的 vim 转投用户
Vim / Neovim 阵营
vim-sexp — Vim 上的 paredit
Vim 生态中最接近 paredit 的插件。提供 s-expression 级别的 text objects(if/af)和运动命令,支持 Clojure、Scheme、Racket、Common Lisp 等。键位设计遵循 vim 哲学,对宏录制友好。
- 优点:~648 stars,Vim Lisp 编辑的事实标准;text objects 设计地道
- 缺点:自 2021 年起无更新;默认键位较少,通常需要搭配
vim-sexp-mappings-for-regular-people使用 - 适合:Vim/Neovim 用户的默认选择
vim-sexp-mappings-for-regular-people
tpope 为 vim-sexp 补充的默认键位映射,把 vim-sexp 的原始操作映射到更直觉的组合键上。两者搭配使用是 Vim 上的标准方案。
- 注意:自 ~2015 年起无更新,但因其功能简单,不影响使用
Parinfer 系列 — 缩进即结构
Parinfer 采用完全不同的思路:你只管缩进,算法自动推导括号结构。有三种模式:
- Indent Mode:修改缩进 → 自动调整括号
- Paren Mode:修改括号 → 自动调整缩进
- Dumb Mode:纯输入,不做推导
核心算法以独立库发布,有多个编辑器集成:
| 实现 | 语言 | 适用编辑器 | Stars | 状态 |
|---|---|---|---|---|
| parinfer.js | JavaScript | VS Code, Atom, Sublime 等 | ~1800 | 活跃 |
| parinfer-rust | Rust | Vim, Neovim, Kakoune | ~630 | 活跃 |
| nvim-parinfer | Lua | Neovim | ~220 | 低频维护 |
- 优点:零学习成本——不需要记任何结构操作命令;对 Clojure 等注重格式一致性的语言特别好用
- 缺点:无法执行 slurp/barf 等结构变换;复杂嵌套场景下推导可能不符预期;本质是辅助而非完整的结构编辑
- 适合:偏好简洁的用户;Clojure 开发者;不想要结构化编辑学习曲线的新手
Neovim 推荐:parinfer-rust(eraserhd),性能最好,维护最活跃。
选型指南
你用哪个编辑器?
├── Emacs
│ ├── 纯 Lisp 开发,求稳 → paredit
│ ├── 多语言,要全面 → smartparens ★ 推荐
│ ├── 追求极致效率,能接受停滞风险 → lispy
│ └── evil-mode 用户 → evil-cleverparens
├── Vim / Neovim
│ ├── 要结构编辑 → vim-sexp + mappings
│ └── 要缩进推导 → parinfer-rust ★ 推荐
└── VS Code / 其他
└── parinfer.js 扩展
总结
- Emacs 首选 smartparens:功能最全、社区最大、维护最活跃,paredit 的超集
- Vim/Neovim 结构编辑选 vim-sexp:虽已停滞但功能完备,仍是唯一成熟选项
- 想要零学习成本选 Parinfer:缩进即结构,适合 Clojure 等格式规范的语言
- lispy 和 evil-cleverparens 各有巧思但社区较小,适合特定偏好的用户
工具只是辅助,核心是养成按结构而非字符思考的编辑习惯。选定一个,花两周适应,之后回不去。