spacemacs: evil mode

本篇,我们来详细讲解 spacemacs evil mode 的常用操作。

Evil,全称 Emulation vim layer。作为 emacs 的扩展插件,它可以模拟绝大多数 vim 的键位和指令。emacs 的功能和可扩展性远在 vim 之上,但键位设计导致其编辑速度无法与 vim 抗衡。evil mode 通过在 emacs 中模拟 vim 的方式解决了这一问题。

启用 evil mode 只需要把 .spacemacs 文件中的 dotspacemacs-editing-style 设定为 'vim 即可。

在阅读本文前,你需要对 vim 的模式和键位有基本的了解。文中用 C- 代表 Ctrl 键,M- 指代 Meta 键(通常映射至 Alt)。列出的操作已在 ubuntu 系统中验证过。windows 与 macOS 的按键可能略有区别。


系列目录


状态栏

vim 的当前模式显示在 spacemacs 下方的状态栏中,对应关系如下表所示。

模式 状态栏颜色
普通 橙色
插入 绿色
可视 灰色


文件操作

同 vim 一样,evil mode 打开文件的指令为 :e。它支持路径补全,初始路径是启动 spacemacs 的工作目录。使用 emacs 的指令 C-x C-f 打开文件会弹出一个小窗格显示当前路径下的文件,这比 :e 方便很多。

:w 保存当前文件。:wa 保存所有打开的文件。

:q 关闭当前窗格。当你有多个窗格处于工作区时(无论它们是左右分栏,上下分栏,或更复杂的情形),:q 会关闭当前激活的(也称“焦点”)窗格。如果页面上只剩下了一个窗格,即便还有其他未关闭的缓冲区,使用这个指令也会退出编辑器。不过,辅助性的窗格,例如 neotree 文件夹视图,是不受 :q 影响的。


光标移动

evil mode 支持 vim 所有常用的移动操作,包括

  • h j k l 按字符移动
  • w W e E b B 按字移动
  • f F 至指定字符
  • 0 ^ g_ $ 至行首/至行尾
  • H M L 至屏幕最上行/至中间行/至屏幕最下行
  • { } 至上个/下个函数块
  • gg G 至文件头/至文件尾
  • 50G 至第50行
  • C-f C-b C-d C-u 向下/向上翻页

值得一提的是 emacs 的滚屏居中功能 C-l 还可以继续使用。由于 C-v 被可视模式占用,只好拿 C-f C-b 代替 emacs 的 C-vM-v


编辑操作

i I a A o O 进入插入模式,EscC-[ 退出,这些和 vim 没有区别。复制 y 与粘贴 p 依旧照常。撤销 u 和重做 C-r 也没有变化。

因为 C-u 已被占用,这个神奇的循环指令无法在 evil mode 中完成诸如字符填充的操作。若想得到一行 80 个 *,如今比较简便的办法是先输入 8 个星号,用 v 进入可视模式选定区域,然后 y 复制 1 次,p 粘贴 9 次。除第一次以外,p 也可以用 . 代替—— . 的功能是重复上一个操作,这也是从 vim 继承过来的。

三种可视模式 v VC-v 在 evil mode 中被完整保留下来。在可视模式中,ab aB ib iB 用于标记整个被 (){} 包围的区域(对 Python 脚本用处不大)。尽管在三种可视模式中,都可以使用 <> 调整缩进,但如果没有插件的支持,列编辑(批量注释代码)依旧需要 C-v + I + Esc/C-[ 这样复杂的操作。

在 evil mode 下,vim 的系统剪贴板也是可用的。"*p 粘贴系统剪贴板里的内容,"*y 将当前可视模式选定的内容放入系统剪贴板。

如果在普通模式和可视模式输错了指令(但还未执行),emacs 的 C-g 可以取消指令并恢复到正常状态,但 Esc 并不能起到同样的效果。


查找与替换

查找操作符 /? 分别相当于 emacs 的 C-s(可用)和 C-r(已被占用)。如果只输入小写字符则进行大小写不敏感的匹配,否则匹配是大小写敏感的。n N 用于在多个匹配间跳转。vim 的替换语句 :%s/OLD/NEW/gc 可以使用,不过 emacs 的交互式查找替换指令 M-% 对新手更友好一些。

在 evil mode 中,* 操作符的威力得到了提升,*e 相当于实时版的 :%s/OLD/NEW/g


窗口管理

创建新的窗格,可以用 :split 上下分栏,或者 :vsplit 左右分栏。它们允许接收一个路径参数,但与 :e 不同,其初始路径由焦点窗格的文件路径决定。也可以使用 C-w sC-w v 创建新的窗格,不过此时没有打开其他文件的机会,新窗格中显示的内容总是焦点窗格内容的副本。

与光标移动类似,切换焦点窗格的指令有 C-w h C-w j C-w k C-w l

emacs 原生并不支持标签页,因此 :tabedit :tabclose :tabdo gt gT 这些指令在 evil mode 中都不复存在了。不过,emacs 的缓冲区管理足够强大,可以在一定程度上实现标签页的功能。:ls 会列出当前打开的所有缓冲区,输入文件名称(支持模糊匹配)就会跳转至指定的缓冲区,关闭缓冲区可以用 vim 的指令 :bd

虽然有一个名为 ElScreen 的插件为 emacs 实现了标签页功能,但因为该插件年久失修,没有被集成至 spacemacs 中。出于以上原因,这里就不介绍 emacs 标签页的使用方法了。


文件夹视图

为了在 spacemacs 启动时显示当前路径的文件夹视图,需要修改 .spacemacs 配置文件中的 dotspacemacs/user-config 函数。

1
2
3
(defun dotspacemacs/user-config ()
(neotree-show)
(global-set-key [f8] 'neotree-toggle))

文件夹视图由 neotree 插件提供,它的操作也是使用 h j k l,不过现在的 h 是返回上一级目录,而 l 是展开子目录。在配置文件中,F8 被定义为 neotree-toggle 快捷键,用于随时唤出或关闭文件夹视图。


运行 shell 指令

:! + command 在 spacemacs 中执行 shell 指令,:r! + command 同时将输出结果粘贴至光标处。执行结束后,使用退格键最小化 shell 窗格。这些和 vim 没有丝毫差别。