既存のキーバインドを置き換える(remap, substitute-key-definition)
既存のコマンドを置き換えるコマンドを自作した際、新しいキーバインドを作るのではなくそのコマンドで古い コマンドを置き換えたい時があります。その際、具体的に「元々どこにバインドされていたか」を調べずに置き 換えることが可能なのでメモを残しておきます。
アクティブなキーマップ上のコマンドを置き換えたい: remapキーイベント + define-key
remap
キーイベントを使うと、新たにremapを行うキーバインドを作成出来ます。注意点として、
実際に置き換えるのではなく「アクティブなキーマップ上のコマンドを置き換えるキーバインド」を新たに作成
する 形になっています。そのため、指定したキーマップから参照されている Prefix keymap中にあるものは置
き換わりません。
つまり、以下のようなキーマップの構成を考えた時、 remap
を使って置き換えようとすると、 outer-map
に存在する func
は new-func
で置き換えられますが inner-map
に存在する func
はそのまま残りま
す:
(let* ((func '(lambda () (interactive) (message "inner-map default")))
(new-func '(lambda () (interactive) (message "replaced")))
(inner-map '(keymap (?1 . func)))
(outer-map `(keymap (?a . func) (?b . ,inner-map))))
(define-key outer-map [remap func] 'new-func)
(describe-keymap outer-map)
)
指定のキーマップから参照される Prefix keymap 内でも変更したい: substitute-key-definition
elisp:substitute-key-definition は、「既存のコマンド」「新しいコマンド」「対象のキーマップ」の3つを 必須の引数として受け取り、「対象のキーマップ」の中にある「既存のコマンド」を「新しいコマンド」で置き 換えるように作用します。
例えば、以下の例ではglobal keymap中の count-words-region
を自作のコマンド
org-count-words/subtree-if-no-region
で置き換えます。
(substitute-key-definition 'count-words-region 'org-count-words/subtree-if-no-region (current-global-map))
(ちなみに org-count-words/subtree-if-no-region
は私のdotfilesにあります)
substitute-key-definition
は、指定したキーマップだけでなく Prefixキーマップ内にあるキーバインドも
置き換えます。つまり、
(let* ((func '(lambda () (interactive) (message "inner-map default")))
(new-func '(lambda () (interactive) (message "replaced")))
(inner-map '(keymap (?1 . func)))
(outer-map `(keymap (?a . func) (?b . ,inner-map))))
(substitute-key-definition 'func 'new-func outer-map)
(describe-keymap outer-map)
)
KEYMAP\ OBJECT\ \(no\ variable\)\ 11
は以下のような表示が出るはずです
key binding --- ------- a new-func b Prefix Command b 1 new-func
「既存のコマンドを置き換えるキーマップを作りたい」: substitute-key-definition
(2)
substitute-key-definition
に OLDMAP
引数も加えてあげると、「 OLDMAP
上の「既存のコマンド」のキー
バインド」を参考にして「対象のキーマップ」を更新します。つまり、先程の例を元に以下のようにすると:
(substitute-key-definition 'count-words-region 'org-count-words/subtree-if-no-region (current-local-map) (current-global-map))
現在の global keymap 中の count-words-region
(デフォルトでは \M-=
)を置き換える代わりに、
local keymap の同じキーバインド(デフォルトなら \M-=
)に count-words-region
を設定します。