キーの再バインドを行うには、キーマップ内のエントリを変更します。グローバルキーマップのバインドを変更すると、その変更はすべてのバッファに適用されます(ただし、ローカルなバインドでグローバルバインドをシャドウしているバッファには直接的な影響はありません)。現在のバッファのローカルマップを変更すると、通常は同じメジャーモードを使用しているすべてのバッファに影響が及びます。keymap-global-set および keymap-local-set 関数は、これらの操作に便利なインターフェースです(キーバインド用コマンドを参照してください)。また、より汎用的な関数である
keymap-set
を使用することもできますが、その場合は変更対象のマップを明示的に指定する必要があります。
Lispプログラムで再バインドするキーシーケンスを選択する際は、各種キーの使用に関するEmacsの規約に従ってください(キーバインドの規約を参照)。
以下の関数は、keymap がキーマップでない場合、または key が有効なキーでない場合にエラーを通知します。
key は、単一のキーまたは一連のキーストロークを表す文字列であり、key-valid-p を満たす必要があります。 キーストロークは単一のスペース文字で区切られます。
各キー入力は、単一の文字か、あるいは山括弧で囲まれたイベント名のいずれかです。また、任意のキー入力の前には、1つ以上の修飾キーを置くことができます。最後に、限られた数の文字には特別な短縮構文が用意されています。以下にキーシーケンスの例をいくつか挙げます:
キー f。
キー S、o、m の3つのキーからなるシーケンス。
コントロール修飾子を伴うキー c と、それに続くキー o という2つのキーのシーケンス
ハイパー修飾子が付いた LEFT という名前のキー。
メタ修飾子付きの RET または Return キー。
コントロール修飾子とメタ修飾子の両方が付いた SPC キー。
特殊な短縮記法を持つキーは、NUL、RET、TAB、LFD、ESC、SPC、DELのみです。
修飾子はアルファベット順に指定する必要があります:‘A-C-H-M-S-s’、つまり‘Alt-Control-Hyper-Meta-Shift-super’です。
この関数は、keymap における key
のバインディングを設定します。引数 key は、key-valid-p を満たす文字列である必要があります(キーシーケンス を参照)。引数 binding
には任意の Lisp オブジェクトを指定できますが、意味を持つのは特定の型のみです。(意味を持つ型の一覧については、キールックアップ を参照してください。)keymap-set が返す値は binding です。
key
のすべてのプレフィックスは、プレフィックスキー(すなわちキーマップにバインドされているもの)であるか、あるいは未定義である必要があります。そうでない場合はエラーが通知されます。key の何らかのプレフィックスが未定義である場合、keymap-set がそれをプレフィックスキーとして定義することで、key の残りの部分を仕様通りに定義できるようになります。
keymap に key のバインディングが以前は存在しなかった場合、新しいバインディングは keymap の先頭に追加されます。キーマップにおけるバインディングの順序は、キーボード入力では影響しませんが、メニューキーマップでは重要になります(メニューキーマップ を参照)。
この関数は keymap-set の逆の動作を行い、keymap における key のバインディングを解除します。これは
nil
にバインディングを設定することと同等です。代わりにバインディングを完全に削除するには、remove を
non-nil として指定してください。この違いが生じるのは、keymap
に親キーマップがある場合のみです。子マップで単にキーのバインディングを解除しても、親キーマップにある同じキーは引き続きシャドウイングされます。代わりに
remove を使用すれば、親キーマップのキーを利用できるようになります。
注:keymap-unset を remove や
nil 以外のキーと併用するのは、ユーザーが init
ファイルに記述することを想定したものです。Emacs
パッケージは、そもそも自前のキーマップを完全に制御できるため、可能な限りこの用法を避けるべきであり、他のパッケージのキーマップを変更すべきではありません。
この例では、疎なキーマップを作成し、そこに複数のバインディングを設定します:
(setq map (make-sparse-keymap))
⇒ (keymap)
(keymap-set map "C-f" 'forward-char)
⇒ forward-char
map
⇒ (keymap (6 . forward-char))
;; Build sparse submap for C-x and bind f in that.
(keymap-set map "C-x f" 'forward-word)
⇒ forward-word
map
⇒ (keymap
(24 keymap ; C-x
(102 . forward-word)) ; f
(6 . forward-char)) ; C-f
;; Bind C-p to thectl-x-map. (keymap-set map "C-p" ctl-x-map) ;;ctl-x-map⇒ [nil ... find-file ... backward-kill-sentence]
;; Bind C-f to foo in the ctl-x-map.
(keymap-set map "C-p C-f" 'foo)
⇒ 'foo
map
⇒ (keymap ; Note foo in ctl-x-map.
(16 keymap [nil ... foo ... backward-kill-sentence])
(24 keymap
(102 . forward-word))
(6 . forward-char))
なお、C-p C-f に新しいバインディングを格納すると、実際には ctl-x-map のエントリが変更され、これによりデフォルトのグローバルマップにおける C-p C-f と C-x C-f
両方のバインディングが変更される点に注意してください。
keymap-set
は、キーマップでキーを定義する際の汎用的な手段です。しかし、モードを記述する際には、一度に多数のキーをバインドする必要があることが多く、すべてに
keymap-set を使用すると煩雑でミスが発生しやすくなります。代わりに define-keymap を使用すれば、キーマップを作成して複数のキーをバインドできます。詳細は キーマップの作成 を参照してください。
関数 substitute-key-definition
は、キーマップの中から特定のバインドを持つキーをスキャンし、それらを別のバインドに再バインドします。より簡潔で、多くの場合同様の結果が得られるもう一つの機能として、あるコマンドを別のコマンドにリマップする方法があります(コマンドのリマッピングを参照)。
この関数は、keymap 内で olddef
にバインドされていたすべてのキーについて、olddef を newdef に置き換えます。言い換えれば、olddef
が現れる箇所はすべて newdef に置き換えられます。この関数は nil を返します。
例えば、標準バインディングが設定されたEmacsでこれを行うと、C-x C-fが再定義されます:
(substitute-key-definition 'find-file 'find-file-read-only (current-global-map))
oldmap が nil でない場合、substitute-key-definition の動作が変わります。具体的には、oldmap のバインディングによって、どのキーを再バインドするかが決定されます。再バインドは依然として oldmap ではなく keymap
で行われます。したがって、あるマップを、別のマップのバインディング制御下で変更することが可能です。例えば、
(substitute-key-definition 'delete-backward-char 'my-funny-delete my-map global-map)
標準の削除コマンドにグローバルにバインドされているキーに対し、my-map
に特殊な削除コマンドを設定します。
置換前後のキーマップを示す例を以下に挙げます。
(setq map (list 'keymap
(cons ?1 olddef-1)
(cons ?2 olddef-2)
(cons ?3 olddef-1)))
⇒ (keymap (49 . olddef-1) (50 . olddef-2) (51 . olddef-1))
(substitute-key-definition 'olddef-1 'newdef map) ⇒ nil
map ⇒ (keymap (49 . newdef) (50 . olddef-2) (51 . newdef))
この関数は、self-insert-command をコマンド undefined に再マッピングすることで、キーマップ keymap 全体の内容を変更します(コマンドの再マッピング
を参照)。これにより、すべての印字文字が未定義となり、通常のテキスト挿入が不可能になります。suppress-keymap は nil を返します。
nodigits が nil である場合、suppress-keymap は digit-argument を、- は negative-argument
を実行するための数字を定義します。そうでない場合は、他の印字文字と同様に、それらは未定義となります。
suppress-keymap 関数は、yank
や quoted-insert
といったコマンドを抑制しないため、バッファの変更が不可能になるわけではありません。バッファの変更を一切禁止するには、読み取り専用にしてください(読み取り専用バッファ を参照)。
この関数は keymap
を変更するため、通常は新しく作成したキーマップに対して使用します。他の目的で使用されている既存のキーマップに対して操作を行うと、問題が発生する可能性が高くなります。例えば、global-map を抑制すると、Emacs の大部分が利用できなくなります。
この関数は、テキストの挿入が望ましくないメジャーモードのローカルキーマップを初期化するために使用できます。ただし、通常このようなモードは special-mode から派生させるべきであり(基本メジャーモード を参照)、その場合、キーマップはすでに抑制されている special-mode-map を自動的に継承します。special-mode-map の定義は以下の通りです。
(defvar special-mode-map
(let ((map (make-sparse-keymap)))
(suppress-keymap map)
(keymap-set map "q" 'quit-window)
...
map))