Vimからアプリケーションをバックグラウンドで起動する優れた1つの方法
※この記事はVim Advent Calendar 2012の262日目の記事です。
以前このような記事を書きました。
Vimからアプリケーションをバックグラウンドで起動するいくつかの方法 - Humanity
その後、vital.vimのProcessモジュールにspawn()関数として実装しました。
もちろんWindowsと*nix系環境(Mac含む)をサポートしています。
そして紆余曲折あり、現時点で結果このような実装になりました。
(Processモジュールの最新版はこちらです)
" Execute program in the background from Vim. " Return an empty string always. " " If a:expr is a List, shellescape() each argument. " If a:expr is a String, the arguments are passed as-is. " " Windows: " Using :!start , execute program without via cmd.exe. " Spawning 'expr' with 'noshellslash' " keep special characters from unwanted expansion. " (see :help shellescape()) " " Unix: " using :! , execute program in the background by shell. function! s:spawn(expr) if s:is_windows let shellslash = &l:shellslash setlocal noshellslash endif try if type(a:expr) is type([]) let special = 1 let cmdline = join(map(a:expr, 'shellescape(v:val, special)'), ' ') elseif type(a:expr) is type("") let cmdline = a:expr else throw 'Process.spawn(): invalid argument (value type:'.type(a:expr).')' endif if s:is_windows silent execute '!start' cmdline else silent execute '!' cmdline '&' endif finally if s:is_windows let &l:shellslash = shellslash endif endtry return '' endfunction
注意点
- shellescape() の第2引数には0でない値を渡すこと
- これは!や%などのVimにとって特別な文字をバックスラッシュでエスケープし、「:!」コマンドによって展開されてしまうのを防ぎます。
- 詳しくは :help shellescape()
- shellescape() を呼ぶ前に「set noshellslash」すること
- これがないと「:!」コマンドが、引数の中の「\」を「/」に自動的に変換してくれやがります
- shellslash はパスの区切りとして '\' が使われるときだけ有効なオプション*1なので、「exists('+shellslash')」の式が1を返すかどうかチェックする必要があります
また前回にも書いた通り、
結論
外部プログラム実行には多くの罠があるのでvitalを使いましょう。
そしてバグがあれば報告することで、よりvitalの安心感が増します。
またProcessモジュールだけでなく、vimprocをバックエンドとした、よりリッチなProcessManagerモジュールなどもあります。
詳しくはVim Advent Calendarのujihisaさんの記事一覧を参照してください。