临时覆盖(全局覆盖 emacs 中的键绑定)
Override (globally override key binding in emacs) temporarily
我使用此处所述的方法: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)
如何明确覆盖它?
link 中的方法对我不起作用。
编辑2:
问题不仅适用于只读模式。 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% 的时间都有效,并且可以很好地防止任何其他次要模式或主要模式修改它。
但是,键映射在只读模式下有问题。所以我需要有 "super priority" 函数来重新映射这个键。我想要类似
的东西
(defun super-priority-map()
(define-key super-my-keys-minor-mode-map (kbd "<return>") 'something-else))
(add-hook 'some-modes 'super-priority-map)
更重要的是,只要离开指定模式,超级优先地图就会起飞。
您是在谈论 read-only 功能?您不能使用键盘映射覆盖它。没有 "read-only" 键盘映射捕获所有击键并发出错误。
要覆盖 read-only-mode
,只需关闭 read-only-mode
!
在代码中,设置 buffer-read-only
变量。
您还可以 let-bind 代码中的 inhibit-read-only
变量来忽略 所有 read-only 机制(包括特定文本区域的属性 - - 请参阅下面列表中的第 7 级和第 3 级。
Read-only 除了, 其他键盘映射完全有可能优先于您的次要模式映射,但我倾向于说对于任何罕见的冲突使用您的次要模式键映射,您应该直接修改与您自己的键映射冲突的键映射。
您的次要模式键盘映射实际上可以被许多其他键盘映射取代,但您可能通常不希望在更高的优先级上工作。
我建议阅读 Mastering Key Bindings in Emacs,这是对这些东西如何工作的非常易读的解释,我从中获得了以下键盘映射优先级列表:
overriding-terminal-local-map
terminal-specific 键绑定。
overriding-local-map
用于应覆盖所有其他本地键盘映射的键。使用这个时要非常小心!
Keymap
char 属性 at point for keymaps that is local to the character point is at.这用于 yasnippet 和自定义对话框中的字段之类的东西。
emulation-mode-map-alists
用于高级 multi-mode 键盘映射管理
minor-mode-overriding-map-alist
用于在主要模式中覆盖次要模式使用的键映射。
minor-mode-map-alist
与上面的覆盖版本完全相同,但是为次要模式指定键映射的首选方法。
Keymap
text 属性 点类似于上面的字符属性,但仅适用于文本属性。
current-local-map
用于在缓冲区的当前本地映射中定义的键映射
current-global-map
是 Emacs 查找键绑定的最后位置,它是全局键绑定的。
请注意,您的次要模式在级别 6 下工作,高于该级别的所有内容都可以优先。
解除冲突绑定的典型模式是:
(eval-after-load "NAME-OF-LIBRARY"
'(define-key NAME-OF-KEYMAP (kbd "KEY") nil)) ;; unbind KEY in KEYMAP implemented by LIBRARY
很可能,您还会 添加 原始命令的替换 (non-conflicting) 绑定。
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)))
临时覆盖高优先键绑定。
甜蜜
我使用此处所述的方法: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)
如何明确覆盖它? link 中的方法对我不起作用。
编辑2:
问题不仅适用于只读模式。 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% 的时间都有效,并且可以很好地防止任何其他次要模式或主要模式修改它。
但是,键映射在只读模式下有问题。所以我需要有 "super priority" 函数来重新映射这个键。我想要类似
的东西(defun super-priority-map()
(define-key super-my-keys-minor-mode-map (kbd "<return>") 'something-else))
(add-hook 'some-modes 'super-priority-map)
更重要的是,只要离开指定模式,超级优先地图就会起飞。
您是在谈论 read-only 功能?您不能使用键盘映射覆盖它。没有 "read-only" 键盘映射捕获所有击键并发出错误。
要覆盖 read-only-mode
,只需关闭 read-only-mode
!
在代码中,设置 buffer-read-only
变量。
您还可以 let-bind 代码中的 inhibit-read-only
变量来忽略 所有 read-only 机制(包括特定文本区域的属性 - - 请参阅下面列表中的第 7 级和第 3 级。
Read-only 除了, 其他键盘映射完全有可能优先于您的次要模式映射,但我倾向于说对于任何罕见的冲突使用您的次要模式键映射,您应该直接修改与您自己的键映射冲突的键映射。
您的次要模式键盘映射实际上可以被许多其他键盘映射取代,但您可能通常不希望在更高的优先级上工作。
我建议阅读 Mastering Key Bindings in Emacs,这是对这些东西如何工作的非常易读的解释,我从中获得了以下键盘映射优先级列表:
overriding-terminal-local-map
terminal-specific 键绑定。overriding-local-map
用于应覆盖所有其他本地键盘映射的键。使用这个时要非常小心!Keymap
char 属性 at point for keymaps that is local to the character point is at.这用于 yasnippet 和自定义对话框中的字段之类的东西。emulation-mode-map-alists
用于高级 multi-mode 键盘映射管理minor-mode-overriding-map-alist
用于在主要模式中覆盖次要模式使用的键映射。minor-mode-map-alist
与上面的覆盖版本完全相同,但是为次要模式指定键映射的首选方法。Keymap
text 属性 点类似于上面的字符属性,但仅适用于文本属性。current-local-map
用于在缓冲区的当前本地映射中定义的键映射current-global-map
是 Emacs 查找键绑定的最后位置,它是全局键绑定的。
请注意,您的次要模式在级别 6 下工作,高于该级别的所有内容都可以优先。
解除冲突绑定的典型模式是:
(eval-after-load "NAME-OF-LIBRARY"
'(define-key NAME-OF-KEYMAP (kbd "KEY") nil)) ;; unbind KEY in KEYMAP implemented by LIBRARY
很可能,您还会 添加 原始命令的替换 (non-conflicting) 绑定。
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)))
临时覆盖高优先键绑定。
甜蜜