emacs键盘映射
在emacs中我们可以将一个交互式的命令绑定到一个按键序列中。比如C-x C-f就绑定了命令find-file,而一般的字母和数字则绑定到了self-insert命令。使用这一个方式我们就可以做很灵活的绑定,让那些我们经常使用的命令绑定到非常方便的key sequence上面。这种命令绑定是通过key-map数据结构实现的。但是我们知道在emacs之中存在不同的major mode和minor mode,而且不同key-sequence的长度也不相同,那么这些因素对键盘绑定有什么影响呢?
1. 存在不同major mode和minor mode对命令绑定的影响
一个很明显的需求就是同样的key sequence在不同的major mode和minor mode中绑定不同的命令。这样就产生了一个全局key-map和局部key-map的需求,全局key-map只有一个,但是不同的major mode 和 minor mode都有一个自己的key-map。当你编辑的文件处于某个major-mode,并启用了一些minor-mode时,只有相关的minor-mode key-map,major-mode key-map和global key-map是可以影响到key-sequence的解释的。当需要给出一个key-sequence所绑定的命令时,首先搜索minor-mode的key-map,然后是major-mode的key-map,最后是global-key-map;当在前一个key-map中找不到时,才会到后一个key-map中寻找。当需要定义全局的key-map时可以使用global-set-key这个函数,如果需要定义局部key-map,使用local-set-key。
2. key-sequence长度对键盘映射的影响
有些键盘操作只需一次即可完成某个命令,比如C-f,C-b;但是另外一些则需要多次的按键,比如打开文件的命令C-x C-f就需要两个键盘操作。一个key-map数据结构只能对一个按键操作映射,因此需要多个键盘操作的命令需要多个key-map,而且第一个键盘操作绑定的不是一个命令,而是另外一个key-map,后面的按键就是根据这个key-map来找到要绑定对象。对于C-x C-f操作,定义了一个global key-map,将C-x绑定到ctl-x-map中,注意这个ctl-x-map并不是一个可执行的emacs函数,而是一个key-map,在这个key-map里面,C-f绑定到了命令find-file,因此按下C-x C-f这个key-sequence时,有两个key-map,而且涉及到了两个绑定。这里C-x就被叫做prefix-key,这里的意思就是这个key只是命令的前缀,但是具体的是那个命令还需要继续给出其他的key才可以。
在emacs中定义了很多这样的prefix-key,比如C-x,Esc,C-x 4,C-x 5,M-g,C-c等等,每一个prefix-key都绑定到一个key-map上面。在相应的key-map用于解释紧接着prefix-key的绑定,这样一直循环下去,直到最后一个key-map将一个key绑定到一个命令上,输入完成之后就执行。
那么global key-map,local key-map跟这些prefix-key绑定到的key-map有什么区别和联系吗?首先这些都是key-map数据结构,作用都是为了完成键的映射。不同的major mode和minor mode都有自己的local key-map,global key-map则只有一个。可以在local key-map里创建prefix-key,也可以在global key-map里创建prefix-key。(note!prefix-key所绑定的是一个key-map,但是prefix-key同样也是一个key,也必须在某个local key-map或者global key-map里创建才行)。
3. 如何创建prefix-key
简单一个函数(define-prefix-command 'key-map-name),然后绑定键值到新建的key-map就可以了。加入我们想把C-r C-t C-z a绑定到find-file命令。a. (define-prefix-command 'ctl-r-map); (local-set-key (kbd "C-r") 'ctl-r-map); (local-set-key (kbd "C-r C-t C-z a") 'find-file);这样就可以使用C-r C-t C-z a来打开文件了。但是在这里需要说明几点a. 如果已经存在相应的prefix-key定义,不需要重新重新创建,如果不存在,那么必须首先创建prefix-key b. 可以看到C-r C-t也是一个prefix-key,C-r C-t C-z也是prefix-key,这些都是emacs自动创建的,当我们也可以自己动手。所以对于一连串的key sequence,只需要对第一个key创建prefix-key就可以了。