我可以推荐 Emacs 的创新 UI——eww 吗?
摘要
文章推荐使用 Emacs 的 eww 网页浏览器,强调其缺少 JavaScript 的特性改善了许多网站的体验,并指出 Emacs 提供了独特的 UI 创新,如逐张图片调整大小和键盘导航。
<p><a href="https://lobste.rs/s/96kz5p/may_i_recommend_eww_for_emacs_s_innovative">评论</a></p>
查看缓存全文
缓存时间: 2026/05/18 00:24
# M-x apropos Emacs 来源:https://www.matem.unam.mx/~omar/apropos-emacs.html
## 目录
- 我能否为你推荐 eww,领略 Emacs 的创新 UI? (https://www.matem.unam.mx/~omar/apropos-emacs.html#may-i-recommend-eww-for-emacs-innovative-ui)
- 用补全探索大量数据 (https://www.matem.unam.mx/~omar/apropos-emacs.html#exploring-data-with-completion)
- Vim 是可组合的 (https://www.matem.unam.mx/~omar/apropos-emacs.html#vim-is-composable)
- 电梯演讲 (https://www.matem.unam.mx/~omar/apropos-emacs.html#elevator-pitch)
- 使用 Embark 尝试的十件事 (https://www.matem.unam.mx/~omar/apropos-emacs.html#ten-things-to-try-with-embark)
- 写作体验 (https://www.matem.unam.mx/~omar/apropos-emacs.html#writing-experience)
- 反对 which-key 的论据:一篇争辩 (https://www.matem.unam.mx/~omar/apropos-emacs.html#the-case-against-which-key-a-polemic)
- Emacs 键映射可以有有用甚至动态的提示 (https://www.matem.unam.mx/~omar/apropos-emacs.html#emacs-keymaps-can-have-prompts)
- 我的补全之旅 (https://www.matem.unam.mx/~omar/apropos-emacs.html#my-quest-for-completion)
- 欢迎来到 `M-x apropos Emacs` (https://www.matem.unam.mx/~omar/apropos-emacs.html#welcome-to-M-x-apropos-Emacs)
RSS 订阅 🛜 (https://www.matem.unam.mx/~omar/apropos-emacs.xml)
## 我能否为你推荐 eww,领略 Emacs 的创新 UI?
*发表于:[2026-05-16 周六]。在 Mastodon (https://mathstodon.xyz/@oantolin/116586598571160370) 上评论。*
我想可以安全地说,很多人认为 Emacs Web Wowser(以下简称 `eww`)是个玩具,并非真正可用的网页浏览器。他们会说“也许适合看文档”(意思是:阅读某款软件的文档)。当然,这种观点有很多道理:`eww` 无法运行 JavaScript,因此大量现代网页应用无法正常工作。但我认为 `eww` 被低估了,为了本月的 Emacs Carnival (https://www.emacswiki.org/emacs/CarnivalMay2026),我推荐人们尝试它,有两个独立的原因。
第一个原因有点令人伤感:`eww` 的局限性实际上 *改善* 了许多网站!我相信 `eww` 最大的弱点——缺乏 JavaScript——也可以是强项。如果你不运行网站的 JavaScript 代码,很多网站反而会 *改善*,这真是可悲。那些 JavaScript 通常只是用来加载广告或付费墙,或者让你正在阅读的文字消失,一两秒后以不同的(甚至更不易读的!)字体重新出现。类似地,许多网站本身就很难读:文本行长得离谱,颜色过于花哨,或者文本与背景对比度太低(我把最后一点归咎于视力极佳的年轻网页设计师,他们不明白很多中年人很难读懂浅灰色背景上细字体的中等灰色文本)。
JavaScript 问题在 `eww` 中开箱即用就能解决,因为它根本无法运行 JavaScript。默认情况下,eww 在颜色方面会让你受网站摆布,但简单的 `(setopt shr-use-colors nil)` 就能解决这个问题。你可以在 `eww` 中用你最喜欢的 Emacs 主题、合理的行宽和你选择的字体阅读任何网站(好吧,很多网站)。(当然,这部分并非 `eww` 独有,也有浏览器扩展可以在普通浏览器中达到同样目的。)
第二个原因可能令人惊讶:与标准浏览器相比,Emacs 有许多 UI 创新!有趣的是,我想到的创新并非专门为 `eww` 设计,而是更广泛的 Emacs UI 功能。以下是我喜欢的一些功能,我认为普通浏览器无法匹敌(如果我说错了,请告诉我):
1. 你可以单独调整图像大小,而不会影响文本或其他图像!使用 `image-increase-size`,当光标位于图像上时,默认绑定为 `i +`(仅限此时)。我经常发现图像要么稍微小了点,要么太大了。
2. 你可以使用 `follow-mode` 在多列中阅读文本。我喜欢让 Emacs 全屏并使用 3 列。(同样,你可能能找到浏览器扩展实现这个功能,但它是 Emacs 内置的。)
3. 你有两种搜索类型:`isearch` 和 `occur`。我用过的浏览器只有 `isearch` 风格的界面:它在你输入时增量搜索,你可以导航到下一个或上一个匹配项。但有时我想创建一个网页中某些文本所有匹配项的列表,并让这个列表持久保留,当成某种待办事项列表。在 Emacs 中,你可以用 `occur` 做到这一点。你可以通过给 `occur` 加上前缀参数来请求每个匹配项周围指定行数的上下文。你可以按 `RET` 或点击 occur 缓冲区中的匹配项来导航,或者使用 `next-error`(`M-g n`)和 `previous-error`(`M-g p`)——即使 occur 缓冲区不可见,它们也能工作。如果我在网上做深度信息搜索,我发现 occur 非常有用。
4. 如果你在 Emacs 中阅读网页,你可以直接评估网页上的代码!如果我正在阅读关于 Emacs 的博客,我经常会用 `eval-last-sexp`(`C-x C-e`)运行其中提到的 Emacs Lisp 代码,这非常方便。但当然,这并不限于 Emacs Lisp!如果我正在阅读一篇包含一些 Python 代码的博客文章,我会用 `run-python` 打开一个 Python REPL,然后将 Python 代码直接从 eww 缓冲区发送给它进行评估。为此,我写了一个小命令,将文本发送给找到的第一个可见 comint 缓冲区(我已经用 `comint-run` 和这个命令替换了几个“次要”主模式,我将它绑定到 `C-:`):
```lisp
(defun send-to-comint ()
"将活动区域或当前行发送到某个窗口中的进程。"
(interactive)
(if-let* ((process (cl-loop for w in (window-list) thereis (get-buffer-process (window-buffer w))))
(input (buffer-substring-no-properties (if (use-region-p) (region-beginning) (pos-bol))
(if (use-region-p) (region-end) (pos-eol)))))
(progn
(setq deactivate-mark t)
(funcall (buffer-local-value 'comint-input-sender (process-buffer process)) process input))
(user-error "未找到进程")))
```
5. 如果你是 Org mode 用户,能够使用 `org-store-link` 获取你正在阅读的网页的链接(包含 URL 和标题)会非常方便。当然,这并不是 `eww` 独有的,你也可以在 Emacs 之外使用 org capture 协议配合浏览器,但设置起来可能有点麻烦,而且至少根据我的经验,你需要为每个域名授权你的浏览器遵循 org-protocol 链接,这也有点麻烦。
6. 我犹豫着是否要加上这一点,因为它不是 Emacs 自带的功能,但我写了一个小而易于复制的库 (https://github.com/oantolin/emacs-config/blob/master/user-lisp/shr-heading.el) 来为所有 eww 缓冲区(更一般地说,是 shr)添加按标题导航的功能,支持 `shr-heading-next` 和 `shr-heading-previous` 命令,以及 imenu 支持。用 `consult-imenu` 通过补全选择章节标题,然后直接导航到长网页的正确部分,感觉棒极了。
最后,还有一点小细节:`eww-readable` 总是可以在 eww 缓冲区中使用,它能减少杂乱;浏览器通常也有“阅读模式”,但它们会用一些愚蠢的启发式规则来决定在哪些网页上显示按钮,而我发现当我想要使用时,按钮经常不显示!
所以:试试 `eww` 吧!是的,它因无法运行 JavaScript 而受限,但 (1) 有时这也是一个优势;(2) 你的“真正”浏览器始终可以通过 `eww-browse-with-external-browser`(绑定到 `&`)打开;(3) Emacs 出色的 UI 提供了一些浏览器在没有扩展或不方便的情况下无法提供的东西。
## 用补全探索大量数据
*发表于:[2026-02-28 周六]。在 Mastodon (https://mathstodon.xyz/@oantolin/116150164678646714) 上评论。*
当面对大量信息时,我希望电脑能帮我筛选。我认为自己的“浏览阈值”很低,很快就会转向搜索而不是翻页阅读。我之前在抱怨 which-key (https://www.matem.unam.mx/~omar/apropos-emacs.html#the-case-against-which-key-a-polemic) 时已经提过这个心理特点,当时提出的解决方案是使用 minibuffer 补全,而不是让眼睛疲劳。我特别建议在结合使用 orderless 补全风格 (https://github.com/oantolin/orderless) 时采用这种策略来筛选数据——因为人生苦短,没必要总是记住单词的顺序。
以下是另一个我使用这种策略的例子。我是学术界人士,经常需要找出某个领域有哪些期刊,以及它们的大致选择性等级。我通常使用 SCImago Journal Rank (https://www.scimagojr.com/) 数据库。我并不同意用引用指标来评价学术工作,但 (1) 我需要在一个使用它们的体系内工作;(2) 在某些用例中,我没有什么好主意用什么来替代它们。如果我把论文发表在该数据库未收录的期刊上,那篇论文很可惜地对我的职业生涯没有帮助——而且大多数期刊都在那个数据库里,所以坚持选择收录的期刊并不难。此外,有时我需要评估其他学者的工作,用于招聘、晋升决策或撰写推荐信,他们常常发表在我并不熟悉的期刊上(因为发表数学论文的学术期刊有成千上万种——而且我相信数学相比许多其他领域已经算小的了!)。在这些情况下,我会查阅该期刊,以便大致了解在那里发表论文的难度。我首先承认这种状况并不理想,但在我必须完成的某些任务中,我无法避免使用某种期刊排名。
总之,我以前直接使用 SCImago 网站查期刊,但用户体验与 Emacs 的 minibuffer 补全相比相形见绌:首先,网站要等到你按回车键才会显示任何结果;其次,你只能搜索期刊名称中的单词片段。我想要 Emacs minibuffer 补全那种完全交互性和搜索灵活性,搭配像 Vertico (https://github.com/minad/vertico) 这样的 UI 和像 Orderless 这样的补全风格——SCImago 网站已经支持 Orderless 最好的特性:以任意顺序匹配单词片段;但有些期刊以其缩写广为人知,而 SCImago 网站不支持这种搜索方式。最后,我在需要查期刊时经常就在 Emacs 中,所以切换到浏览器去做这件事是种小浪费。
现在,我发现你可以下载 SCImago 每年的数据,是一个 CSV 文件,所以我下载了最近几年的数据。每年的文件大约 10MB,所以我对其进行筛选,只保留至少发表一些数学论文的期刊,并将每年的列表合并成一个文件,大约有 15000 行。该文件格式化成一个 Lisp 列表,每行一个元素,每个元素对应一个特定期刊在某个主题和年份中的排名。然后我写了一个 Emacs 命令,它首先在 minibuffer 中提示输入期刊名称,然后再次提示输入年份,最后将那个期刊在那一年中的主题和排名列表复制到 kill-ring。我几乎从未完成过这个命令:找到我想看的期刊后,我在第二个 minibuffer 提示中看到主题和排名,然后用 `C-g` 取消命令。有时我不是在找某个特定期刊,而是想要某个领域的专业期刊列表。在这种情况下,我会运行命令,输入领域名称,然后用 `embark-export` 得到一个列出匹配期刊的缓冲区。在该缓冲区中,按 `RET` 在一个期刊标题上,会在 minibuffer 中提示输入年份,以便将主题和排名复制到 kill-ring。同样,我通常只是阅读它们,然后按 `C-g`。
另一种使用我命令的方式是作为一种补全形式:我用 `embark-insert` 将期刊的完整标题插入当前缓冲区。总的来说,拥有这个命令确实节省了不少时间。如果有人对代码感兴趣,它在一个公共仓库 (https://github.com/oantolin/scimago) 中,但我应该提醒大家:1. 用 `wget` 下载每年数据库文件的代码已不再有效,因为 SCImago 现在使用 Cloudflare 来验证你不是机器人(所以只能手动下载);2. 将 SCImago CSV 文件预处理成单个 Lisp 文件的代码是用 BQN 编程语言 (https://mlochbaum.github.io/BQN/) 编写的。我非常喜欢数组语言处理数据清洗任务,但由于目的是在 Emacs 中使用这些数据,我可能应该用 Emacs Lisp。而且如果 Emacs 自带 CSV 解析器的话,我可能也会用(尽管 BQN 也没有自带……)。总之,这里只是想说明一个观点:minibuffer 补全是一种很好的浏览大量信息的方式(对我来说,几屏内容就已经算“大量”了)。
哦,我差点忘了提代码中一件有趣的事:除了上面提到的命令,我还写了第二个命令,它也提示输入期刊名称,但随后不再提示,而是生成一个 `tabulated-list-mode` 缓冲区,显示每年的主题和排名。我从未用过那个命令,因为我前面描述的命令可以模拟它:从 *第二个* minibuffer 提示中使用 `embark-export` 可以得到几乎相同的结果!你可能认为,像我这样的人,应该能看出这个命令已被第一个命令和 Embark 涵盖……
## Vim 是可组合的
*发表于:<2025-12-28 周日>。在 Mastodon (https://mathstodon.xyz/@oantolin/115799215103803114) 上评论。*
我想阐明一件令我困惑的事情。这不是关于 Vim 本身,而是关于 Vim 用户。(既然这是一个 Emacs 博客,我也会顺便提供一些 Emacs 的提示。)我用了几年 Vim,仍然很喜欢它。当被迫在非 Emacs 编辑器中编辑文本时,我通常使用该编辑器的 Vim 模拟模式,因为通常都有不错的版本。
Vim 用户常说,Vim 的伟大之处在于它拥有一个可组合的文本编辑语言,他们会说这意味着你分别选择要操作的文本和要执行的操作,并且可以将任何操作与任何选择文本的方式组合起来。而且你可以按任何顺序选择这些组件:在所谓普通模式下,你先选择一个操作,然后一个操作数;但如果你更喜欢反过来,你可以使用 Vim 的视觉模式。
真正让我困惑的是:Vim 用户从未告诉你,这种可组合的编辑模型——分别选择要操作的文本和要执行的操作——极其常见,并且几乎内置于所有文本编辑器中。他们也没有说这是 Vim 独有的,但我认为,当它是一个普遍功能时,对其大加赞赏仍然显得非常奇怪。这就像一位朋友兴奋地谈论他的新车,告诉你他买的型号酷毙了,因为它有轮胎!即使是简陋的 Windows 记事本也是一个可组合的文本编辑器:你可以用鼠标高亮选择文本,使用 Shift 和方向键,双击选择单词,或三击选择一行;一旦选择了文本,你可以按退格键删除它,按 Ctrl+X 剪切到剪贴板,按 Ctrl+V 用剪贴板内容替换它,等等。记事本中的操作很少,但它们都与各种选择文本的方式组合在一起。我不记得用过任何一个文本编辑器,在 Vim 用户解释的意义上是不可组合的。对我来说,这根本不是让 Vim 与众不同的原因——它
相似文章
Emacs 就是我的浏览器
Joshua Blais 分享自己如何用 Emacs 内置的 EWW 替代主流浏览器,完成 85–90% 的日常上网需求,称此举干扰更少、信噪比更高。
推荐一下……理解 Emacs 的模式
文章解释了 Emacs 的架构模式,重点介绍了通用缓冲区数据模型和增量补全读取(ICR),并将其比作玫瑰的根与花瓣。文章强调了 Emacs 如何统一界面并通过 Elisp 实现可扩展性。
Emacs Docs: Emacs应有的现代文档网站
宣布Emacs Docs,一个为Emacs文本编辑器打造的现代文档网站。
在 Emacs 中,一切都像服务
这篇文章解释了 Emacs 如何作为各种服务的客户端,利用其内置的 UI、网络通信和数据管理库,支持了“一切都像服务”在 Emacs 中的理念。
软件界的Emacs化
作者讲述了在终端中阅读 Markdown 的烦恼,并描述了如何使用 Claude 快速构建一个自定义的 macOS Markdown 查看器(MDV.app),展示了 AI 如何让人能够迅速创建个人软件工具。