Vimからアプリケーションをバックグラウンドで起動するいくつかの方法
ばよえ〜ん(訳:Vim Advent Calendar 2012への9回目の投稿です)
この記事はVim Advent Calendar 2012の105日目の記事になります。
104日目は@mopp_jpさんのカーソルキーさん@つかわない インサートモード編でした。
Vimからアプリケーションをバックグラウンドで起動する方法はいくつかありますが、
やり方を間違えるとハマります。
特にWindowsでcmd.exeを介してごにょごにょしようとすると人類なら誰もがハマると思われます。
(参考記事:cmd.exe のコマンドラインの仕様を解析してみた - 永遠に未完成)
vimprocを使えばシェルを介さずにアプリケーションを起動することが可能なため、
厄介なエスケープ処理を入れる必要がなくなりますが、
vimprocがインストールされていない可能性があります。
しかし、先日@mattn_jpさんと@h_eastさんにTwitterで、
なんと一切ライブラリをインストールすることなく使えるtipを教えてもらった*1ので、感謝の意を込めて覚書したいと思います。
バックグラウンド起動のベストプラクティス (Windows)
いきなりですが結論から。:!startを使います。
詳しくは「:help :!start」を読んでもらうとして、
:!startを使うとシェル(cmd.exe)を介さずにVimから直接アプリケーションをバックグラウンドで起動することができます。
また、シェルを介さないため引数のエスケープが要りません。
let arg = 'value' execute '!start app' arg
バックグラウンド起動のベストプラクティス (Unix系)
ついでなのでUnix系向けのサンプルコードも載せておきます。
:!startのような仕組みはないので、:!かsystem()とshellescape()を組み合わせて使う必要があります。
:! + shellescape()の場合
let arg = 'value' execute '!app' shellescape(arg) '&'
system() + shellescape()の場合
let arg = 'value' call system('app '.shellescape(arg).' &')
雑感
今の所これがベストプラクティスだと思います。*2
個人的にはシェル用に引数をエスケープ処理とか入れたくないので、どのプラットフォームでも使える:!startのような仕組みがあるとうれしいと思いました。
Perlみたくsystem()にListを渡すとシェルを介さないとかあったらうれしいですが...
次のVim Advent Calendarは@manga_osyoさんです。
*1:mattn on Twitter: "@tyru @h_east なのでdos窓出さずに非同期に外部アプリ起動するならvimproc要らないんです(あまり知られてないtips)" h_east (トロッコ6個) on Twitter: "@mattn_jp @tyru 私の_vimrcには10年以上前から noremap <C-W>N :!start gvim<CR> っていう設定が入っていて結構使用頻度高いです。シングルインスタンスVim派からは文句必至だと思うけどw" Twilog Twilog
*2:こんな方法ベストプラクティスって言いたくないですが、言語がヘボいとベストプラクティスが量産されるのはしょうがないことですね!