まだロードされていないキーマップにキーをバインドする方法は?


9

use-packageインストールしたパッケージを管理しbind-keyたり、好きなカスタムキーにアクションを割り当てたりするために使用しています。

デフォルトのEmacsキーバインドのほとんどをオーバーライドします(たとえば、にC-nなるM-k、にC-pなるM-i)が、キーバインドスキームをオーバーライドする他のモードでも問題ありません。ただし、キーバインドを永続化したい場合もあります。私がしたいM-kデフォルトのGnusやヘルムよりも他の平均何かを、。

ただし、キーマップが存在しない場合はバインドを追加できないため(use-packageパッケージの読み込みが遅れることがあるため)、Emacsの起動時にすべてが競合します。たとえば、(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呼び出しが1つのファイルにありbind-key、カスタムキーバインドの別のファイルにあります。use-packageカスタムキーバインドスキームをスタンドアロンパッケージとして公開する可能性があるため、バインディングを呼び出しに含めたくありません。私のスキームをインストールする誰かにHelmとGnusのローカルキーバインドもオーバーライドさせたい場合はどうなりますか?

bind-keyパッケージを最近ロードした場合でもすべてのキーが設定され、すべてのキー設定が1つのファイル内にあるように、を使用してモードローカルキーバインドを管理するにはどうすればよいですか?

回答:


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-loadEmacs 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で、すべてをaでラップする必要があります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

解決

与えられたパッケージがロードされた後に何かを実行するために、あなたはそれを後:configに置く必要がありますuse-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))

説明

以下の2つのスニペットを、emacs内のさまざまな場所、init.elまたはロード/必須のネストされたファイルのいずれかに配置しても問題ありません。

スニペット#2

(use-package gnus)

スニペット#3

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

その理由は、上記の2つのスニペットのどちらが最初に実行されるかは問題ではないためです。

ここに理由があります。以下は、スニペット#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)

また、上記のSnippet#2でgnusすでに必要であり、Snippet#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.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)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.