Next: , Previous: , Up: キーマップ   [Contents][Index]


23.4 キーマップの作成

以下はキーマップを作成する関数です。

Function: make-sparse-keymap &optional prompt

この関数はエントリーをもたない新たなsparseキーマップを作成してそれをリターンする(sparseキーマップはあなたが通常望む類のキーマップのこと)。make-keymapと異なり新たなキーマップは文字テーブルを含まず、何のイベントもバインドしない。

(make-sparse-keymap)
    ⇒ (keymap)

promptを指定すると、それはキーマップにたいするoverallプロンプト文字列になる。これはメニューキーマップ(メニューの定義を参照)にたいしてのみ指定すべきである。overallプロンプト文字列をともなうキーマップがアクティブなら、次の入力イベントのルックアップにたいしてマウスメニューとキーボードメニューを常に提示する。これはコマンドループにたいして毎回キーボードメニューを提示するので、overallプロンプト文字列をメインマップ、メジャーモードマップ、マイナーモードマップに指定しないこと。

Function: make-keymap &optional prompt

この関数は新たなfullキーマップを作成してそれをリターンする。このキーマップは修飾されないすべての文字にたいするスロットをもつ文字テーブル(文字テーブルを参照)を含む。この新たなキーマップは初期状態ではすべての文字、およびその他の種類のイベントがnilにバインドされている。引数promptmake-sparse-keymapのようにプロンプト文字列を指定する。

(make-keymap)
    ⇒ (keymap #^[nil nil keymap nil nil nil …])

fullキーマップは多くのスロットを保持するときはsparseキーマップより効果的であり、少ししかスロットを保持しないときはsparseキーマップのほうが適している。

Function: define-keymap &key options... &rest pairs...

上述した関数によってキーマップを作成してから、keymap-set (キーバインディングの変更を参照)を使用してそのマップ内のキーバインディングを指定する。ただしモードを記述する際には一度に大量のキーのバインドを要することが頻繁にあるため、keymap-setを使用してそれらすべてをバインドするのは面倒かもしれないしエラーも起きやすいだろう。かわりにキーマップの作成と複数のキーのバインドを行うdefine-keymapを使うことができる。基本的な例を以下に示す:

(define-keymap
  "n" #'forward-line
  "f" #'previous-line
  "C-c C-c" #'quit-window)

この関数はpairs内のキーストロークを定義するsparseキーマップを新たに作成して、そのキーマップをリターンする。pairs内に重複したキーバインディングがあればエラーをシグナルする。

pairskeymap-setが受け入れるようなキーバインディングとキー定義が交互に指定されたリスト。更にキーは特別なシンボル:menuでもよい。この場合には、定義easy-menu-define (easy-menuを参照)が許容するようなメニュー定義であること。以下は使い方を示す簡単な例:

(define-keymap :full t
  "g" #'eww-reload
  :menu '("Eww"
          ["Exit" quit-window t]
          ["Reload" eww-reload t]))

新たなキーマップの機能を変更するために、キー/定義のペアーの前にいくつかのキーワードを使うことができる。define-keymapの呼び出しに含まれていないキーワードの機能にたいするデフォルト値はnil。利用可能な機能キーワードは以下のとおり:

:full

nilなら(make-sparse-keymapが作成するような)sparseキーマップのかわりに、(make-keymapが作成するような)文字テーブルキーマップを作成する(キーマップの作成を参照)。デフォルトはsparseキーマップ。

:parent

nilなら値は親として使用するキーマップであること(継承とキーマップを参照)。

:keymap

nilなら、値はキーマップであること。新たにキーマップを作成するかわりに指定されたキーマップを変更する。

:suppress

nilなら、そのキーマップはsuppress-keymapによって抑制される(キーバインディングの変更を参照)。デフォルトでは数字とマイナス記号は抑制から除外されるが、値がnodigitsなら他の文字と同様に数字とマイナス記号も抑制する。

:name

nil、かつx-popup-menu (ポップアップメニューを参照)によるメニューとして使用する場合には、値をメニューとして使用するような文字列にする必要がある。

:prefix

nilなら、値はプレフィックスコマンドとして使用するシンボルであること(プレフィクスキーを参照)。この場合にはマップ自体ではなく、このシンボルがdefine-keymapによってリターンされる。

Macro: defvar-keymap name &key options... &rest pairs...

キーマップでもっとも一般的に行われるのは専ら変数へのバインドであろう。これはほぼすべてのモードが行っていることであり、fooと呼ばれるモードにはほとんど常にfoo-mode-mapと呼ばれる変数が存在する。

このマクロはnameを変数として定義して、optionspairsdefine-keymapに渡した結果をその変数のデフォルト値として使用する。pairs内に重複したキーバインディングがあればエラーをシグナルする。

optionsdefine-keymapにおけるキーワードと同様だが、定義される変数にたいしてdoc文字列を提供するためのキーワード:docが追加されている。

以下は例:

(defvar-keymap eww-textarea-map
  :parent text-mode-map
  :doc "Keymap for the eww text area."
  "RET" #'forward-line
  "TAB" #'shr-next-link)

キーマップ内のコマンドはそれぞれrepeat-mapプロパティを配置することによって、(repeat-modeで便利なように)‘repeatable(繰り返し可能)’とマークすることができる、たとえば

(put 'undo 'repeat-map 'undo-repeat-map)

repeat-modeによって使用されるマップがこのプロパティになる。

putを繰り返し呼び出すことを避けるためのキーワードとして、defvar-keymapには:repeatがある。このキーワードを使えばキーマップのどのコマンドがrepeat-modeで使用可能かを指定できる。使用できる値は以下のとおり:

t

キーマップのすべてのコマンドが繰り返し可能ということを意味する。もっとも一般的な使い方。

(:enter (commands ...) :exit (commands ...))

:enterリストにあるコマンドでrepeat-modeにエンター、:exitリストにあるコマンドでrepeatモードからexitすることを指定する。

:enterリストが空の場合には、そのマップのすべてのコマンドがrepeat-modeにエンターする。このリストに1つ以上のコマンドを指定しておけば、定義しているマップには存在しないものの、repeat-mapプロパティをもつべきコマンドがある場合に役に立つだろう。

:exitリストが空なら、そのマップにおいてrepeat-modeをexitするコマンドは存在しない。このリストに1つ以上のコマンドを指定しておけば、定義しているマップにrepeat-mapプロパティをもつべきではないコマンドが含まれる場合に役に立つだろう。

たとえばuundoコマンドを繰り返す場合には、以下の2節は等価である:

(defvar-keymap undo-repeat-map
  "u" #'undo)
(put 'undo 'repeat-map 'undo-repeat-map)

または

(defvar-keymap undo-repeat-map
  :repeat t
  "u" #'undo)

マップに多くのコマンドがあり、それらすべてを繰り返し可能にする必要がある場合には後者を使うほうがよいだろう。

Function: copy-keymap keymap

この関数はkeymapのコピーをリターンする。これはほとんど必要ないだろう。ほとんど差のないキーマップが必要なら、コピーより以下のように継承を使用するべきである:

(let ((map (make-sparse-keymap)))
  (set-keymap-parent map <theirmap>)
  (keymap-set map ...)
  ...)

copy-keymapを処理する際には、keymap内でバインディングとして直接出現するすべてのキーマップも、すべてのレベルまで再帰的にコピーされる。しかしある文字の定義が関数定義にキーマップをもつ関数のときには再帰的なコピーは行われず、新たにコピーされたキーマップには同じシンボルがコピーされる。

(setq map (copy-keymap (current-local-map)))
⇒ (keymap
     ;; (これはメタ文字を実装する)
     (27 keymap
         (83 . center-paragraph)
         (115 . center-line))
     (9 . tab-to-tab-stop))

(eq map (current-local-map))
    ⇒ nil
(equal map (current-local-map))
    ⇒ t

Next: 継承とキーマップ, Previous: キーマップのフォーマット, Up: キーマップ   [Contents][Index]