Skip to content

Instantly share code, notes, and snippets.

@ujihisa
Created February 9, 2015 06:20
Show Gist options
  • Save ujihisa/acb0a4f31c5a3a8ee455 to your computer and use it in GitHub Desktop.
Save ujihisa/acb0a4f31c5a3a8ee455 to your computer and use it in GitHub Desktop.
let s:save_cpo = &cpo
set cpo&vim
" * queries: [(QueueLabel, QueueBody)]
" * logs: [String]
" * vp: vimproc dict
" * buffer_out, buffer_err: String
" * current buffered vp output/error
" * vars: dict
let s:_process_info = {}
function! s:_vital_loaded(V) abort
let s:V = a:V
let s:L = s:V.import('Data.List')
let s:S = s:V.import('Data.String')
endfunction
function! s:_vital_depends() abort
return ['Data.List', 'Data.String']
endfunction
function! s:is_available() abort
return s:P.has_vimproc()
endfunction
function! s:of(command, dir, initial_queries) abort
let label = sha256(printf('%s--%s--%s', a:command, a:dir, join(a:initial_queries, ';')))
if !has_key(s:_process_info, label)
let cwd = getcwd()
execute 'chdir' a:dir
let vp = vimproc#popen3(a:command)
execute 'chdir' cwd
let s:_process_info[label] = {
\ 'logs': [], 'queries': a:initial_queries, 'vp': vp,
\ 'buffer_out': '', 'buffer_err': '', 'vars': {}}
endif
return label
endfunction
function! s:tick(label) abort
let pi = s:_process_info[a:label]
if len(pi.queries)
let qlabel = pi.queries[0][0]
if qlabel ==# '*read*'
let rname = pi.queries[0][1]
let rtil = pi.queries[0][2]
let [out, err] = [pi.vp.stdout.read(), pi.vp.stderr.read()]
call add(pi.logs, [rname, {'out': out, 'err': err}])
let pi.buffer_out .= out
let pi.buffer_err .= err
let pattern = "\\(^\\|\n\\)" . rtil . '$'
" wait ended.
if pi.buffer_out =~ pattern
if rname !=# '_'
let pi.vars[rname] = [
\ s:S.substitute_last(pi.buffer_out, pattern, ''),
\ pi.buffer_err]
endif
call remove(pi.queries, 0)
let pi.buffer_out = ''
let pi.buffer_err = ''
call s:tick(a:label)
endif
elseif qlabel ==# '*writeln*'
let wbody = pi.queries[0][1]
call pi.vp.stdin.write(wbody . "\n")
call remove(pi.queries, 0)
call s:tick(a:label)
else
" must not happen
throw printf("ProcessManager: must not happen")
endif
endif
endfunction
function! s:takeout(label, varname) abort
if has_key(s:_process_info[a:label].vars, a:varname)
let memo = s:_process_info[a:label].vars[a:varname]
call remove(s:_process_info[a:label].vars, a:varname)
return memo
else
return ['', '']
endif
endfunction
function! s:is_done(label, rname) abort
echomsg string([s:_process_info[a:label].buffer_out])
return s:L.all(
\ printf('v:val[0] ==# "*read*" && v:val[1] !=# %s', string(a:rname)),
\ s:_process_info[a:label].queries)
endfunction
function! s:queue(label, queries) abort
let s:_process_info[a:label].queries += a:queries
endfunction
function! s:log_clear(label) abort
let s:_process_info[a:label].logs = []
endfunction
function! s:log_prn(label) abort
echomsg '-----------------------------'
for x in s:_process_info[a:label].logs
echomsg string(x)
endfor
let s:_process_info[a:label].logs = []
endfunction
let &cpo = s:save_cpo
unlet s:save_cpo
" vim:set et ts=2 sts=2 sw=2 tw=0:
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment