vim-users.jp

Hack #124: Vimで非同期実行を行う

Posted at 2010/02/13
このエントリーをはてなブックマークに追加

VimがEmacsと比較して一番劣っている機能として、コマンドの非同期実行があげられます。ここでは現状のコマンド実行の問題点とEmacsとの比較、その解決方法について議論を行います。

Vimのコマンド実行の欠点

Vimはsystem():readを用いて外部コマンドを実行し、その結果を得ることができます。これは非常に便利なのですが、Vimが起動した外部コマンドの終了を待ち合わせるため、Vimが停止してしまうという欠点があります。これは特にquickrunや:makeを実行しているときに問題となります。プログラムをバックグラウンドで実行すれば、終了を待ち合わせずにすみますが、それでは結果がとれません。さらにWindows上のGVimの場合、外部コマンドを実行するたびにDOS窓が開いて煩わしいです。 処理内容がシェルに依存するという欠点もあります。たとえば、Windowsでプログラムを起動するためには適切にエスケープしなければいけません。

Emacsとの比較

対するEmacsはどうでしょう。Emacsでは、start-process関数を用いてプロセスを生成することにより、コマンドを非同期的に実行できます。 comint-modeでもこれを用いてインタプリタを起動し、非同期で通信しています。 ただし、Emacsにはマルチスレッド関数がありません。全ての処理はシングルスレッドです。

外部インタフェースの欠点

RubyやPerl, Pythonといった外部インタフェースを用いるという解決策もあります。 しかし、外部インタフェースは通常のVimScriptとは文法が異なるため、連携が非常にややこしいです。時折フリーズしたり、エラーが起こったときにデバッグしづらいという欠点もあります。さらに、すべての環境で使えるわけでもありません。インストールしているRubyやPerl, Pythonのバージョンにも依存するなど、 非同期に通信するためだけに外部インタフェースを用いるのは大げさすぎます。 ただし外部インタフェース内ではマルチスレッドが使えるので、真の非同期通信をするためには、外部インタフェースを用いるほかありません。

vimprocについて

外部ライブラリであるvimprocを用いて外部コマンドと通信すれば、上記に挙げたほとんどの欠点が解消されます。 vimprocとはYukihiro Nakadairaさんが開発している、優れた非同期実行ライブラリです。私が改良したものをgithub上で開発しています。 http://github.com/Shougo/vimproc/tree/master ソースからコンパイルしてVimのautoloadディレクトリに、「proc.soまたはproc.dll」と「vimproc.vim」をコピーすれば準備完了です。

ここでは、vimprocで実装されているvimproc#system関数を紹介します。これは、標準のsystem関数を置き換えることができます。 ただしシェルを起動しないので、シェルの内部コマンドは動作しません。パイプやリダイレクトも動かないので注意してください。 パイプやリダイレクトについては、今後実装予定です。 let l:result = vimproc#system('ls') vimprocを駆使すれば非同期実行をエミュレーションできますが、スレッドの存在しないVimでは使い方がとてもややこしいので、ここでは説明を省略します。 興味がある場合にはvimprocのtestディレクトリにあるサンプルスクリプトを参照してください。 ネットワーク通信もできるので、Twit.vimみたいなプログラムも簡単に作成できます。 いずれはcomint-modeのように、インタプリタ実行機能を統合させたいと思っています。 ちなみにVimScriptでのシェル実装であるvimshellでも、vimprocを用いて非同期実行を行っています。

その他の非同期実行ライブラリ

その他のライブラリとして、vimprocやvimshellをもとにNico Raffatoさんが製作しているConqueというプラグインがあり、とても精力的に開発されています。Emacsのansi-term.elを目標にしているようで、動作が散漫なのが欠点ですが、多機能のようなので使用してみるといいかもしれません。

CursorHoldイベントの落とし穴

しかも、Vimには指定された時間が経過したら関数を呼び出すタイマー機能がありません。 CursorHoldICursorHoldイベントで代用するという手がありますが、これにはイベントごとに時間を設定できない、 ポップアップが表示されているときは呼ばれない、カーソルが動くまで呼ばれないといった欠点があります。 この欠点は本質的に回避不能です。Vim本体にタイマー実行機能が搭載されるのを待つしかありません。

clientserver機能を使う

Vimのclientserver機能を用いると、処理が完了した際に機能を呼び出すコールバック機能を実装することが可能です。 ただし、X環境が必要になります。Windows上でも使用できますが、あらかじめ別のVimを用意しておく必要があります。詳しくは:help clientserverを参照してください。

Shougo

もどる
blog comments powered by Disqus