在说基本编辑命令之前,我们先加一个小tip,说说如何将函数和键绑定在一起。
define-key函数需要三个参数,第一个是绑定表的名称,不同的模式下的描述表是不同的。第二个参数是键名,第三个参数是键要绑定的函数名。
emacs是一种无模式的编辑器,这也是除了vi之外大部分编辑器的标准做法。每个输入的字符都会直接输入到缓冲区里。编辑要用到的功能函数,就只好绑定到组合键上,主要是ctrl键,esc或alt键的组合键。
比如,最基本的光标移动。如果有上下左右键,就用上下左右键。没有的话,emacs会用c-f向右,c-b向左,c-n向下一行,c-p向上一行。c-a移动到行首,c-e移动到行尾。
大量使用ctrl和alt,esc键,使得手需要经常移动,小指被过度使用。
而vi的采用正常模式和编辑模式分离来解决这个问题,在正常模式下,不能输入字符,所有的字符都被当成命令来执行。此时,j是下一行,k是上一行,h是向左,l向右。效率要比c-n,c-p,c-b,c-f要高。0到行首,$到行尾。
但是vi的问题就是,需要经常在正常模式和编辑模式来回切换。
spacemacs使用evil来模拟vi的这种模式,而且有些键的绑定与标准emacs有所不同。
移动光标是最基本的命令了,这其中最基本的是光标左右移动,和上下移动。
我们先学习emacs的标准方式:
向右一个字符: c-f (forward-char)
向左一个字符: c-b (backward-char)
这两个函数都是用c语言实现的,所以没有lisp源码,目前我们暂时先关注lisp部分。
但是,在spacemacs的默认情况下,这两个绑定已经被取消了。因为spacemacs默认是用vi的模式方案,在正常模式下,使用h键左移,l键右移。
l键和右箭头键,绑定到evil-forward-char函数上. 最终,evil-forward-char还是会调用到forward-char来实现移动的功能的:
而左箭头和h键,则是调用的evil-backward-char函数:
就是行间移动,标准emacs的方式是:
向下一行:c-n (next-line)
向上一行:c-p (previous-line)
这两种方式在spacemacs中,在编辑模式下仍然可以使用。但是正常模式下已经被绑定到其他函数上了,因为有更方便的j和k可以用。
spacemacs支持在普通模式下使用j来移动到下一行,k来移动到上一行。j绑定的是evil-next-line函数,k绑定的是evil-previous-line函数。
上面两个函数都是对evil-line-move的封装,evil-next-line的参数是正的,evil-previous-line是负的。
很多时候,我们需要移动到行首或行尾,而不是向左或向右一点一点移动。
我们还是先看emacs的标准实现方式:
到行首:c-a (move-beginning-of-line) spacemacs支持
到行尾:c-e (move-end-of-line) spacemacs不支持
move-beginning-of-line的实现如下:
最终会调用到我们后面要学的goto-char函数,通过goto-char跳到真正的位置上。
spacemacs支持vi的方式,在普通模式下,0移动到行首,$移动到行尾
0 (evil-digit-argument-or-evil-beginning-of-line)
$ (evil-end-of-line)
evil-end-of-line其实还是要调用move-end-of-line函数来实现功能的。
emacs的标准方式:
到缓冲区头 a-< (beginning-of-buffer)
到缓冲区尾 a-> (end-of-buffer)
spacemacs支持这两种方式,在正常模式下,还支持"<"键绑定beginning-of-buffer,">"绑定end-of-buffer的方式。
我们先看下beginning-of-buffer,虽然也是goto-char的封装,但是确实不只是(goto-char 0)这么简单:
end-of-buffer的话,除了goto-char之外,还得考虑recenter的问题
emacs提供了两个函数,可以跳到任意一行,或者是任意一个字符。
a-g g 或 a-g a-g (goto-line n) :跳转到第n行
a-g c (goto-char n): 跳转到第n个字符
spacemacs还支持vi的方式来跳转行
行号 g (evil-goto-line),如果没有行号,则跳到缓冲区末尾
goto-char不出意料的,是用c实现的。
我们先来看看goto-line:
evil-goto-line写得简短一些:
如果一行一行的移动,实在是太慢了,我们可以使用重复命令,给函数传递一个参数。
标准emacs的做法是esc + 数字和c-u加数字两种方式:
esc n + 命令:执行n次命令。如果无法执行完n次,就尽最大的努力。比如向下移动n行,到是没到n行就到文件末尾了。那么就停在文件末尾。
例:
esc 10 c-n,向下移动10行
(universal-argument)函数,它绑定在c-u键上。
universal-argument如果不指定参数的话,默认执行4次。
但是在spacemacs上,universal-argument函数绑定在"空格 u"和"alt-m u"两个键上。
c-u在spacemacs中被移做绑定到evil-scroll-up上,用于翻屏。
有的时候,需要重新绘制一下屏幕,让我们移动到的那行变为中心:
c-l (recenter-top-bottom)
做错了,撤销是很关键的操作。
在标准emacs中,使用undo函数来进行这个操作。它绑定到c-_或c-/或c-x u三个键上。
在spacemacs中,c-x u被绑定到undo-tree-visualize函数上。 还可以用"空格 a u"来访问它。
而c-_,c-/,在spacemacs中,被绑定在undo-tree-undo上。
功能
函数名
快捷键
leader键
光标右移
forward-char
无
evil-forward-char
l
光标左移
backward-char
evil-backward-char
h
下移一行
next-line
正常模式c-n无效
evil-next-line
j
上移一行
previous-line
正常模式c-p无效
evil-previous-line
k
光标移至行首
move-beginning-of-line
c-a
evil-digit-argument-or-evil-beginning-of-line
光标移至行尾
move-end-of-line
evil-end-of-line
$
跳转到某一行
goto-line
a-g g或a-g a-g
evil-goto-line
g
跳到某一字符
goto-char
a-g c
跳到缓冲区头
beginning-of-buffer
a-<或>
跳到缓冲区尾
end-of-buffer
a->或>
重复执行
universal-argument
a-m u
空格 u
居中重绘屏幕
recenter-top-bottom
c-l
撤销上一次的操作
undo
undo-tree-visualize
c-x u
undo-tree-undo
c-_或c-/