Re: vimperatorが最強になった日

例えば

:open twitter teramako

とすると
vimperator-awesomebar

Big Sky :: vimperatorが最強になった日

すごい、ラブコールを送られたので返答しますよ。

ところで、vimperator使ってると稀にパススルーモードが外れてしまい、「Google Readerキーバインドが効かなくなった」とか「LivedoorReaderで上手く動かなくなった」って事になったりします。
私の場合、以下の様にキーマップして回避しています。

noremap <c-i> :js modes.passAllKeys = true<cr>

ただ、これを使ってて気づいたのですがどうやらvimperatorの補完はmapで実行する「:ex」コマンドにも反応してる臭い。これはいずれ直るかと思うけど気になる様だったらパッチを送ってみよう。とりあえずは、mapで実行するんじゃなくてaddUserMap使ってやる事にした。

javascript <<EOM
liberator.mappings.addUserMap([liberator.modes.NORMAL], ['<C-i>'],
    'Pass through mode',
    function () { liberator.modes.passAllKeys = true }
);
EOM
Big Sky :: vimperatorが最強になった日

について。

mapコマンドの仕様は内部で何をしているかというと、当然lhrrhrに変換しているわけだが、その方法はrhrに対応するkeypressイベントを生成して順番に発行しています。*1
マッチポンプであります。
rhrの先頭に:がある場合、自身で:に対応するイベントを発行し、自身で受け取ってコマンドライン行へフォーカスします。イベントはその時フォーカスされた要素に対して発行されるので、次からは文字としてコマンドラインに現るようになります。
つまり、手打ちしているところを完全に模倣しているのであります。

set wildoptions=autoをすると、コマンドラインに対して発行されたキーイベントをトリガーに自動で補完候補を表示するようになります。mapからの「:ex」コマンドと組合わさると、まさにマッチポンプ*2

そんなわけで仕様上、mapコマンドで生成した「:ex」コマンドにも反応してしまうのです。

解決方法としては上で示されているようにcommand.addUserCommandを使用して素直にJavaScriptコードを実行させるか、map <C-i> <C-q>としてあげるのが吉かと思います。

mapコマンドは馬鹿正直にキーイベントを生成するためrhrにあまり長いコマンドは入れない方が良いでしょう、というのがオイラの見解です。前々から馬鹿正直で気持ち悪いなとは思っていて、rhrの最初の文字が:だったらcommands.parseCommandに渡して得たCommandオブジェクトを実行させた方がスマートだとは思っていたのですが、ここにきて弊害が出てしまいましたね。

set complete=l について(余談)

lはAweSomeBarの内部機構を利用した補完となるわけですが、機能的にはbhと似ています。非同期の補完が可能なのでパフォーマンスは良く感じられるでしょう。ただし、ブックマークキーワードの補完は履歴に入っていない限り出来ない様です。パフォーマンスに問題が無ければbhの方が使い勝手が良いでしょう。

*1:参照:echo events.feedkeys

*2:別に避難しているわけではない。XBLなどのFirefox内部では普通に行われている