《elisp 每日一练》—— 前缀按键

上一节我们提到Emacs中keymap上某个键可以绑定一个具体的函数,也可以绑定另一个keymap,如果绑定另一个keymap,它就变成了一个前缀键,本篇我们来讨论前缀和自建keymap

背景知识

emacs-lisp 复制代码
(defun my/hello()
  (interactive)
  (message "hello world"))

(keymap-local-set "C-c p h" 'my/hello)

我们先从上面的例子开始。上面我们通过 keymap-local-set 在当前buffer中绑定了一个快捷键。根据之前介绍的查找顺序,它在当前buffer的局部keymap中找到了这个绑定。

而我们将它拆解开来,实际上它先找到 C-c ,发现它绑定了一个 keymap 实际上 C-c 就是一个前缀。然后在它绑定的 keymap 中找到了关于 p 的内容,p也绑定了一个 keymap,接着在这个 keymap 中找到了 h 绑定的函数,最终执行这个函数。我们可以用这个图来描述这个树形结构

txt 复制代码
C-c
 ↓
keymap
 ↓
p
 ↓
keymap
 ↓
h → my/hello

也就是说我们调用 keymap-local-set 绑定快捷键时,Emacs已经帮我们构建了这样一个多层的keymap 结构。只不过这个过程我们之前没注意到。

既然Emacs已经默默帮我们构造了这样一个keymap,为什么还要提供让我们手动构造自己keymap的方式呢?因为这样可以使前缀的 keymap 成为一个独立的、可复用、可管理的对象,方便插件的开发者组织自己的快捷键。

例如 Projectile 有一组 C-c p 的快捷键,那么我们就可以创建一个keymap,将它绑定到 C-c p 的位置,然后我们只要操作这个 keymap ,就可以做到自然的将这些操作都绑定到 C-c p 下面

创建一个 keymap 可以使用 make-sparse-keymap。后续我们可以将它创建的 keymap 放入到 define-key 或者 keymap-set 函数的 keymap 参数中。

当然你也可以使用 define-prefix-command 这个宏来定义一个专门用于前缀的 keymap 。这个函数会将创建的keymap 映射为一个函数,后续我们可以调用该函数获得底层的 keymap

练习

本节我们利用这两种机制来创建一个类似 Projectile 插件的一组以 C-c p 开头的函数。我们绑定这么几个函数:

  • C-c p f 绑定到 find-file
  • C-c p b 绑定到 switch-buffer
  • C-c p g s 绑定到 vc-dir
  • C-c p g l 绑定到 vc-print-log
emacs-lisp 复制代码
(defvar my/git-sub-map (make-sparse-keymap)
  "用于二级git菜单的keymap")

(define-prefix-command 'my/project-sparse-map)

;; 绑定一级菜单
(keymap-set my/project-sparse-map "f" #'find-file)
(keymap-set my/project-sparse-map "b" #'switch-buffer)

;; 绑定二级
(keymap-set my/git-sub-map "s" #'vc-dir)
(keymap-set my/git-sub-map "l" #'vc-print-log)

;; 将二级map绑定到一级map
(keymap-set my/project-sparse-map "g" my/git-sub-map)

;; 绑定一级菜单
(global-set-key (kbd "C-c p") my/project-sparse-map)

(message "my/project-sparse-map 内部结构: %S" my/project-sparse-map)

小结

本节我们简单了解了一下前缀和嵌套keymap的内容,一般来讲,创建一个keymap可以使用下面两个函数

  • make-sparse-keymap
  • define-prefix-command
相关推荐
aluluka14 小时前
《elisp 每日一练》——状态栏显示管理与modeline 动态更新
emacs·lisp·elisp
aluluka2 天前
《elisp 每日一练》——minor mode 快捷键管理
emacs·lisp·elisp
Masimaro2 天前
《elisp 每日一练》——状态栏显示管理与modeline 动态更新
emacs
Masimaro4 天前
《elisp 每日一练》——minor mode 开关变量的管理
emacs
Masimaro5 天前
《elisp 每日一练》—— Minor Mode 变量生成机制与状态控制
emacs
Masimaro6 天前
《elisp 每日一练》——文件与目录的回顾与综合练习
emacs
Masimaro13 天前
《elisp 每日一练》——minibuffer输入读取和set-transient-map 临时热键状态机
emacs
Masimaro16 天前
《elisp 每日一练》——Window 树与布局状态恢复
emacs
典典分享指南18 天前
Windows 自动化踩坑实录
python·intellij-idea·pyqt·emacs·visual studio
辰辉创聚19 天前
重组细胞因子全解析:定义、分类与应用指南
人工智能·eclipse·emacs·白细胞介素·重组蛋白·重组细胞因子