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


23.15 イベントシーケンス変換のためのキーマップ

read-key-sequence関数がキーシーケンス(キーシーケンス入力を参照)を読み取るときには、特定のイベントシーケンスを他のものに変換(translate)するために変換キーマップ(translation keymaps)を使用します。input-decode-maplocal-function-key-mapkey-translation-map(優先順)は変換キーマップです。

変換キーマップは他のキーマップと同じ構造をもちますが使い方は異なります。変換キーマップはキーシーケンスを読み取るときに、コンプリートキーシーケンスにたいするバインディングではなくキーシーケンスに行う変換を指定します。キーシーケンスが読み取られると、それらのキーシーケンスは変換キーマップにたいしてチェックされます。ある変換キーマップがkをベクターvにバインドするなら、キーシーケンス内のどこかにサブシーケンスとしてkが出現すると、それはv内のイベントに置き換えられます。

たとえばキーパッドキーPF1が押下されたとき、VT100端末はESC O Pを送信します。そのような端末ではEmacsはそのイベントシーケンスを単一イベントpf1に変換しなければなりません。これはinput-decode-map内でESC O P[pf1]にバインドすることにより行われます。したがってその端末上でC-c PF1をタイプしたとき、端末は文字シーケンスC-c ESC O Pを発行して、read-key-sequenceがそれをC-c PF1に変換、ベクター[?\C-c pf1]としてリターンします。

変換キーマップは、(keyboard-coding-systemで指定された入力コーディングシステムを通じて)Emacsがキーボード入力をデコードした直後だけ効果をもちます。端末I/Oのエンコーディングを参照してください。

Variable: input-decode-map

この変数は通常の文字端末上のファンクションキーから送信された文字シーケンスを記述するキーマップを保持する。

input-decode-mapの値は、通常はその端末のTerminfoかTermcapのエントリーに応じて自動的にセットアップされるが、Lispの端末仕様ファイルの助けが必要なときもある。Emacsには一般的な多くの端末の端末仕様ファイルが同梱されている。これらのファイルの主な目的はTermcapやTerminfoから推定できないエントリーをinput-decode-map内に作成することである。端末固有の初期化を参照のこと。

Variable: local-function-key-map

この変数はinput-decode-mapと同じようにキーマップを保持するが、通常は優先される解釈選択肢(alternative interpretation)に変換されるべきキーシーケンスを記述するキーマップを保持する。このキーマップはinput-decode-mapの後、key-translation-mapの前に適用される。

local-function-key-map内のエントリーはマイナーモード、ローカルキーマップ、グローバルキーマップによるバインディングと衝突する場合には無視される。つまり元のキーシーケンスが他にバインディングをもたない場合だけリマッピングが適用される。

local-function-key-mapfunction-key-mapを継承する。後者はすべての端末にバインディングを適用したい場合のみ修正するべきなので、ほとんど常に前者の使用が望ましい。

Variable: key-translation-map

この変数は入力イベントを他のイベントに変換するために、input-decode-mapと同じように使用される別のキーマップを保持する。input-decode-mapとの違いは、local-function-key-mapの前ではなく後に機能する点である。このキーマップはlocal-function-key-mapによる変換結果を受け取る。

input-decode-mapと同様だがlocal-function-key-mapとは異なり、このキーマップは入力キーシーケンスが通常のバインディングをもつかどうかかに関わらず適用される。しかしこのキーマップによりキーバインディングがオーバーライドされても、key-translation-mapでは実際のキーバインディングが効果をもち得ることに注意。確かに実際のキーバインディングはlocal-function-key-mapをオーバーライドし、したがってkey-translation-mapが受け取るキーシーケンスは変更されるだろう。明確にするためにはこのような類の状況は避けたほうがよい。

key-translation-mapは通常はself-insert-commandにバインディングされるような通常文字を含めて、ユーザーがある文字を他の文字にマップすることを意図している。

キーシーケンスのかわりにキーの変換として関数を使用することにより、シンプルなエイリアスより多くのことにinput-decode-maplocal-function-key-mapkey-translation-mapを使用できます。その場合にはこの関数はそのキーの変換を計算するために呼び出されます。

キー変換関数は引数を1つ受け取ります。この引数はread-key-sequence内で指定されるプロンプトです。キーシーケンスがエディターコマンドループに読み取られる場合はnilです。ほとんどの場合にはプロンプト値は無視できます。

関数が自身で入力を読み取る場合、その関数は後続のイベントを変更する効果をもつことができます。たとえば以下はC-c hをハイパー文字に後続する文字とするために定義する方法の例です:

(defun hyperify (prompt)
  (let ((e (read-event)))
    (vector (if (numberp e)
                (logior (ash 1 24) e)
              (if (memq 'hyper (event-modifiers e))
                  e
                (add-event-modifier "H-" e))))))

(defun add-event-modifier (string e)
  (let ((symbol (if (symbolp e) e (car e))))
    (setq symbol (intern (concat string
                                 (symbol-name symbol))))
    (if (symbolp e)
        symbol
      (cons symbol (cdr e)))))

(keymap-set local-function-key-map "C-c h" 'hyperify)

23.15.1 通常のキーマップとの対話

そのキーシーケンスがコマンドにバインドされたとき、またはさらにイベントを追加してもコマンドにバインドされるシーケンスにすることができないとEmacsが判断したときにキーシーケンスの終わりが検出されます。

これは元のキーシーケンスがバインディングをもつかどうかに関わらず、input-decode-mapkey-translation-mapを適用するときに、そのようなバインディングが変換の開始を妨げることを意味します。たとえば前述のVT100の例に戻って、グローバルマップにC-c ESCを追加してみましょう。するとユーザーがC-c PF1をタイプしたとき、EmacsはC-c ESC O PC-c PF1に変換するのに失敗するでしょう。これはEmacsがC-c ESCの直後に読み取りを停止して、O Pが読み取られずに残るからです。この場合にはユーザーが実際にC-c ESCをタイプすると、ユーザーが実際にESCを押下したのか、あるいはPF1を押下したのか判断するためにEmacsが待つべきではないのです。

この理由によりキーシーケンスの終わりがキー変換のプレフィクスであるようなキーシーケンスをコマンドにバインドするのは、避けたほうがよいでしょう。そのような問題を起こす主なサフィックス、およびプレフィクスはESCM-O (実際はESC O)、M-[ (実際はESC [)です。