News Hacker|极客洞察

238 66 天前 rahuljuliato.com
🛠两年 Emacs Solo:35 个自写模块、零外部包与全面重构的得失
把所有第三方包都重写,只为‘理解’Emacs?

🎯 讨论背景

原帖介绍一位用户用两年时间把自己的 Emacs 配置重构为“Emacs Solo”:35 个自写模块、不依赖外部包并做了全面重构。评论在实践层面补充了大量细节:如何处理备份与锁文件造成的系统污染(并给出 elisp 片段)、是否应重写社区包以便学习 elisp、以及 Emacs 在现代开发工具链(LSP、treesitter、LLM 辅助)中的位置。讨论还触及贡献到 GNU ELPA 需签署 FSF 版权转让这一治理约束、以及像 Tramp、which-key、magit、org-mode、Eglot、EAF 等具体工具和权衡。以上背景帮助读者评估“零外部包”策略的收益(可控性与学习)与代价(时间、维护和兼容性)。

📌 讨论焦点

备份与锁文件的默认配置问题

很多评论集中讨论 Emacs 的默认备份与锁文件行为会在系统路径(例如 /etc/nginx/sites-enabled/foo)生成 foo~ 或 .#filename 之类的残留文件,甚至被服务错误加载。社区给出具体可复用的 elisp 解决方案,例如禁用自动备份 (setq make-backup-files nil)、将备份重定向到单独目录(通过 backup-directory-alist 指向 ~/.emacs.d/backups/)、或关闭/重定向锁文件(create-lockfiles 与 lock-file-name-transforms)。有人指出 Tramp 在修改备份目录时会发出警告但通常仍能工作,另有用户强调在容器/VM 环境下使用 emacs-nox 时这些默认设置尤其恼人。评论同时回顾了这些默认的历史原因(早期网络不稳时的保护设计),并给出避免误提交与系统污染的权衡建议。

[来源1] [来源2] [来源3] [来源4] [来源5] [来源6] [来源7]

自行重写包 vs 复用社区包:学习与效率争论

有人认为把所有功能从零实现是低效且不必要的:Emacs 内置与 ELPA 之间的界限并不硬性,若不使用 ELPA 某些内置包可能缺补丁或更新。评论建议的折衷包括阅读社区开源包并把实现拷进配置或借鉴其思路——作者本人也承认受到 diff-hl、ace-window、olivetti、doom-modeline、exec-path-from-shell、eldoc-box、rainbow-delimiters、sudo-edit 等包的启发。多位评论强调“阅读别人的代码”对学习 elisp 更关键,仅靠写代码容易形成偏差;此外还提到向 GNU ELPA 投稿需签署 FSF 的版权转让(CLA),NonGNU ELPA 则没有此限制,这影响贡献和上游选择。总体争论在于:出于效率和补丁管理应优先复用社区代码,但出于掌控与学习可选择自写,二者有不同的成本与收益。

[来源1] [来源2] [来源3] [来源4] [来源5]

Emacs 的现代性与与 LLM / 新特性的结合

许多评论认为 Emacs 的设计经得起时间检验,最近的改进(如原生窗口管理、xref 与 wgrep 的整合)让它在现代开发工具链中仍具竞争力。有人讨论到 LLM(例如 Claude Code)可以从命令行生成或辅助编写 Elisp,利用 Emacs 强大的内核功能更快达到个性化目标;作者手工实现了这些功能,但评论者预期 LLM 会显著缩短实现时间。关于图形浏览器嵌入的可行性,讨论指出 webkit xwidgets 在 Emacs 30+ 兼容性受限,第三方 EAF(Emacs Application Framework)在 macOS 上也报告不稳定,限制了把浏览器直接嵌入的现实可用性。还有声音建议将合理的改动上游,以改善默认出厂体验而非全部本地维护。

[来源1] [来源2] [来源3]

个性化配置的收益与维护成本

评论反复提到高度定制能带来强大的工作流但需要投入大量时间与持续维护,许多读者既佩服又感到望而却步。多人把 magit 或 org-mode 列为继续使用 Emacs 的关键理由,并有用户坦言因公司无法使用 Emacs 而难以长期投入精力。对于想降低上手成本的用户,which-key、doom-emacs 等能提供按键提示和预设体验;但也有用户明确偏好 GUI 编辑器(如 Zed、Sublime)以避免学习曲线。总体评价是:定制是一项技艺投资,回报高但门槛与迁移/维护成本也高。

[来源1] [来源2] [来源3] [来源4] [来源5] [来源6] [来源7]

Emacs Lisp 的历史与设计哲学

关于为什么 Emacs 用 Lisp 的讨论回到历史与语言特性:Lisp 在 MIT AI Lab 与 Lisp Machine 的传统中盛行,Emacs 的可动态检查、修改与运行时代码生成特性与 Lisp 的“代码即数据”天然契合。评论指出 Emacs 更像一个可交互的 Lisp 机器而非纯粹的文本编辑器,这种环境便于热补丁、hooks、defadvice 等动态扩展模式。也有观点补充:Lisp 的极简语法和元编程能力使得生成和操纵代码更直接,但若只为纯文本编辑则并非唯一选择;总体上 Lisp 为 Emacs 提供了可观察、可扩展的运行时优势。

[来源1] [来源2] [来源3] [来源4] [来源5] [来源6]

可借鉴的具体实现与功能示例(expand-region、treesitter 等)

评论中给出若干可直接借鉴的实现细节:例如作者或读者实现了一个可自定义配对的 expand-region,支持按键触发在不同配对层级循环选择,并示例化映射如 'w'/'W'、Space、'$'、'/'、'*' 等以适配 vim 风格或 Markdown 场景。尽管有基于 treesitter 的现成插件可用,有人仍保留自写方案以便在特定文本对象缺失或需要跨越多层选择时更灵活。此外有用户表示这些自定义虽对个人工作流极为重要,但因兼容性与维护成本常对公开发布持保留态度;评论还包含实践性建议与小段 elisp 可供摘用。

[来源1] [来源2] [来源3]

📚 术语解释

ELPA(GNU ELPA / NonGNU ELPA): Emacs Lisp Package Archive,用于分发和更新 Emacs 包。向 GNU ELPA 投稿通常需要签署 FSF 的版权转让/CLA,而 NonGNU ELPA 不要求版权转让,这会影响贡献流程和上游选择。

Tramp: Emacs 的远程文件编辑层(Transparent Remote Access),支持 SSH 多跳等协议,允许在本地 Emacs 中透明编辑远程文件。Tramp 的行为会受备份与锁文件设置影响,在某些备份重定向方案下会产生警告但通常可用。

备份与锁文件机制(make-backup-files, backup-directory-alist, create-lockfiles, lock-file-name-transforms): 一组控制 Emacs 自动备份(产生 ~ 后缀文件)和锁文件(.# 前缀)的配置项。make-backup-files 可关闭备份,backup-directory-alist 用于将所有备份集中到指定目录,create-lockfiles 控制是否生成锁文件,lock-file-name-transforms 能重定向锁文件位置以避免工作区污染。

xwidgets / EAF: xwidgets 是 Emacs 的 WebKit 嵌入控件(用于在 Emacs 内嵌网页/GUI),在 Emacs 30+ 上存在兼容性问题;EAF(Emacs Application Framework)是第三方项目,尝试在 Emacs 内嵌浏览器和其他应用,但在 macOS 或新版 Emacs 上被多次报告不稳定。

LSP 客户端(Eglot, emacs-lsp / lsp-mode): Eglot 与 lsp-mode(常被称为 emacs-lsp)是将 Emacs 连接至 Language Server Protocol 服务器的客户端。两者在 UX 和配置上有差别,但功能与性能主要取决于所使用的 LSP 服务器(例如 C++ 常借助 compile_commands.json 提供准确的索引/补全)。

Magit / Org-mode: Magit 是一个被广泛推崇的 Git 操作界面插件,许多用户认为它是 Emacs 无可替代的核心优势之一;Org-mode 是 Emacs 的笔记、任务和文档系统,两者常被列为用户继续使用 Emacs 的主要理由。