Emacs 28 新特性介绍
现任 Emacs 维护者 Eli Zaretskii 在 9 月 30 号通过邮件列表[1]宣布 emacs-28 分支已经创建出,这意味着 28 版本的大功能已经 ready,不会再有大改动,但距离正式发版还要一段时间,根据之前的发版记录[2],大概率会在 22 年上半年 release。
2021-03-25 - Emacs 27.2 released.
2020-08-10 - Emacs 27.1 released.
2019-08-28 - Emacs 26.3 released.
2019-04-12 - Emacs 26.2 released.
2018-05-28 - Emacs 26.1 released.
2017-09-11 - Emacs 25.3 released.
...
对于 Emacs 拥趸来说,新功能要等上才能使用一两年是无法接受的。但实际这个问题不大,因为很多用户都在用开发版,这可能也是 Emacs 社区的特殊文化,自己去编译 master 分支来使用应该算是常态。由于使用人数多,所以即使是开发版,质量也能得到保证。
这篇文章就来介绍 Emacs 28 中,笔者个人觉得比较实用的功能,完整列表可参考 NEWS[3] ( M-x view-emacs-news
),最后会介绍如何在 macOS 上编译。
安装选项变更
• --with-native-compilation
这个功能是近几年 Emacs 中最大的更新,没有之一。它可以把解释执行的 elisp 代码通过 gccjit 技术直接编译成二进制代码。社区内相关讨论[4]
编辑变更
• 新配置 word-wrap-by-category
这是第八期嘉宾 casouri 的贡献,针对 CJK 字符,提高 word-wrap[5] 的效果。默认 false
• 新增命令 undo-redo
(C-?) 取消上一次 undo 命令,而且这个取消操作本身无法取消。Emacs undo 机制比较绕,可以参考之前的文章介绍[6]• 新增命令 copy-matching-lines
与 kill-matching-lines
。与 flush-lines
命令类似,但是匹配的行会作为整体加到 kill ring 中• 新配置 kill-transform-function
字符在添加到 kill ring 中的预处理函数• 新命令 revert-buffer-quick
提示更少的 revert• show-paren-mode
默认开启
通用变更
•更好支持 emoji。在 27 版本中,需要做如下配置:
(set-fontset-font t 'symbol (font-spec :family "Apple Color Emoji") nil 'prepend)
现在不需要这个配置就可以正常展示,并且提供了一个专门的 script symbol 用于表示:
(set-fontset-font t 'emoji '("My New Emoji Font" . "iso10646-1") nil 'prepend)
• 新选项 kill-buffer-delete-auto-save-files
之前总是会弹出提示,现在可配置•新选项 use-short-answers
用 y-or-n-p
替代 yes-or-no-p
,之前都是用这么做的:
(fset 'yes-or-no-p 'y-or-n-p)
• 新选项 copy-directory-create-symlink
在 src dir 为软链时, copy-directory
的 dst dir 是否也为软链,默认 false。• remove-hook
改成 interactive 命令• 新增命令 shortdoc-display-group
之前节目[7]中多次提到过的功能,按函数类型归类,展示其用法
• 新增命令 memory-report
• 新增命令 submit-emacs-patch
• 在没有设置 LANG 时,默认采用 UTF8 编码,之前是 ISO-8859-1
特定 mode 变更
• 新配置 dired-kill-when-opening-new-dired-buffer
默认 false• 新配置 dired-compress-directory-default-suffix
控制压缩目录的默认后缀,nil 表示 tar.gz
• 新配置 dired-copy-dereference
拷贝时是否跟随源文件中的符号链接• Org 升级到 9.5 版本• NonGNU[8] ELPA 默认开启• 新配置 abbrev-suggest
,开启后会根据用户输入,在 echo area 区域提示使用 abbrev 来简化输入• recentf-auto-cleanup
如果设置成时间字符串,会每天定时清理。比如 11:00pm
• 新配置 browse-url-default-handlers
根据 url 来定制不同的打开方式• mode-line 会展示 Elisp 作用域方式
• 新配置 shr-max-width
默认 120。• project 更新了一堆实用的命令,后面会单独写一篇文章介绍 28 中的 project 使用方式。
新 mode/package
• 新 mode repeat-mode
,比如 C-x u u
表示 C-x u C-x u
• 新主题 modus-vivendi
与 modus-operandi
• 新 major mode lisp-data-mode
适用于 lisp 表达式,但不是可执行的程序,比如 .dir-locals.el
• transient.el[9],就是 magit 中菜单导航使用的库,我的配置[10]中大量使用。• hierarchy.el[11],用于操作具有层级关系数据结构的库• shorthands.el[12] 一种 ELisp 命名空间的实现,社区内相关讨论[13]
平台相关变更
macOS
• s-<left>
与 s-<right>
绑定到 move-beginning-of-line
与 move-end-of-line
• 支持 Xwidget 组件
Windows
• 可以使用原生图像 API (MS-Windows GDI+)展示图片,该特性在测试阶段,需开启 w32-use-native-image-API
选项才能使用• 新增方法 w32-set-ime-open-status
,用于控制输入法切换,可以在 evil 切到 normal 模式时自动切到英文。社区内相关讨论[14]
不兼容变更
• Xref 实现机制从 EIEIO 迁移到 cl-defstruct, 不能再使用 oref
与 with-slots
• 使用 define-minor-mode
中的 positional 参数已经被淘汰
编译方式
看了上面那么多新功能,读者可能已经按捺不住内心的喜悦,这里就来介绍如何在 macOS 中编译 28 版本,其他操作系统方式类似。
1. 下载源码
git clone git://git.savannah.gnu.org/emacs.git
cd emacs
git checkout emacs-28
2. 下载依赖
brew install mailutils libxml2
3. 编译
make configure
./configure --with-mailutils
make -j4
make install
4. 测试
# 直接打开 Emacs
open nextstep/Emacs.app
# 在 Finder 中打开 Emacs,方便拖到 /Applications
open -R nextstep/Emacs.app
如果遇到下面的错误
xml.c:26:10: fatal error: 'libxml/tree.h' file not found
可以在第二步下载依赖后,导出下面的环境变量即可
export CPATH=`xcrun --show-sdk-path`/usr/include:`xcrun --show-sdk-path`/usr/include/libxml2
That's all. Enjoy hacking Emacs.
引用链接
[1]
邮件列表: https://mail.gnu.org/archive/html/emacs-devel/2021-09/msg02290.html[2]
发版记录: https://www.gnu.org/software/emacs/history.html[3]
NEWS: http://git.savannah.gnu.org/cgit/emacs.git/tree/etc/NEWS?h=emacs-28[4]
相关讨论: https://emacs-china.org/t/macos-emacs-28-native-comp/12201[5]
word-wrap: https://www.gnu.org/software/emacs/manual/html_node/emacs/Visual-Line-Mode.html[6]
文章介绍: https://liujiacai.net/blog/2020/11/25/why-emacs/#undoredo[7]
之前节目: https://emacstalk.github.io/post/002/[8]
NonGNU: https://elpa.nongnu.org/[9]
transient.el: https://github.com/emacs-mirror/emacs/blob/emacs-28/lisp/transient.el[10]
我的配置: https://github.com/jiacai2050/dotfiles/blob/1758c493243087f09f087e382f2021e139bb4c41/.config/emacs/i-basic.el#L346[11]
hierarchy.el: https://github.com/emacs-mirror/emacs/blob/emacs-28/lisp/emacs-lisp/hierarchy.el[12]
shorthands.el: https://github.com/emacs-mirror/emacs/blob/emacs-28/lisp/emacs-lisp/shorthands.el[13]
相关讨论: https://emacs-china.org/t/elisp-shorthands-emacs28/18481[14]
相关讨论: https://emacs-china.org/t/emacs-28-0-windows/12350