vimproc を使用して非同期で外部コマンドを実行し、後から結果を取得する
殆ど quickrun.vim の写経なんですが、自分でも書いてみました。
[ソース]
set updatetime=100 augroup vimproc-async-receive-test augroup END " コマンド終了時に呼ばれる関数 function! s:finish(result) echom "finish" echo a:result endfunction function! s:receive_vimproc_result() if !has_key(s:, "vimproc") return endif let vimproc = s:vimproc try if !vimproc.stdout.eof let s:result .= vimproc.stdout.read() endif if !vimproc.stderr.eof let s:result .= vimproc.stderr.read() endif if !(vimproc.stdout.eof && vimproc.stderr.eof) return 0 endif catch echom v:throwpoint endtry " 終了時に呼ぶ call s:finish(s:result) augroup vimproc-async-receive-test autocmd! augroup END call vimproc.stdout.close() call vimproc.stderr.close() call vimproc.waitpid() unlet s:vimproc unlet s:result endfunction function! s:system_async(cmd) let cmd = a:cmd let vimproc = vimproc#pgroup_open(cmd) call vimproc.stdin.close() let s:vimproc = vimproc let s:result = "" augroup vimproc-async-receive-test execute "autocmd! CursorHold,CursorHoldI * call" \ "s:receive_vimproc_result()" augroup END endfunction call s:system_async("ruby -e \"sleep 3; puts 'homu'; puts 'mado'\"")
s:system_async に渡したコマンドを非同期で実行し、処理が終わったら s:finish を呼ぶような感じです。
上記のコードでは :source すると3秒後に "homu" と "mado" が出力されます。
もうちょっと複雑なイメージがあったんですが、実際に書いてみるとそうでもなかったですね。
おもしろい。
差し当っての問題としては更新のタイミングは updatetime に依存してしまうことですかね…。
プラグイン側で非同期処理を行う場合、updatetime を気軽に変更することが出来ないのがつらぽよ…。