Promise and Generator #2

そういうわけでちまちまといじっている。

とりあえず vi コマンドを回す部分に関しては修正した。これで非同期の処理だろうが同期の処理だろうが不自然なく呼べるようになった。それはいいのだが、vi コマンド群は本丸ではない。qeema が発生するキーボードイベントから、各 vi コマンドのハンドラに達するまで、せいぜい 4〜5 の関数がネストするだけであり、ただそれを Promise を使うようにすれば済む。

難しいのは ex コマンドの方なのだった。

ex コマンドは、ex コマンド列をコンパイルして中間コードの配列に落とし、それを逐一実行するという構造になっている。なので、修正するとしたら ex コマンドごとに Promise をつなげていく、ex コマンド自体はそれぞれ resolve() でコマンドの終了を通知するといった形になる。

ただいくつか面倒な点がある。

  • write、read、edit などバックグラウンドに処理を投げるファイルシステム系のコマンドは、読み書きの進捗イベントをバックグラウンドから複数回返される。従来は、この複数回返されるメッセージというのは ex コマンドのハンドラの外で処理していた。というのも非同期的な ex コマンドを実行する際は一旦そのコマンドの同期的な部分のみを実行したあと executor を一時停止し、バックグラウンドから処理完了メッセージが到着したら executor.resume() で再開するようになっていたからだ。これは処理が分散しているといえばそうなので、若干不自然ではある。

    個々の ex コマンドを Promise によって駆動するのであれば、複数回返されるメッセージの扱いというものも ex コマンドのハンドラ内で完結できるわけで、そうすべきだと思う。具体的にはハンドラ内で long-lived connection をその都度行い、コマンド完了時に閉じればいい

  • シグナルの扱い。シグナルというと若干語弊があるのだけど、つまりやはりファイルシステム系の時間がかかるコマンドの実行中、[cci]^C[/cci] が押されたらキャンセル扱いにする処理のことだ。これも Promise 化によって中身がかなり変わる。

ちなみに非同期で実行される ex コマンドとしては

  • cd
  • edit
  • read
  • c オプションが付加された s
  • 非同期とマークされたオプションの値の変更を含んだ set
  • write

となっている。また、レジスタを指定できる ex コマンドで [cci]*[/cci] レジスタが指定された場合も非同期になる。レジスタを指定できる ex コマンドは、

  • delete
  • put
  • yank
  • @
  • *

となっている。非同期とマークされたオプションは以下のとおり。

  • fullscreen
  • syncsize
  • columns
  • lines

Leave a Reply

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