以下是一段伪 Lisp 代码,概括了 Emacs 搜索活跃按键映射表的流程:
(or (if overriding-terminal-local-map
(find-in overriding-terminal-local-map))
(if overriding-local-map
(find-in overriding-local-map)
(or (find-in (get-char-property (point) 'keymap))
(find-in-any emulation-mode-map-alists)
(find-in-any minor-mode-overriding-map-alist)
(find-in-any minor-mode-map-alist)
(if (get-char-property (point) 'local-map)
(find-in (get-char-property (point) 'local-map))
(find-in (current-local-map)))))
(find-in (current-global-map)))
其中 find-in 和 find-in-any 是伪函数,分别表示在单个按键映射表
和在关联列表(alist)形式的一组映射表中进行查找。
注意 set-transient-map 函数正是通过设置 overriding-terminal-local-map
来实现其功能的(see 控制活跃按键映射表)。
在上述伪代码中,如果按键序列以鼠标事件开头(see 鼠标事件),
则会使用该事件所在位置而非光标位置,并使用事件所在缓冲区而非当前缓冲区。
这尤其会影响 keymap 和 local-map 属性的查找方式。
如果鼠标事件发生在带有 display、before-string 或
after-string 属性的内嵌字符串上(see Properties with Special Meanings),
且该字符串的 keymap 或 local-map 属性非 nil,
则该属性会覆盖底层缓冲区文本对应的属性(即底层文本的属性会被忽略)。
当在某个活跃映射表中找到按键绑定,且该绑定是一个命令时,搜索结束并执行该命令。 但如果该绑定是一个带有值的符号或字符串,Emacs 会用该变量值或字符串替换输入按键序列, 并重新开始在活跃映射表中搜索。See 按键查找。
最终找到的命令还可能被重映射。See 命令重映射。