代码之家  ›  专栏  ›  技术社区  ›  Brian Carper

全局覆盖Emacs中的键绑定

  •  92
  • Brian Carper  · 技术社区  · 16 年前

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

    这当然不行:

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

    它工作在 text-mode 但是当我使用 lisp-mode , C-i 反弹到 lisp-indent-line .

    我可以在 LISP模式 在每一种其他模式中,都是单独的,但必须有一种更简单的方法。每次我为新的文件类型安装一个新模式时,我都必须返回并检查以确保我的所有键绑定不会被新模式覆盖。

    我之所以要这样做,是因为我想模仿我已经从其他编辑器学习并根深蒂固的绑定。

    8 回复  |  直到 9 年前
        1
  •  140
  •   Stefan    9 年前

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

    (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)
    
        2
  •  30
  •   Community CDub    8 年前

    作为对 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))))
    
        3
  •  15
  •   Mirzhan Irkegulov    10 年前

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

    (require 'bind-key)
    (bind-key* "C-i" 'some-function)
    
        4
  •  13
  •   tshepang Arrie    10 年前

    我在搜索“Emacs Undefine组织模式键绑定”时发现了这个问题,因为我想解除现有的C-C C-B行为的绑定,以允许全局映射将缓冲区埋藏在组织缓冲区中。

    这是我最简单的解决方案:

    (add-hook 'org-mode-hook
          (lambda ()
            (local-unset-key (kbd "C-c C-b"))))
    
        5
  •  12
  •   Kirkland    15 年前

    尽管斯科特弗雷泽的回答正是你所要求的,但我会为子孙后代提出另一个解决方案。

    The Emacs Manual :

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

    如果您将您的个人全局绑定绑定到C-C加上一个字母,那么您“应该”是安全的。然而,这仅仅是一种约定,任何模式仍然能够覆盖您的绑定。

        6
  •  3
  •   Community CDub    8 年前

    如果您希望“始终使用映射中的键绑定,除非我为特定模式映射显式重写它们”,并假定您正在使用 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)
    

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

        7
  •  2
  •   T.E.D.    16 年前

    我觉得你做不到。这大致相当于您希望定义一个全局变量,该变量不能被函数中的局部变量声明隐藏。范围就是不能这样工作。

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

        8
  •  2
  •   JesperE    16 年前

    除非你真的想自己做这个,否则你应该四处看看,看看是否有其他人已经做过了。

    有一个Emacs包,它提供了类似于Windows的键绑定。你应该能通过谷歌找到它。