ヰ゛ムッ ヰ゛ムッ
此の記事は TokyoVim#19 の会場で書いてゐます。
VimScriptでJavaScriptみたいなcallback型で、コマンドを非同期に実行させませう。
vimproc を使ひます。
ヰ゛ムッ ヰ゛ムッ ヰ゛ムッ
vimproc#popen2()
等で command を非同期に実行すると、返り値として vimproc オブジェクトを貰えるので其れをとっておきます。vimproc の公式には此んなcodeが書いてあります。
let prc = vimproc#popen2('ls') let response = '' while !prc.stdout.eof let response .= prc.stdout.read() endwhile echo response
while で vimproc.stdout.eof
が真に成るのを待ってゐます。が、此れでは結局 Vim が固まるので用を足せない。其所で定期的に vimproc.stdout.eof
を確認しに行く様にします。autocmd です。Cursor eventをとっ掴まへて timer の代りにします。
event をとっ掴まへて timer の代りにしてると、AzureaScript を思ひ出しますね。AzureaScript には此の後 System.setTimeout()
が実装されてました。好かった。
cf. AzureaUtil作りました #AzureaScript #js http://c4se.hatenablog.com/entry/20110226/1298651872
" license: Public Domain let s:async_vimproc = { \ 'response': '', \ 'original_updatetime': 0 \ } augroup async_vimproc autocmd! augroup END function! Async(exec, callback) let s:async_vimproc.original_updatetime = &updatetime set updatetime=50 let s:async_vimproc.vimproc = vimproc#pgroup_open(a:exec) let s:async_vimproc.callback = a:callback autocmd async_vimproc CursorHold,CursorHoldI * call Callback() sleep 50m call Callback() endfunction function! Callback() if s:async_vimproc.vimproc.stdout.eof autocmd! async_vimproc let &updatetime = s:async_vimproc.original_updatetime call s:async_vimproc.callback(s:async_vimproc.response) unlet s:async_vimproc.vimproc unlet s:async_vimproc.callback else let s:async_vimproc.response .= s:async_vimproc.vimproc.stdout.read() endif endfunction function! s:callback(response) echo a:response endfunction call Async('ruby -e"sleep 2; p 42"', function('s:callback'))
Async()
を呼ぶと autocmd を設定し、適当な時に Callback()
を呼ぶ樣にします。Callback()
で返り値を蓄積しつつ、command が終ったか否かを確認します。終ってゐたら、autocmd を解除し、渡されてゐた callback 関数を実行します。
vimproc に setImmediate か requestAnimationFrame みたいなのを実装した方が好いのかもしれない。
ヰ゛ムッ
cf. Vim-users.jp - Hack #124: Vimで非同期実行を行う http://vim-users.jp/2010/02/hack124/