次: , 前: Functions for Key Lookup, 上: Keymaps


21.9 キーバインディングの変更

キーを再バインドするには、キーマップにおける当該項目を変更します。 グローバルキーマップでバインディングを変更すると、 その変更はすべてのバッファで効果を発揮します (ただし、ローカルキーマップでグローバルバインディングを 隠しているバッファでは直接の効果はない)。 カレントバッファのローカルキーマップで変更すると、 通常、同じメジャーモードを使っているすべてのバッファに影響します。 関数global-set-keylocal-set-keyは、 これらの操作を行うための便利なインターフェイスです (see Key Binding Commands)。 より汎用の関数define-keyを使うこともできますが、 変更対象のキーマップを明示する必要があります。

キー列の再バインドを書くときには、 コントロール文字やメタ文字向けの 特別なエスケープシーケンスを使うのがよいです(see String Type)。 構文`\C-'は後続の文字がコントロール文字であること、 構文`\M-'は後続の文字がメタ文字であることを意味します。 したがって、文字列"\M-x"は単一のM-xを含むと読まれ、 "\C-f"は単一のC-fを含むと読まれ、 "\M-\C-x""\C-\M-x"はいずれも単一のC-M-xを 含むと読まれます。 同じエスケープシーケンスは、 ベクトルでも使え、文字列が許されない他の場面でも使えます。 たとえば、`[?\C-\H-x home]'です。 See Character Type

キーを定義したり探索する関数では、 ベクトルで表したキー列内のイベント型に対して別の構文、 つまり、修飾子名と1つの基本イベント(文字やファンクションキー名) から成るリストを受け付けます。 たとえば、(control ?a)?\C-aに等価であり、 (hyper control left)C-H-leftに等価です。 このようなリストの利点の1つは、 コンパイル済みのファイルに修飾ビットの数値が現れないことです。

以下の関数では、keymapがキーマップでなかったり、 keyがキー列を表す文字列やベクトルでないと、エラーを通知します。 リストであるイベントの省略形としてイベント型(シンボル)を使えます。

— 機能: define-key keymap key binding

この関数は、キーマップkeymapにおいて キーkeyに対するバインディングを設定する。 (keyが複数イベントの場合、 keymapから辿った別のキーマップが実際には変更される。) 引数bindingは任意のLispオブジェクトであるが、 ある種の型のものだけが意味を持つ。 (意味のある型の一覧については、Key Lookupを参照。) define-keyが返す値はbindingである。

keyのおのおののプレフィックスはプレフィックスキーである (キーマップにある)か未定義であること。 さもなければ、エラーを通知する。 keyのプレフィックスに未定義なものがあると、 define-keyは当該プレフィックスをプレフィックスキーと定義し、 keyの残りの部分を指定どおりに定義できるようにする。

keymapkeyのバインディングがなければ、 新たなバインディングをkeymapの先頭に追加する。 キーマップ内のバインディングの順序は多くの場合関係ないが、 メニューキーマップでは意味を持つ(see Menu Keymaps)。

疎なキーマップを作成し、そこにバインディングを作る例を示します。

     (setq map (make-sparse-keymap))
         => (keymap)
     (define-key map "\C-f" 'forward-char)
         => forward-char
     map
         => (keymap (6 . forward-char))
     
     
     ;; C-x用の疎なサブマップを作り、
     ;; そこにfのバインディングを入れる
     (define-key map "\C-xf" 'forward-word)
         => forward-word
     map
     => (keymap
         (24 keymap                ; C-x
             (102 . forward-word)) ;      f
         (6 . forward-char))       ; C-f
     
     
     ;; C-pctl-x-mapにバインドする
     (define-key map "\C-p" ctl-x-map)
     ;; ctl-x-map
     => [nil ... find-file ... backward-kill-sentence]
     
     
     ;; ctl-x-mapで、C-ffooにバインドする
     (define-key map "\C-p\C-f" 'foo)
     => 'foo
     map
     
     => (keymap     ; fooctl-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の両方のバインディングを変更する効果がある ことに注意してください。

— 機能: substitute-key-definition olddef newdef keymap &optional oldmap

この関数は、keymap内のolddefにバインドされたキーの olddefnewdefに置き換える。 いいかえると、olddefに出会うたびにそれをnewdefに置き換える。 関数はnilを返す。

たとえば、Emacsの標準のバインディングであると、 つぎの例はC-x C-fを再定義する。

          (substitute-key-definition
           'find-file 'find-file-read-only (current-global-map))
     

oldmapnil以外であると、 そのバインディングによってどのキーを再バインドするかを決定する。 再バインディングはkeymapで行い、oldmapではない。 つまり、別のキーマップ内のバインディングの制御のもとに、 キーマップを変更できる。 たとえば、

          (substitute-key-definition
            'delete-backward-char 'my-funny-delete
            my-map global-map)
     

では、グローバルには標準の削除コマンドにバインドされているキーに対しては、 my-mapでは特別な削除コマンドにする。

変更前後のキーマップを以下に示す。

          (setq map '(keymap
                      (?1 . olddef-1)
                      (?2 . olddef-2)
                      (?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))
     
— 機能: suppress-keymap keymap &optional nodigits

この関数は、完全なキーマップkeymapの内容を変更し、 すべての印字文字を未定義にする。 より正確には、それらにコマンドundefinedをバインドする。 これにより、通常のテキストの挿入を不可能にする。 suppress-keymapnilを返す。

nodigitsnilであると、 suppress-keymapは、 数字文字ではdigit-argumentを実行し、 -ではnegative-argumentを実行するように定義する。 さもなければ、それらも他の印字文字と同様に未定義にする。

関数suppress-keymapは、 yankquoted-insertなどのコマンドを抑制しないので、 バッファを変更不可能にするわけではない。 バッファの変更を禁止するには、バッファを読み出し専用にする (see Read Only Buffers)。

この関数はkeymapを変更するため、 読者は、通常、新たに作成したキーマップに対して使うであろう。 ある目的で使用中の既存のキーマップを操作すると、 問題を引き起こすことがある。 たとえば、global-mapに適用するとEmacsをほとんど使用不能にしてしまう。

多くの場合、テキストの挿入が必要なくバッファを読み出し専用で使う rmailやdiredなどのモードのローカルキーマップの初期化に suppress-keymapを使う。 ファイルemacs/lisp/dired.elから持ってきた例を示す。 これは、diredモード用のローカルキーマップの設定方法である。

          (setq dired-mode-map (make-keymap))
          (suppress-keymap dired-mode-map)
          (define-key dired-mode-map "r" 'dired-rename-file)
          (define-key dired-mode-map "\C-d" 'dired-flag-file-deleted)
          (define-key dired-mode-map "d" 'dired-flag-file-deleted)
          (define-key dired-mode-map "v" 'dired-view-file)
          (define-key dired-mode-map "e" 'dired-find-file)
          (define-key dired-mode-map "f" 'dired-find-file)
          ...