map, map, map

ex コマンドの map をテストしている。map コマンドは、任意のキーストロークをそれに対応するまったく別のストロークへ透過的に変換するためのルールを指定する。

:map[!] [lhs rhs]

あるいは何も引数を指定しない場合、現在定義されているルールの一覧を表示する。vi には 2 つのマップがあり、それぞれコマンドモード、テキスト入力モードで排他的に使用される。テキスト入力モードのマップを対象にするには、map! と指定する。なお vim にはもっといろいろなモード用のマップが用意されているが、wasavi は vi に則って、やはり 2 つのマップだけを備える。

で、これを実装する際の話として。まず仮に lhs、つまり変換元キーストロークが高々 1 キーなら話は簡単である。押されたら変換関数を通して変換する。これが最も簡単なパターン。

次に難しいのは、lhs が複数のキーストロークであった場合。:map qq 3w みたいな。これは、変換関数に状態を持たせるようにすればいい。

次に難しいのは、変換ルールに曖昧なものがあった場合。たとえば、
:map q 1G
:map qq G

みたいな。どうなるか想像できますか? q を押すとバッファ先頭へ、qq を押すとバッファ末尾へジャンプするつもりの定義だ。

このような曖昧な定義に対してどう振る舞うかを、posix は未定義のままにしている。つまり曖昧な定義をエラーにする vi があってもいいし、よきに計らう vi があってもいいということだ。エラーにするのは簡単だが、よきに計らうにはどうすればいいだろうか?

この定義が有効な状態で、まず q を押す。この状態では、ユーザはバッファ先頭へ飛びたいのか? それとも末尾か? は判断できない。そこで、タイマを仕掛け、1 秒後に 1G へ変換されるようにする。つまり q 単体の入力に対する変換が行われるようにする。また、1 秒以内にキー入力があった場合:

  • タイマを仕掛けていたら、それをキャンセルする
  • 新しいキー入力を加えた上で新しい仮変換候補を抜き出す
  • 抜き出した結果、新しいキー入力を加える前の仮変換候補が確定したら、それを実行する
  • そうではなく、新しいキー入力を加えた後の変換候補が 1 つに絞られれば、その変換候補を確定し実行する
  • そうではなく、新しいキー入力を加えた後の変換候補が複数あれば、変換候補の最初のものに対して 1 秒後に確定・実行されるようにタイマを仕掛ける

みたいな感じにする。

Leave a Reply

Your email address will not be published. Required fields are marked *