web-dev-qa-db-ja.com

Emacsでキーバインドをグローバルにオーバーライドする

グローバルにオーバーライドし、そのキーの他のすべてのバインディングより優先するキーバインディングを設定するにはどうすればよいですか?すべてのメジャー/マイナーモードマップをオーバーライドし、バインディングが常に有効であることを確認します。

もちろんこれは機能しません:

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

text-modeで動作しますが、LISP-modeを使用すると、C-iLISP-indent-lineにリバウンドされます。

LISP-modeおよび他のすべてのモードで個別にこのバインディングをオーバーライドできますが、もっと簡単な方法が必要です。新しいファイルタイプに新しいモードをインストールするたびに、すべてのキーバインディングが新しいモードによってオーバーライドされていないことを確認するために戻って確認する必要があります。

これは、他のエディターから既に学び、染み込ませたバインディングをエミュレートしたいので、これをしたいです。

97
Brian Carper

すべての「オーバーライド」キーバインディングにマイナーモードを使用します。

(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)

これには、他の誰かがキーボードを操作している場合、またはデフォルトのキーバインディングが何をするかを確認する必要がある場合に、すべての変更を一気にオフにすることができるという利点があります(マイナーモードを無効にするだけです)。

ミニバッファでこれをオフにする必要があるかもしれないことに注意してください:

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

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

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))))
30
phils

インストール use-package 、eval、完了です:

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

「emacs undefine org mode keybindings」の検索中にこの質問を見つけました。これは、既存のC-c C-b動作をアンバインドして、組織マップでグローバルマップをbury-bufferできるようにしたかったためです。

これは私にとって最も簡単な解決策になりました:

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

スコットフレイザーの答えはまさにあなたが求めたものですが、私は後世のために別の解決策に言及します。

から Emacsマニュアル

「C-c文字をLISPプログラムのキーとして定義しないでください。C-cと文字(大文字または小文字)で構成されるシーケンスはユーザー用に予約されています。ユーザー用に予約されている唯一のシーケンスなので、ブロックしないでください。」

個人的なグローバルバインディングをC-cと文字にバインドする場合、安全である必要があります。ただし、これは単なる規則であり、どのモードでもバインディングをオーバーライドできます。

12
Kirkland

「マップでキーバインドを常に使用し、特定のモードマップでキーバインドを明示的にオーバーライドしない限り」、そして scottfrazierのアプローチ を使用していると仮定すると、次のようになります。

(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」バインディングを削除する必要があります。警告:これは完全にテストされていませんが、正しいアプローチのようです。 my-keys-minor-mode-mapのグローバル値を単に処理するのではなく、親を設定するポイントは、グローバル値へのその後の変更がローカル値に自動的に反映されるようにするためです。

3
gbrunick

本当に自分でこれを行いたい場合を除き、他の誰かがすでにそれを行っているかどうかを確認してください。

Emacsには、ウィンドウのようなキーバインドを提供するパッケージがあります。あなたはグーグルを介してそれを見つけることができるはずです。

2
JesperE

できるとは思わない。これは、関数のローカル変数宣言で隠せないグローバル変数を定義したいということとほぼ同じです。スコープはそのようには機能しません。

ただし、elisp関数を作成して、モードリストを調べて、すべての関数リストに再割り当てする方法があるかもしれません。

2
T.E.D.