ChatGPT解决这个技术问题 Extra ChatGPT

在 Emacs 中全局覆盖键绑定

如何设置全局覆盖并优先于该键的所有其他绑定的键绑定?我想覆盖所有主要/次要模式映射并确保我的绑定始终有效。

这当然行不通:

(global-set-key "\C-i" 'some-function)

它在 text-mode 中有效,但是当我使用 lisp-mode 时,C-i 会反弹到 lisp-indent-line

我可以在 lisp-mode 和其他所有模式中单独遍历并覆盖此绑定,但必须有更简单的方法。每次我为新文件类型安装新模式时,我都必须返回并检查以确保我的所有键绑定都没有被新模式覆盖。

我想这样做是因为我想模仿我已经从其他编辑器那里学到并根深蒂固的绑定。

emacs.stackexchange.com/questions/352/… 处的后续重复项进行交叉引用

S
Stefan

我对所有“覆盖”键绑定使用次要模式:

(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."
  :init-value t
  :lighter " my-keys")

(my-keys-minor-mode 1)

这还有一个额外的好处,就是能够一举关闭我的所有修改(只需禁用次要模式),以防其他人正在驱动键盘,或者如果我需要查看默认键绑定的作用。

请注意,您可能需要在 minibuffer 中将其关闭:

(defun my-minibuffer-setup-hook ()
  (my-keys-minor-mode 0))

(add-hook 'minibuffer-setup-hook 'my-minibuffer-setup-hook)

这似乎是个好主意。有什么方法可以确保您的次要模式不会与其他次要模式发生冲突?
确保您的次要模式首先在列表次要模式映射列表中。
特雷是对的。通常把它放在 .emacs 的末尾就足够了。此外,您要覆盖的大多数绑定都是主要模式正在设置的绑定......次要模式通常不会妨碍您。
我遵循了这种方法,但后来我意识到我绑定到 Ci 的任何东西也会绑定到 TAB 键。有什么建议么?
Brian Carper:这是处理后续加载的次要模式的增强功能:stackoverflow.com/questions/683425/…
C
Community

作为 scottfrazer's answer 的补充,我编写了以下内容,以便我的键绑定保持优先级,即使随后加载的库引入了它们自己的新键映射。

因为可以在编译时生成键映射,所以 load 似乎是执行此操作的最佳位置。

(add-hook 'after-load-functions 'my-keys-have-priority)

(defun my-keys-have-priority (_file)
  "Try to ensure that my keybindings retain priority over other minor modes.

Called via the `after-load-functions' special hook."
  (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))))

我粘贴了您的脚本,但没有任何影响:(
@alper 我建议您发布一个包含所有相关详细信息的问题,包括您实际使用的代码,以及重现问题的特定示例/配方。
M
Mirzhan Irkegulov

安装 use-package,eval 就完成了:

(require 'bind-key)
(bind-key* "C-i" 'some-function)

只安装 bind-key 就足够了,尽管 use-package 依赖于 bind-key。
这个('bind-key'包)似乎是最方便的解决方案;感谢分享。
它在 minibuffer-setup-hook 上被禁用了吗?
t
tshepang

我在搜索“emacs undefine org mode keybindings”时发现了这个问题,因为我想取消绑定现有的 Cc Cb 行为以允许我的全局映射埋入缓冲区以在 org 缓冲区中工作。

这最终成为我最简单的解决方案:

(add-hook 'org-mode-hook
      (lambda ()
        (local-unset-key (kbd "C-c C-b"))))

这是特定于模式的,即使它确实适用于您的单个用例,也不能解决更大的问题。
K
Kirkland

尽管 scottfrazer 的答案正是您所要求的,但我会为后代提及另一种解决方案。

The Emacs Manual

“不要将 Cc 字母定义为 Lisp 程序中的键。由 Cc 和字母(大写或小写)组成的序列是为用户保留的;它们是为用户保留的唯一序列,所以不要阻止它们。”

如果您将您的个人全局绑定绑定到 Cc 加一个字母,那么您“应该”是安全的。但是,这只是一个约定,任何模式仍然可以覆盖您的绑定。


我没想到 org-mode,在所有模式中,都会打破这个规则。 `Cc Ch' 告诉我 Cc a、b、c 和 l 分别绑定到 org-agenda、org-iswitchb、org-capture 和 org-store-link。
Afaik,绑定这些是 org-mode 建议使用它的第一步,但用户必须自己定义它们(即默认情况下不完成),并且可以在这样做时选择任何其他。 (另外,这是因为这些绑定应该是全局的,而不是绑定到 org 主要模式)
C
Community

如果您想“始终使用映射中的键绑定,除非我为特定模式映射显式覆盖它们”,并假设您使用的是 scottfrazier's approach,您希望:

(defun locally-override (key cmd)
  (unless (local-variable-p 'my-keys-minor-mode-map)
    (set (make-variable-buffer-local 'my-keys-minor-mode-map)
         (make-sparse-keymap))
    (set-keymap-parent my-keys-minor-mode-map 
                       (default-value 'my-keys-minor-mode-map)))
  (define-key my-keys-minor-mode-map key cmd))

所以

(locally-override "\C-i" nil)

应该只从当前缓冲区的次要模式中删除“\Ci”绑定。警告:这完全未经测试,但似乎是正确的方法。设置父级而不是仅仅处理 my-keys-minor-mode-map 的全局值的重点是,以后对全局值的任何更改都会自动反映在本地值中。


T
T.E.D.

我不认为你可以。这大致相当于说要定义一个不能被函数中的局部变量声明隐藏的全局变量。范围只是不那样工作。

但是,可能有一种方法可以编写一个 elisp 函数来遍历模式列表,并为您在每个模式列表中重新分配它。


这种范围界定的想法在技术上是正确的,但 overriding-local-map 是专门为覆盖所有其他地图而设计的。但是使用它是危险的。
J
JesperE

除非你真的想自己做,否则你应该检查一下,看看其他人是否已经做过。

有一个适用于 Emacs 的包,它为您提供类似 Windows 的键绑定。你应该可以通过谷歌找到它。


您正在考虑的包可能是 cua-mode
是的,就是这个包。
c
c4710n

在 Emacs 27 中,有 override-global-map。然后,您可以执行以下操作: (define-key override-global-map (kbd "Mh") 'backward-kill-word)

这个答案不对,不好意思。


该键映射在哪里定义?
抱歉,这个键映射是由 Emacs 中不包含的 bind-key 包定义的。我会在我的帖子中声明它。

关注公众号,不定期副业成功案例分享
关注公众号

不定期副业成功案例分享

领先一步获取最新的外包任务吗?

立即订阅