如何将您的键绑定到尚未加载的键映射?


9

use-package用来管理已安装的软件包,并将bind-key操作分配给我喜欢的自定义键。

我覆盖了大多数默认的Emacs键盘绑定(例如,C-n变为M-kC-p成为M-i),但是我可以接受其他模式来覆盖我的键盘绑定方案。有时,我希望我的键绑定继续存在。M-k除了默认的Gnus或Helm,我还想表达其他意思。

但是,它们在Emacs启动时彼此冲突,因为如果键映射不存在,我无法将其添加到该键映射中(因为use-package有时会延迟加载程序包)。例如,以下命令会引发错误(例如(void-variable helm-map)),因为Helm和Gnus尚未完全加载。

(bind-key "M-Y" 'helm-end-of-buffer helm-map)
(bind-key "M-k" 'helm-next-line helm-find-files-map)
(bind-key "M-s" 'other-window gnus-summary-mode-map)

我将所有use-package调用都放在一个文件中,并将bind-key自定义键绑定放在另一个文件中。我不想将绑定放入use-package调用中,因为也许我想将自定义键绑定方案发布为独立程序包。如果我希望安装我的方案的人也改写了Helm和Gnus本地键绑定,该怎么办?

我如何使用来管理本地模式的键绑定bind-key,以便即使最近装入程序包也设置所有键,并且所有键设置都在一个文件中?

Answers:


20

您可以使用with-eval-after-load延迟键绑定,直到加载了某个模块(从而定义了键映射)之后:

(with-eval-after-load "helm"
  (bind-key "M-Y" #'helm-end-of-buffer helm-map))

使用C-h v helm-map找出哪个模块的键盘映射表中定义,从而把该字符串中的第一行。


with-eval-after-load在Emacs 24.4中引入。如果您使用的是较早的Emacs版本,则需要eval-after-load改用,并在bind-key呼叫前加一个单引号:

(eval-after-load "helm"
  '(bind-key "M-Y" #'helm-end-of-buffer helm-map))

如果要以bind-key这种形式发出多个呼叫,with-eval-after-load只需将它们一个接一个地放置,但eval-after-load需要将它们全部包装在一个中progn

(eval-after-load "helm"
  '(progn
     (bind-key "M-Y" #'helm-end-of-buffer helm-map)
     (bind-key "M-k" #'helm-next-line helm-find-files-map)))

9

为了在给定的包被加载后执行的东西,你需要把那以后:configuse-package

这是在您的问题中使用摘要的示例:

片段1

(use-package helm
  :config
  (progn
    (bind-key "M-Y" #'helm-end-of-buffer helm-map)
    (bind-key "M-k" #'helm-next-line helm-find-files-map)))

(use-package gnus
  :config
  (bind-key "M-s" #'other-window gnus-summary-mode-map))

说明

可以在emacs init.el或加载/需要的任何嵌套文件中的不同位置放置以下2个摘要。

片段2

(use-package gnus)

片段3

(use-package gnus
  :config
  (bind-key "M-s" #'other-window gnus-summary-mode-map))

原因是,首先执行以上两个片段中的哪个片段都没有关系。

这就是为什么..下面是代码片段3扩展到的内容。

M-x pp-macroexpand-last-sexp当点(光标)在该代码段的最后一个右括号之后时,将得到以下结果。

摘要#4

(if (not (require 'gnus nil t))
    (ignore (message (format "Could not load %s" 'gnus)))
  (condition-case-unless-debug err
      (bind-key "M-s" #'other-window gnus-summary-mode-map)
    (error
     (ignore
      (display-warning 'use-package
                       (format "%s %s: %s" "gnus" ":config"
                               (error-message-string err))
                       :error))))
  t)

上面的代码段基本上意味着

  • gnus首先需要,然后bind-key执行表单。
  • 如果gnus未找到,则您将在* Messages *缓冲区中看到一条消息,指出无法加载该软件包。
  • 如果执行中有任何问题,将会抛出错误 (bind-key "M-s" #'other-window gnus-summary-mode-map)

同样,如果上面gnus代码片段2已要求该代码,并且代码片段3再次需要该消息,也没关系,因为require如果已经加载了软件包,则不会再次加载该软件包。


参考

从github 的use-package基础知识来看,

:config可以在加载包后用于执行代码。如果延迟进行加载(请参阅下面的有关自动加载的更多信息),则此执行将推迟到自动加载发生之后:

片段5

(use-package foo
  :init
  (setq foo-variable t)
  :config
  (foo-mode 1))

上面加载包之前执行:init(setq foo-variable t))部分。但是在该节被加载执行。 foo(foo-mode 1):config foo


3

与其他答案相反,我一直为此使用钩子:

(defun my-company-maps()
  (define-key company-active-map "\C-x\M-h" 'company-show-doc-buffer)
  (define-key company-active-map "\C-n" 'company-select-next)
  (define-key company-active-map "\C-p" 'company-select-previous)
  (define-key company-active-map "\C-h" 'delete-backward-char))

(add-hook 'company-mode-hook 'my-company-maps)

我也是,我认为这是首选的方式。
有意义的用户名

2

由于您已经在使用bind-key,因此直接参考bind-key.el

如果您希望键绑定覆盖所有可能也绑定相同键的次要模式,请使用“ bind-key *”形式:

(bind-key* "<C-return>" 'other-window)

要取消绑定键映射中的键(例如,要阻止您最喜欢的主模式更改不想在任何地方覆盖的绑定),请使用unbind-key:

(unbind-key "C-c x" some-other-mode-map)

如果当前未定义键映射,则最后一种形式会失效,因为some-other-mode-map尚未加载文件定义。因此,您可以将其放入use-packagefor some-other-mode(定义的包some-other-mode-map)中,或使用with-eval-after-load

(with-eval-after-load 'some-other-mode
  (unbind-key "C-c x" some-other-mode-map))

另一种选择是定义您自己的次要模式,其中包含不应被主要模式覆盖的所有绑定:

(defvar my-very-own-keymap (make-keymap) "my very own keymap.")

(define-key my-very-own-keymap (kbd "M-i") 'my-foo)

(define-minor-mode my-very-own-keys-minor-mode
  "Minor mode with my very own keybindings."
  t " my-own-keys" my-very-own-keymap)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.