Next: , Previous: , Up: Keymaps   [Contents][Index]


21.14 Keymaps for Translating Sequences of Events

read-key-sequence関数がキーシーケンス(Key Sequence Inputを参照)を読み取るときは、特定のイベントシーケンスを他のものに変換(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がキーボード入力をデコードした直後だけ効果をもちます。Terminal I/O Encodingを参照してください。

Variable: input-decode-map

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

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

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を継承するが、function-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 (lsh 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)))))

(define-key local-function-key-map "\C-ch" 'hyperify)

21.14.1 Interaction with normal keymaps

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

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

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