faux の Vim キーバインド対応
faux で Vim キーバインドを使えるように対応を行った時に調べた CodeMirror (v5) のキーバインド拡張についてのメモです。
CodeMirror のキーバインドの拡張
https://codemirror.net/doc/manual.html#option_extraKeys
キーバインドの簡単な拡張方法として、extraKeys オプションを利用する方法があります。
ただし、この方法でキーバインドを追加した場合は KeyMap の設定に関わらず常に有効な設定となります。
今回は KeyMap 毎に別のキーバインドを追加したいので、この方法は利用できません。
KeyMap 毎の拡張方法を調べたのですが残念ながら見つけられず、諦めて各々の KeyMap 設定に直接追加する方法で拡張を行いました。
KeyMap 設定は、CodeMirror.keyMap オブジェクトにそれぞれ格納されており、標準の KeyMap であれば CodeMirror.keyMap.basic、 Emacs であれば CodeMirror.keyMap.emacs となります。
例えば Emacs であれば、以下のように任意のキーバインドを追加できます。
CodeMirror.keyMap.emacs['Ctrl-X Ctrl-C'] = function() { alert('bye!') };
しかし Vim はモードがある為か事情が異なり、この方法では追加できません。ただしその代わりに API が存在します。
Vim キーバインドの拡張
CodeMirror.Vim オブジェクトを通じて API を利用する形となります。
キーバインドの追加には、map または mapCommand を利用します。
map
map(lhs: string, rhs: string, ?context: string)
map はキーとコマンドのマッピング設定を行えます。
あるキーから別のキーやコマンドへ、または、あるコマンドから別のコマンドやキーへとマッピングすることができます。
例: gonextline コマンドで j を押した時と同じ動作をする
CodeMirror.Vim.map(':gonextline', 'j');
mapCommand
mapCommand(keys: string, type: string, name: string, ?args: object, ?extra: object)
mapCommand はキーに対応するコマンドのマッピング設定を行えます。
type に motion / operator / action などを指定し、name で実行するコマンド名を指定します。
新しいコマンドが必要な時は、defineMotion / defineOperator / defineAction で定義できます。
例:キー ZQ で bye とメッセージを表示する
CodeMirror.Vim.defineAction('end', function() { alert('bye'); }); CodeMirror.Vim.mapCommand('ZQ', 'action', 'end', {});