c4se記:さっちゃんですよ☆

.。oO(さっちゃんですよヾ(〃l _ l)ノ゙☆)

.。oO(此のblogは、主に音樂考察Programming に分類されますよ。ヾ(〃l _ l)ノ゙♬♪♡)

音樂は SoundCloud に公開中です。

考察は現在は主に Scrapbox で公表中です。

Programming は GitHub で開發中です。

vimproc で command の非同期実行を待ち callback してもらう

ヰ゛ムッ ヰ゛ムッ

此の記事は 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/