Humanity

Edit the world by your favorite way

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さんです。