短松江月

Emacs 基础

· simons ·
Emacs 编辑器 快捷键 入门指南 效率工具 文本编辑

本篇介绍 GNU Emacs 的基础知识和操作。本文内容只是让读者初识 Emacs 操作,这些操作需要日积月累的练习才能掌握,本文的后半部分更偏向用于日后查阅;另一方面,很多操作有些繁琐难以记忆,笔者将会在后续介绍一些插件能够极大改善这些问题,因此读者如果遇到晦涩的地方不必过分担心,也不用死记硬背。

文章的结尾附上了本文出现的快捷键及其命令名,供读者查阅。

另外不要忘了官网的  Emacs Reference Card:即 Emacs 备忘表(Cheatsheet)。前两个 PDF 是基本内容,一个是 基本操作卡片,另一个是更为简洁的“ 生存卡片”。可以打印出来放在一边。

安装

截止本文更新日期(2025.7.17)Emacs 的稳定版本为 30.1。建议使用新一些的版本,最好是 Emacs 26 以上,因为一些插件需要 Emacs 更高版本的支持。

特别的,Emacs 28 版本新增使用 GCC JIT 对 Emacs Lisp 字节码的执行进行加速,可以显著提高 Emacs 的运行速度。推荐大家安装最新的版本。

图形界面在 官网下载安装包进行安装。

此外还可以用正常包管理工具来进行安装。

macOS:

$ brew install emacs-app

BASH

Debian/Ubuntu:

$ sudo apt-get install emacs

BASH

稍老一些的 Ubuntu 可能不能直接这样安装最新版本的 Emacs,需要自行去下载最新版本安装包安装。

其它系统类似,安装操作 官网下载页已描述详尽,在此不做赘述。

启动

图形界面可以直接打开程序。命令行输入命令启动 Emacs。

$ emacs

BASH

如果在安装了图形界面的机器上想要在终端里打开非图形界面版的 Emacs,输入:

$ emacs -nw # no window system

BASH

如果后面接文件名,则可以直接打开相应文件。

启动后可以看到这样的界面,可以看到其中有一个 “Emacs tutorial”,本文算是把该教程的内容梳理了一下,并进行了拓展,可以在阅读完本教程后,进一步参考,可以进行互动。同时,输入 M-x help-with-turorial-spec-language 可以更改语言,输入 Chinese 可切换中文(如何输入下文介绍)。

../../images/emacs-book/basic/startup.png
../../images/emacs-book/basic/startup.png

退出程序的方法请见最后的附录。

关于键盘操作

为什么大量使用快捷键?

Emacs 作为一个在图形界面诞生之前就存在的编辑器,其打设计之初就根本不需要鼠标来进行操作,那么直到今天,真正流畅的编程其实也最好不要引入过多的鼠标操作,越是常用的操作就应当更多地使用键盘而不是使用鼠标。鼠标是低效的,读者可以把手放到键盘上正常打字的位置,如果你现在忽然要使用鼠标来进行文本的选择,那右手(对于大部分人来说)就要立刻拿开,摸到鼠标、找到光标、移动到合适的位置、微调鼠标定位、选中、手放回原位。这么长的操作只是为了选中那么一点文字,而这又是如此常见的需求,这种操作模式会打断码代码的手部连贯性和头脑思绪的连贯性。

快捷键的出现就是用来弥补这一不足,通过简短的按键来完成一些复杂的任务。而 Emacs 一不做二不休,直接将快捷键用到极致——所有操作都最好用快捷键。这样一来,程序员会比较辛苦,需要记忆繁多的快捷键,但一旦形成了肌肉记忆,将能得到极高的效率。

需要提前说明的是,快捷键是一个十分自由的配置,你可以根据你自己的需要任意修改,笔者会给出一些笔者实践中的经验,但读者不必也不需要完全仿照,一切根据自己的习惯和需求来。

功能键

Emacs 中有五个功能键: Control 、 Meta 、 Shift 、 Super 、 Hyper 。其中部分名称读者可能不熟悉,那是几十年前的键盘上的按键名称,其中的 Hyper 键更是在现代键盘上消失了。那 Meta 和 Super 又是什么呢? Meta 对应于普通 PC 键盘上的 Alt 键,Mac 电脑上的 Option 键。 Super 对应 PC 键盘上的 Win 键,对应 Mac 电脑上的 Command 键。那么我们知道, Super 键在现代系统中起到了重要作用,因此 Emacs 平常不使用和 Super 键相关的快捷键,Emacs 的绝大多数快捷键都是使用 Control 和 Meta 键,而其中一大部分都是只使用 Control 键。

尽管 Hyper 键已经消失了,但是 Emacs 依然可以使用这个功能键,例如如果读者手上的键盘有一些不常用的按键,可以考虑设定为 Hyper 键,拓宽快捷键,这部分读者自行探索吧。 事实上 Emacs 中也有 Alt 键,但现在键盘上的 Alt 键都是被映射为 Meta , Alt 键也几乎不去使用了,为避免混淆就没有放到正文中介绍。

可以看到, Control 键是 Emacs 程序员键盘的“重灾区”,按 Control 键的小指也是 Emacs 程序员最易出问题的部位,因此笔者强烈建议,在你正式使用 Emacs 后改变键盘键位保护手指。 例如笔者将 Control 键改到了大小写锁定键上(读者可以调换两个键,但考虑到实际很少用大小写锁定键,笔者索性不要大小写锁定键了)。也可以将 PC 键盘上的 Win 键、Mac 键盘上 的 Command 键与 Control 调换,这样使用强壮的大拇指也没有问题。如果不想全局改变,也可以只在 Emacs 内部进行,后面会提到。 笔者作为 Mac 用户,推荐一款改键软件  Karabiner-Elements,它甚至可以将 Emacs 常用键位完全拓展到全局。

在 Emacs 中,我们经常需要自定义快捷键,那么需要一种方式来表示快捷键,这样才能写到配置文件里。Emacs 使用一个单独的字母表达功能键,见下表。

Emacs 功能键缩写对应键盘按键(Win/Mac)
ControlCCtrl / Control
MetaMAlt / Option
ShiftSShift / Shift
SupersWin / Command
HyperH

Emacs 用连字符表示“同时按下”。例如,我们用 C-a 表达“先按下 Control 键不要松,再按下 a 键“。 C-x b 则表达“先按下 Control 键不松,按下 x 键,松开这两个键,按下 b 键”。 C-S-<mouse-1> 表达“同时按下 Control 键和 Shift 键,然后鼠标左键点击“。这里提到了鼠标是因为 Emacs 图形界面支持鼠标操作,并且在有些场景下的确使用鼠标更为方便(例如无规律的多光标选择)。

特别的, Meta 键做前缀有两种按法,例如 M-x 可以“按住 Meta 键不要松,再按下 x 键“,也可以“先按一下 Esc 键松开,再按一下 x 键“。后者是为了在应对无法使用 Meta 键的硬件或系统。但实际操作有很多不便,因此读者尽可能使用 Alt / Option 作为 Meta 键来按。

一些终端例如 Mac 自带的终端默认不会把 Option 键作为 Meta 传入,但只需打开它的偏好设置,其中 ”Profiles - Keyboard“ 中有一项“将 Option 用作 Meta 键“,勾选即可。iTerm2 同理。

Emacs 命令

在介绍具体的快捷键之前,要先说明 Emacs 的主体逻辑。与其它编辑器类似,Emacs 也是通过命令进行交互的。而所谓命令,就是 Emacs 中使用 Elisp 语言定义的一些函数。这些函数可以完成一些功能。例如,即使是最最简单的“将光标上移一行”,也对应着命令 previous-line 。一切操作都对应一个命令,而快捷键的本质是在调用这些命令。

对 Emacs 输入命令需要先按下 M-x ,此时你会看到 Emacs 最下面的空行上出现了 “M-x “,然后等待你的输入,随后你便可以输入一个函数名。这一快捷键可以说是最重要的一个快捷键了,只要有它,即使你忘记了其它快捷键,也可以输入函数名进行调用。

命令名的传统是有连字符连接的多个有意义的英文单词。在输入时可以用空格代替连字符。也可以使用 <tab> 键自动补全。

自然, M-x 也对应着命令 execute-extended-command 。

基础快捷键

接下来介绍一些入门基础内容。读者最好打开一个文本进行尝试,例如前面提到的 Emacs 内置教程,如果不知如何打开,请按下 C-h t (注意松开 Control 键和 h 键之后再按 t 键)。或者读者打开任意一段代码。

对于 Vim 用户,可以安装 evil 插件来使用 Vim 按键,可略读下文的大部分内容。 插件的安装方式请参考 基本配置插件:功能增强类的最后一节。

如何退出

退出程序: C-x C-c 。

对于输了一半的命令,或者按了一部分快捷键但不想继续了,可以按下 C-g 放弃。此外在任何场合如果出现了卡住等情况,也都可以尝试输入 C-g 打断。

光标移动

光标移动也需要教?是的,Emacs 快捷键甚至连方向键都绑定了快捷键。如此大费周章是由于方向键在键盘上处于非常偏的位置,按方向键时你的右手需要做移动,而按方向键又是常见操作,Emacs 认为这种程度的手部移动就已经在打断写代码的连贯性了!

于是,方向键上下左右的快捷键是 C-p 、 C-n 、 C-b 、 C-f 。它们的英文含义分别是:previous(前)、next(后)、back(退)、forward(进)。一开始看的确很奇怪,但熟练之后确实方便顺手。

除此之外,Emacs 提供了多种方式进行光标移动:

  • 以词为单位: M-b 光标向左移动一个词, M-f 光标向右移动一个词。

  • 首尾:

    • 行: C-a 光标移至行首, C-e 光标移至行尾。而代码经常是有缩进的,但 C-a 会直接移动到整个行首,并不能直接编辑开头的文字,这种情况可使用 M-m 来移动到文字的开头。不过这里只是介绍,在 插件:功能优化类篇章中会直接推荐一个插件 mwim ,避免这个琐碎的小区别。
    • 句子: M-a 光标移至句首, M-e 光标移至句尾。
    • 整个文件: M-< 移动到文件开头, M-> 移动到文件末尾。注意这里需要同时按下 Meta 键、 Shift键和逗号/句号键。
  • 窗口: M-r 按第一次——光标移动到窗口中间行;接着按第二次——光标移动到窗口最上面一行;接着按第三次——光标移动到窗口最下面一行。

笔者平日使用 mac 电脑,macOS 本身就有着近乎全局的这套 Emacs 快捷键,因此笔者平日很少按方向键,全部使用这四个快捷键。读者需要大量练习,形成肌肉记忆。

如果想增加一些趣味性,可以玩 Emacs 内的贪吃蛇游戏来锻炼对方向键的熟练度。按 M-~ 调用 tmm-menubar ,按 t 选择 Tools,按 g 选择 Games,按 s 选择 Snake,然后开始游戏吧!

编辑操作

  • 删除字符:删除一个字符与正常一样,按下删除键(在 Emacs 中删除键写为 <DEL> 或 <backspace> )即可删掉光标左侧的字符。如果想要删掉右侧的字符,就按下 C-d 键。
  • 移除词: M-d 移除光标右边一整个词。 M-<DEL> 移除光标左侧一整个词。
  • 移除右侧直到句子结尾: M-k 。
  • 移除右侧直到行结尾: C-k 。
  • 选中部分区域(region):把光标移动到某处,按下 C-SPC ( SPC 表示空格键,space),此时 Emacs 最下方的空行显示 “Mark set“,表示当前打了一个标;接着任意移动光标到另一个位置,可以看到半透明的选择框。这就是和平日里你使用鼠标进行选择是一样的。按 C-g 可以取消选择。
  • 复制: M-w 复制选中的区域。
  • 移除: C-w 移除选中的区域。

注意,这里用了“删除”和“移除“两种说法,”删除“对应于 “delete”,是真的删除,而“移除”对应于 “kill”,相当于“剪切”,之后可以再次插入到其它位置,即 “insert”,相当于粘贴。

笔者的实际使用中,复制比移除更为常见,由于光标的移动等大量操作依赖于 Control 键,因此将复制与移除调换,使用 C-w 做复制, M-w 做移除更为顺手。读者可以根据自己的需要更改,具体配置方法见后续教程。

Emacs 内部维护了一个环形“剪贴板历史”,当你想插入之前移除的内容时(即粘贴之前剪切的内容),按下 C-y ,这被称为 “yank”,它会将最近一次移除的内容插入回来。那么如何粘贴历史记录呢?在一次 “yank” 的基础上,再按 M-y ,就可以得到倒数第二次移除的内容,再按一次 M-y 即可得到倒数第三次移除的内容,以此类推。 插件:功能优化类中笔者会介绍插件  counsel 辅助这个过程。

  • 撤销(undo): C-/ 或 C-_ 或 C-x u 。撤销刚刚的操作。对字符进行编辑例外,它会聚合最近的 20 次编辑,例如你按了 5 次删除键删除了 5 个字符,按一下撤销即可复原。
  • 重做(redo):Emacs 对于历史记录也维护成了一个环。但 Emacs 并没有直接的重做操作,而是先按一下 C-g ,即没有操作,此时再按撤销键时,会撤销上次的“撤销”,相当于重做;也可以理解为按下 C-g 后这个环的移动方向会改变。所以 Emacs 其实不分 undo 和 redo,而是靠改变历史记录的移动方向来控制。那么读者一定觉得这里难以理解不便使用,没错,因此笔者将会在 插件:功能优化类中介绍更好用的插件  undo-tree 。

标记与跳转

上文提到的选中键 C-SPC 不仅是选中文本这么简单的功能,它的本质是设定一个标记(mark)。Emacs 还有一个标记跳转功能,例如我们先在文本的第一行,按下两次 C-SPC (这样我们即打了标记,又没有选中文本),然后光标移动到别的位置(甚至以后学过之后,到别的文件),这时候按下 C-x C-SPC 或 C-u C-SPC ,即可立刻跳转回刚刚的位置。同样的,有更好用的插件可以辅助这一功能即上文提到的 counsel 。

想要跳到特定的行, M-g M-g 加行号、回车即可 。

重复操作

Emacs 提供了一个机制可以把一个命令重复执行任意次数。具体来说,先按下 C-u ,再按数字表示次数,再按下命令的快捷键。例如: C-u 12 C-n 表示向下 12 行。如果不加数字,默认是 4 次。这个用法的本质是对本来的 C-n 命令传递了一个数字参数。

此外,也可以按下 Meta 键的同时输入数字,或同时按下 C-M- 输入数字,同样可以实现数字传参。在图形界面 Emacs 中,也可以只按下 Ctrl 同时输入数字。

注意, C-u 其实是前缀参数(prefix argument)中的 universal-argument 的快捷键。其后加数字在大部分基本命令中是表示次数,但部分命令不一定表示次数,例如与 M-x 组合时的 C-u M-x 是基于前缀字符串搜索命令。可以类比我们的键盘上,按下 1 是输入数字 1,但按下 shift+1 得到的是叹号,C-u 就类似 shift 的作用,并且由于可以接数字等额外参数,C-u 非常强大。具体每个命令的前缀参数有何作用在其文档中都有说明,如何查看文档参考本文“获得帮助”小节。

页面移动

C-v 会向下翻滚一页内容, M-v 会向上翻滚一页。但 Emacs 会保留三行不会被翻过去,这样看起来更为舒服。

C-l 第一次按时,会移动页面使得光标所在行在窗口中央。这样当我们写文本写到下面时,只需要按一下 C-l 即可把当前光标所在行移动到正中央,有利于查看。但如果按完一次之后紧接着再按一次 C-l ,会移动页面使得光标所在行在窗口最上面,而按第三次 C-l 会移动页面使得光标所在行在窗口最下面。第四次按与按一次的效果相同,如此循环。

搜索文本

从光标位置向下搜索,按下 C-s ,即 search,此时最下方空行会出现 “I-search: “,输入你要搜索 的文本,此时会显示出能够匹配的文本,光标会移动到第一个匹配的文本位置。

  • 如果你想让光标跳到下一个匹配位置,就再按一次 C-s 。
  • 如果想停留在当前位置,退出搜索,按下回车键。
  • 如果想放弃搜索,回到搜索前的位置,按下 C-g 。
  • 如果想用正则表达式向后搜索,按下 C-M-s 。
  • 从光标位置向前搜索,按下 C-r ,其用法与 C-s 一致,只是方向相反。如果是想用正则,则按 C-M-r

安装了 swiper 的话会显示搜索结果列表,且默认可用正则表达式,更为直观( swiper 和上文提到的 counsel 是一套插件)。

如果对于一个很长的日志文件想要筛选其中特定的行,可以用 M-s o (或 M-x occur ),输入正则表达式即可。Emacs 中的正则表达式说明在 这里

其它小操作

  • 交换光标左右的字符: C-t ;交换光标前后的词: M-t ;交换光标所在行和上一行: C-x C-t 。还有交换句子、段落、选择区域等,但没有快捷键,详见 文档
  • 在光标所在行下方创建一个新的空行: C-o ;将光标所在前后所有连续空行变为一个空行: C-x C-o
  • 将光标后一词变为小写: M-l ;变为大写: M-u ;变为首字母大写: M-c 。
  • 放大字号: C-x C-= ,缩小字号: C-x C-- ,重置字号: C-x C-0 。

获得帮助

Emacs 内置了多种获取帮助的方式。其共有前缀 C-h 。

  • 简要描述快捷键功能:按下 C-h c 后,按想查询的快捷键。例如 C-h c C-p ,会在最下面出现:“C-p runs the command previous-line”,告诉你 C-p 键对应的命令是 “previous-line”。
  • 详细描述快捷键功能:按下 C-h k 后,按想查询的快捷键。
  • 描述函数(function): C-h f ,输入函数名。
  • 描述变量(variable): C-h v ,输入变量名。
  • 列出含某一关键词的命令(Command Apropos): C-h a ,加一个关键词。
  • 列出含某一关键词的符号的文档: C-h d ,加一个关键词。

这些帮助太多了记不住?还有帮助的帮助:

C-h ? ,列出以上功能,以及其它帮助功能。

有一个插件  which-key 可以在敲快捷键给予一定的提示作用,后续章节 插件:功能增强类会详细介绍。

一些系统对有些键位会做映射。例如 macOS 就会将 C-/ 映射为 C-_ , C-SPC 映射为 C-@。不影响日常使用,但是读者想覆盖键位时需要注意。

命令列表

操作描述快捷键命令名
输入命令M-xexecute-extended-command
退出程序C-x C-csave-buffers-kill-terminal
放弃当前输入C-gkeyboard-quit
光标向上一行(方向键上)C-pprevious-line
光标向下一行(方向键下)C-nnext-line
光标向左一个字符(方向键左)C-bbackward-char
光标向右一个字符(方向键右)C-fforward-char
光标向左移动一个词M-bbackward-word
光标向右移动一个词M-fforward-word
光标移至行首C-amove-beginning-of-line
光标移至行尾C-emove-end-of-line
光标移动到一行缩进的开头M-mback-to-indentation
光标移至句首M-abackward-sentence
光标移至句尾M-eforward-sentence
光标移至文件开头M-<beginning-of-buffer
光标移至文件结尾M->end-of-buffer
光标移动至窗口的中间、最上、最下M-rmove-to-window-line-top-bottom
删除光标右侧字符C-ddelete-char
移除光标右侧词M-dkill-word
移除光标左侧词M-DELbackward-kill-word
移除右侧直到句子结尾M-kkill-sentence
移除右侧直到行尾C-kkill-line
设置标记以选择区域C-SPCset-mark-command
复制区域M-wkill-region-save
移除区域C-wkill-region
插入已移除文本C-yyank
插入历史移除文本M-yyank-pop
撤回C-/ 或 C-_ 或 C-x uundo
跳转到上一标记C-x C-SPC 或 C-u C-SPCpop-global-mark
跳转到行号M-g M-ggoto-line
重复C-uuniversal-argument
向下一页C-vscroll-up-command
向上一页M-vscroll-down-command
移动页面使得光标在中央/最上方/最下方C-lrecenter-top-bottom
向后搜索C-sisearch-forward
向前搜索C-risearch-backward
向后用正则表达式搜索C-M-sisearch-forward-regexp
向前用正则表达式搜索C-M-risearch-backward-regexp
用正则表达式过滤文件的行M-s ooccur
交换前后字符C-ttranspose-chars
交换前后词M-ttranspose-words
交换前后两行C-x C-ttranspose-lines
在下方新建一行C-oopen-line
删除连续空行为一个空行C-x C-odelete-blank-lines
将后面的词变为小写M-ldowncase-word
将后面的词变为大写M-uupcase-word
将后面的词变为首字母大写M-ccapitalize-word
放大字号C-x C-=text-scale-adjust
缩小字号C-x C–text-scale-adjust
重置字号C-x C-0text-scale-adjust
简要描述快捷键功能C-h cdescribe-key-briefly
描述快捷键功能C-h kdescribe-key
描述函数功能C-h fdescribe-function
描述变量C-h vdescribe-variable
列出含某一关键词的命令C-h aapropos-command
列出含某一关键词的符号的文档C-h dapropos-documentation
帮助的帮助C-h ?help-for-help

入门介绍

多文件与模式