暂时覆盖(全局覆盖emacs中的键绑定)

时间:2016-01-01 07:37:28

标签: emacs elisp key-bindings

我使用此处所述的方法:globally-override-key-binding-in-emacs

(defvar my-keys-minor-mode-map
  (let ((map (make-sparse-keymap)))
    (define-key map (kbd "C-i") 'some-function)
    map)
  "my-keys-minor-mode keymap.")

(define-minor-mode my-keys-minor-mode
  "A minor mode so that my key settings override annoying major modes."
  ;; Define-minor-mode will use `my-keys-minor-mode-map' for us.
  :init-value t
  :lighter " my-keys")

(defun my-keys-keep-on-top (&rest _)
  "Try to ensure that my keybindings always have priority."
  (unless (eq (caar minor-mode-map-alist) 'my-keys-minor-mode)
    (let ((mykeys (assq 'my-keys-minor-mode minor-mode-map-alist)))
      (assq-delete-all 'my-keys-minor-mode minor-mode-map-alist)
      (add-to-list 'minor-mode-map-alist mykeys))))
(add-hook 'after-load-functions #'my-keys-keep-on-top)

(my-keys-minor-mode 1)

如何明确覆盖此内容? 链接中的方法对我不起作用。

EDIT2:

问题不仅适用于只读模式。 eval-after-load不是一个好方法,因为它会长期更改my-minor-mode-keymap

我在这里再说一个例子:

我大部分时间都使用程序模式。假设我想在程序模式下绑定C-q语法检查。但是,我有时会以文本模式记下笔记。在文本模式下进行语法检查是没有意义的。所以我决定让C-q绑定到拼写检查。

在正常情况下,我会这样做

(global-set-key (kbd "C-q") 'syntax-check)
(define-key text-mode-map (kbd "C-q") 'spell-check)

如果定义my-keys-minor-mode-map,如何产生这样的效果? 假设我把它放在我的键盘图中:

(define-key 'my-keys-minor-mode-map (kbd "C-q") 'syntax-check)

(define-key text-mode-map (kbd "C-q") 'spell-check)无法正常工作,因为我的键盘映射始终优先于其他次要模式映射。

无论

(eval-after-load "text-mode"
  (define-key my-keys-minor-mode-map (kbd "C-q") 'spell-check))

,也不

(add-hook 'text-mode-map (lambda () 
  (define-key my-keys-minor-mode-map (kbd "C-q") 'spell-check)))

做得好,因为他们长期改变了my-keys-minor-mode-map。这意味着当我从文本模式切换回程序模式时,我将失去语法检查功能。

编辑:

例如,

(define-key my-keys-minor-mode-map (kbd "<return>") 'newline-and-indent)

99%的时间可以工作,并且可以防止任何其他次要模式或主要模式修改它。

但是,键映射在只读模式下存在问题。所以我需要有超级优先级&#34;功能重新映射此键。我想要像

这样的东西
(defun super-priority-map()
  (define-key super-my-keys-minor-mode-map (kbd "<return>") 'something-else))
(add-hook 'some-modes 'super-priority-map)

更重要的是,只要保留指定的模式,超级优先级映射就应该起飞。

2 个答案:

答案 0 :(得分:0)

你在谈论只读功能吗?您无法使用键盘映射覆盖它。没有&#34;只读&#34; keymap捕获所有击键并发出错误。

要覆盖read-only-mode,只需关闭read-only-mode

即可

在代码中,设置buffer-read-only变量。

您还可以在代码中绑定inhibit-read-only变量以忽略所有只读机制(包括特定文本区域的属性 - 请参阅列表中的级别7和3)下文)。

除了只读之外, 完全有可能让其他键盘图优先于你的次要模式地图,但我倾向于说与你的次要模式键映射有任何罕见的冲突,您应该直接修改与您自己的密钥映射冲突的密钥映射。

您的次要模式键映射实际上可以被许多其他人取代,但您可能不希望通常以更高的优先级工作。

我建议阅读Mastering Key Bindings in Emacs,这是对这些内容如何运作的一个非常可读的解释,并且从中我已经抓住了以下的键盘映射优先级列表:

  1. overriding-terminal-local-map用于终端特定的密钥绑定。
  2. overriding-local-map表示应覆盖所有其他本地键盘映射的键。如果你使用它,要非常小心!
  3. Keymap字符点本地键盘图的点的char属性为。这用于yasnippet中的字段和自定义对话框等内容。
  4. emulation-mode-map-alists用于高级多模式键盘映射管理
  5. minor-mode-overriding-map-alist用于覆盖主要模式中次要模式使用的键盘映射。
  6. minor-mode-map-alist与上面的覆盖版本完全相同,但是为次要模式指定键盘图的首选方法。
  7. Keymap点上的文本属性类似于上面的char属性,但仅适用于文本属性。
  8. current-local-map表示缓冲区当前本地地图中定义的键盘映射
  9. current-global-map是Emacs寻找关键绑定的最后一个地方,它适用于全球关键绑定。
  10. 请注意,您的辅助模式在6级工作,并且上面的所有内容都可以优先使用。

    解除冲突的典型模式是:

    (eval-after-load "NAME-OF-LIBRARY"
      '(define-key NAME-OF-KEYMAP (kbd "KEY") nil)) ;; unbind KEY in KEYMAP implemented by LIBRARY
    

    最有可能的是,您还添加原始命令的替换(非冲突)绑定。

答案 1 :(得分:0)

buffer-locally-overriding-minor-mode-key-bindings-in-emacs

将所有内容组合起来

(defvar my-keys-minor-mode-map (make-keymap) "my-keys-minor-mode keymap.")

(define-minor-mode my-keys-minor-mode
  "A minor mode so that my key settings override annoying major modes."
  t " my-keys" 'my-keys-minor-mode-map)

(defadvice load (after give-my-keybindings-priority)
  "Try to ensure that my keybindings always have priority."
  (unless (eq (caar minor-mode-map-alist) 'my-keys-minor-mode)
    (let ((mykeys (assq 'my-keys-minor-mode minor-mode-map-alist)))
      (assq-delete-all 'my-keys-minor-mode minor-mode-map-alist)
          (add-to-list 'minor-mode-map-alist mykeys))))
    (ad-activate 'load)

(defun my-keys-minor-mode-override (key def)
  "Overrides a minor mode keybinding for the local
   buffer, by creating or altering keymaps stored in buffer-local
   `minor-mode-overriding-map-alist'."
    (let* ((oldmap (cdr (assoc 'my-keys-minor-mode minor-mode-map-alist)))
           (newmap (or (cdr (assoc 'my-keys-minor-mode minor-mode-overriding-map-alist))
                     (let ((map (make-sparse-keymap)))
                       (set-keymap-parent map oldmap)
                       (push `(my-keys-minor-mode . ,map) minor-mode-overriding-map-alist) 
                       map))))
  ;; (make-local-variable 'minor-mode-overriding-map-alist)
  (define-key newmap key def)))

(my-keys-minor-mode 1)

这可以做的是:

(define-key my-keys-minor-mode-map (kbd "C-i") 'backward-char)

定义高优先级键绑定而不是其他次要模式。

(add-hook 'text-mode-hook (lambda ()
    (my-keys-minor-mode-override (kbd "C-i") 'forward-char)))

暂时覆盖高优先级键绑定。