如何在 derived major-mode 中 覆盖已有的键绑定

vue-mode 派生自 web-mode。在 web-mode 中, M-. 快捷键 通过 tide-mode-map 被绑定到了 tide-jump-to-definition。我想在 vue-mode 中将 M-. 绑定到 lsp-ui-peek-find-definitions,而在 web-mode 中 M-. 还是绑定到 tide-jump-to-definition,该如何实现呢?

我目前是这样做的:

(defun adi/add-vue-keys ()
  (define-key tide-mode-map (kbd "M-.") nil)
  (local-set-key (kbd "M-.") #'lsp-ui-peek-find-definitions)
  )

(defun adi/post-init-web-mode ()
  (use-package web-mode
    :mode ("\\.html?\\'" "\\.jsx?\\'")
    :config
    (tide-mode)
    (add-hook 'vue-mode-hook #'adi/add-vue-keys)
    ))

但这样设置,首次进入 vue 文件后,M-.tide-jump-to-definition 永久解绑了,随后再进入 web-mode,M-. 使用的是其他默认的绑定。

绑到 vue-mode-map?

(define-key vue-mode-map (kbd "M-.") 'lsp-ui-peek-find-definitions)
(define-key web-mode-map (kbd "M-.") 'tide-jump-to-definition)

tide-jump-to-definition 被绑到 tide-mode-map 上的 M-. 了,tide-mode 是 minor-mode , 绑定键的优先级比 vue-mode 高

也许你需要 make-sparse-keymap,参考这里 hooks - How to suppress a minor mode's key binding in only certain major modes? - Emacs Stack Exchange

(add-hook '<major-mode>-hook
  (lambda ()
    (let ((oldmap (cdr (assoc '<minor-mode> minor-mode-map-alist)))
          (newmap (make-sparse-keymap)))
      (set-keymap-parent newmap oldmap)
      (define-key newmap [<thekeyYouWanttochange>] nil)
      (make-local-variable 'minor-mode-overriding-map-alist)
      (push `(<minor-mode> . ,newmap) minor-mode-overriding-map-alist))))

好的,我试试,多谢

describe-key 找到按键来源, 然后创建 local map 来覆盖设置。

可参考 Mastering Key Bindings in Emacs - Mastering Emacs 特别是 Keymap Lookup Order 小节总结的几个变量的优先级顺序。

1 个赞