O’Reilly に表題のようなタイトルがある。日本語版は「入門 vi」だ。一丁前のブログぽく広告なんかを出してみると、
こんな感じ。ちなみにこの本は持っていて決して損はない、とても分かりやすいいい本だ。
なんでいきなりステマかというと、この本の中に記述されている vi/ex コマンドの実例をテストケースとして起こして、だいたい全てのテストに通ることを保証したい。つまり巷の vi 本が、そのまま wasavi のチュートリアルとしても通用するようにしたい。とそういうわけです。
O’Reilly に表題のようなタイトルがある。日本語版は「入門 vi」だ。一丁前のブログぽく広告なんかを出してみると、
こんな感じ。ちなみにこの本は持っていて決して損はない、とても分かりやすいいい本だ。
なんでいきなりステマかというと、この本の中に記述されている vi/ex コマンドの実例をテストケースとして起こして、だいたい全てのテストに通ることを保証したい。つまり巷の vi 本が、そのまま wasavi のチュートリアルとしても通用するようにしたい。とそういうわけです。
wasavi.js、agent.js、extension_wrapper_js、background.js を strict mode にした。
と言ってもそんなに弄る必要もなかったのだけど、arguments.callee を追い出す必要があった。そもそも strict モードは、コードを堅牢にしたりセキュアにしたりするためのものだ。しかし arguments.callee の参照禁止という点では、副作用的に jit コンパイルがより深いレベルで行われるとかで、速くなる(可能性がある)、そうな。へー。
* * *
wasavi 0.4.207 をそれぞれのブラウザのエクステンション向けに公開した。Chrome が即時、Opera がだいたい 1 日なのは今までの通りとして、Firefox がとりあえずまず validation が滞りなく進み(やっと)、Full Review 待ちになった。ここからだいたい 10 日かかると見ていたら、3 日くらいでレビューが通った。なんだー早いなー。
それはそれとして、レビュー結果で、ソース中のとあるコメントに対して
This is not even remotely true.
つまり「ぜんぜん間違ってるんですけど?」と一言あったのだけど、そのコメントは複数の文からなるものなのだ。えーとどの部分が間違ってるのか書いてほしい……。レビュー結果のメールに返答して返事が返ってくるものなのかな? なんか機械的に送られてきてる気がするけど。
いろいろと修正。keyManager や mapManager を弄るのは、wasavi の動作が根本的にぶっ壊れる可能性があるので怖い。ちなみに「なんとか Manager」と命名されたクラスは悪い設計の兆候だという意見もあるらしい。うむむ。
前の記事の通り、@ コマンドや :@ コマンドで実行する文字列内で特殊なキーを示すためには私用領域の文字 U+e000 をヘッダにする。矢印キーなら “\ue000<down>” などといった感じだ。q コマンドで記録したストロークに特殊なキーが含まれていたとして、それを “ap とかすると普通に U+e000 の文字も貼り付けられる。どういう文字がレンダリングされるかは環境に依存する。
q コマンドに頼らない場合、適当な行にキーストロークを打ち込んでそれを yy する必要があるが、挿入モードでの ^V で任意のコードポイントを入力する方法は wasavi にはまだない。将来的にはできるようにするつもりだが、とりあえずあとまわし。
:map コマンドでマップ前とマップ後のストロークをそれぞれ指定する際は、U+e000 を明示的に打ち込む必要はない。<~> の文字列には自動的に U+e000 が前置される。これを避け、純粋に文字列としての <~> を指定するには、”<” の前に ^V そのものを前置する。つまり ^V^V と入力してから <~> を打つ。ストロークに空白文字を含める場合にも ^V を前置する必要がある。この辺は素の vi、あるいは vim でもだいたい同じだ。
* * *
Chrome Web Store でのバグレポート、および Opera でのフィードバックで指摘されたのだが、”array[i]” とか打つと wasavi 内のとあるループ処理が終わらなくなってハングする。閉じ括弧に対応する開き括弧を点滅させる処理と挿入モードの下処理がかち合ってるために起こるバグだ。これは手元のソースではすでに修正してある。公開版では、とりあえず [cci]:set noshowmatch[/cci] することで回避できる。
Chrome Web Store でのバグレポは(たぶん)ニュージーランドの方からだったが、Opera 版のそれは日本の方からのようだ。で、その方のブログのエントリを見るとバグレポートを出すのに少なくない心の中の逡巡があるようなのだな。
これは日本人らしい奥ゆかしさの発露なのかもしれないが、バグレポートはまずそれが行われないことにはこちらに届かないわけなので、特に難しいことを考えず気軽にしてほしいと思った。「このエクステンションはゴミだな! 作った奴は死んだほうがいい! てか死ね!」とか書かれても特段なんとも思わないくらいの鈍感力は備えているので心配ない。
ちなみに各エクステンションのリポジトリにあるフィードバック機構はそんなにちょくちょく見てるわけじゃないので、もしアカウントを持っているなら github の issue を作ってもらえるか、ここのフォーラムに書き込んでもらうのがいちばん手っ取り早いです。
キーストロークの記録は、:map と間接的な関係がある。両者とも、キーストロークを文字列化したものを扱う。さてキーの中には、一般的なコードポイントに対応しないものがある。例えば Page Up とか F1 とかね。そういうキーをどう文字列化するか? というところが現在の wasavi の実装ではまだ不完全なのだ。
vim では、特殊なキーは CSI (Control Sequence Introducer, 0x9B) と呼ばれる特別なバイトを前置して区別している、ようだ。wasavi でも同じような形式にしよう。私用領域の U+e000 を 使用する。たとえば delete キーに対応するキーストロークは、文字列化すると “\ue000<delete>” となる。
:map では同じような、しかし逆の変換を実装することになる。:map の rhs で “<delete>” と書いたら、内部的には “\ue000<delete>” として扱わないといけないのだ。
@ コマンド、:@ コマンドはすでに作ってある。これらは、指定のレジスタの内容をそれぞれ vi コマンド、ex コマンドとして実行する。
ではコマンド列をどうやってレジスタに突っ込むかというと、素の vi では適当な行にコマンド列を打ち込んで yy することになる。
一方 vim では、q{register} コマンドが新設されている。これはエディタの状態を「キーストローク記録中」にする。この状態のキー入力は記録される。この状態を抜けるには、単に q を押す。すると記録されたキーストロークが {register} に保存される。この機能はつまり、インタラクティブにキーストロークを記録するものだ。
というわけでこれを実装する。
こんなことを書いてそろそろ 1 年経つのだけど:
DOM3 Composition events、いつのまにやら Chrome(と、おそらく Safari)、IE9、Fx9 と実装済みのブラウザが揃っている 2011 年末。
さて Opera は何年後くらいに実装するの?
# そしてまさかの実装されない、というオチ
まさか 1 年たってもまったく状況が変わってないとは思わなかった。強いて変わった点といえば、Opera は 12.50 で DOM3 Events に準拠するようになるらしいということ。ただし開発版 Opera である Opera Next の最新ビルドでも、Composition Events はまったく実装されていない。さすがに最終的に「実装されない、というオチ」はないと思うけど。ない……よね?
ちなみに、Composition Events をサポートしていないとしても、たとえば google でやってるように、思い切りタイマーをぶんまわして textarea#value をポーリングすれば確かに同じようなことはできる。できるのだけど、ただ 1 つだけ問題がある。IME を通した入力サイクルを考えてみると、
の繰り返しだ。しかし実際は、確定として enter を押すことはそれほど多くない。(少なくとも MS-IME は)変換後の候補選択状態で、選択のための特定のキー以外のキーを押せば、暗黙的に確定が行われて仮入力状態に移行する。この暗黙的な確定が発生した正確なタイミングをタイマー方式では認識できない。
そういうわけで、wasavi には Composition Events がないブラウザのためのフォールバック機構は入れていない。つまり今のところ Opera で IME を通した入力は正しく動作しない。どうしたものかなあ……。
AMO の中の人の手元でもサーバーエラーになるそうなので、bugzilla に登録してもらった。
うーんこちらで直接登録してもよかった気がするが。まあでも中の人……というか「the Add-ons Developer Relations Lead for Mozilla」という肩書きのおかげか、あるいはアサインとかも最初から割り当てられてたせいか、すぐに修正されたようだ。あとは、そのパッチがレビューされて実際に適用されるのを待つだけということかな。
長かったなあ。
関係ないけど、wasavi の preliminary / full review をしてくれた方は Pentadactyl の開発者の一人ということで、vi 繋がりなのかと思ってたら、単にものすごく多くのアドオンをレビューしているだけだった。なーんだ。
そういえばすっかり忘れていたが、AMO に新しい xpi をアップロードできない件。
(先週の)金曜になったら試してみてね! などと言うから期待していたのだが案の定同じサーバーエラーが帰ってくるだけだった。枕を涙で濡らしつつ、再び AMO の中の人にメールしたら、xpi を送ってみろというので送った。
個別に対応してくれるのはありがたいけど、サーバーエラー時のメッセージをもうちょっと詳しく出すように改修してくれないかなあ。次またエラー出たらまたこのやりとりしろというのだろうか。
お願いしますよ Jorge さん。
「relativenumber、いいよね」「いい……」
vim の機能を全て知っているわけもないが、知ってる機能の中で、初めて知ったとき最も衝撃的だったのは relativenumber かもしれない。relativenumber 好きだ、大好きだ。お前が好きだ、お前が欲しい!
というわけでこっそりと wasavi へ移植する。
内部的には、wasavi の行番号は css のカウンタだ。したがって、操作できるのは counter-reset、counter-increment くらいで、それほど自由度があるわけではない。そういう環境下でカーソル行を 0 とした相対的な行番号ぽくするには、バッファの counter-reset を -(カーソル行位置+1) で初期化する。カーソルの上方向は負の符号付きになってはしまうが、これでだいたい目的は達せられる。
しかし実際に作ってみるとやっぱり負符号が気になる……。