hsingko


使用 keymap-set 管理 Emacs 快捷键

以前简单粗暴地直接用 global-set-key 来定义快捷键,于是配置文件里常常有下面这种一大段的代码:

(global-set-key (kbd "C-c n d") #'denote)
(global-set-key (kbd "C-c n t") #'denote-keywords-add)
(global-set-key (kbd "C-c n T") #'denote-keywords-remove)

最近看了 prot 刚出的视频, Emacs: define prefix/leader key (nested key maps) ,发现自己定义 keymap 其实很简单的,使用 defvar-keymap ,可以从上面的配置中抽取 C-c n 作为一个 prefix key ,定义如下:

(defvar-keymap hsk/notetaking-map
  :doc "My notetaking keymap"
  "d" #'denote
  "t" #'denote-keywords-add
  "T" #'denote-keywords-remove)

然后就可以用:

(global-set-key (kbd "C-c n") hsk/notetaking-map)

来将上面定义的 keymap 绑定到 C-c n 上。不过从 emacs-29 开始,更推荐用 keymap-set ,上面的代码可以改成:

(keymap-set global-map "C-c n" hsk/notetaking-map)

省去了 (kbd ...) 这一层,比较方便。

比起原先每个快捷键单独定义,使用 keymap 好处是便于管理,比如之后我想更换快捷键前缀,从 C-c n 换成 C-c C-n ,只要改一处 keymap-set 就可以了。

另一个优点是可以嵌套定义,比如我想要将 org-journal 相关的操作也挂到 hsk/notetaking-map 下面,可以先定义一个 hsk/org-journal-map

(defvar-keymap hsk/org-journal-map
  :doc "My org-journal keymap"
  "n" #'org-journal-new-entry
  "s" #'org-journal-search
  "o" #'org-journal-open-current-journal-file)

然后将它嵌套进另一个 map 下面:

(defvar-keymap hsk/notetaking-map
  :doc "My notetaking keymap"
  ;;...
  "j" hsk/org-journal-map)

这样 org-journal-new-entry 就映射到 C-c n j n 上了,非常优雅。