1
0
mirror of https://github.com/SpaceVim/SpaceVim.git synced 2025-02-04 01:00:04 +08:00
SpaceVim/bundle/dein.vim/autoload/vital/_dein/System/Job/Vim.vim

154 lines
4.6 KiB
VimL
Raw Normal View History

2020-06-13 14:06:35 +08:00
" ___vital___
" NOTE: lines between '" ___vital___' is generated by :Vitalize.
" Do not modify the code nor insert new lines before '" ___vital___'
2020-06-13 14:06:35 +08:00
function! s:_SID() abort
return matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze__SID$')
endfunction
execute join(['function! vital#_dein#System#Job#Vim#import() abort', printf("return map({'is_available': '', 'start': ''}, \"vital#_dein#function('<SNR>%s_' . v:key)\")", s:_SID()), 'endfunction'], "\n")
delfunction s:_SID
" ___vital___
" https://github.com/neovim/neovim/blob/f629f83/src/nvim/event/process.c#L24-L26
let s:KILL_TIMEOUT_MS = 2000
function! s:is_available() abort
return !has('nvim') && has('patch-8.0.0027')
endfunction
function! s:start(args, options) abort
let job = extend(copy(s:job), a:options)
let job_options = {
\ 'mode': 'raw',
\ 'timeout': 0,
\}
if has('patch-8.1.889')
let job_options['noblock'] = 1
endif
2020-06-13 14:06:35 +08:00
if has_key(job, 'on_stdout')
let job_options.out_cb = funcref('s:_out_cb', [job])
2020-06-13 14:06:35 +08:00
else
let job_options.out_io = 'null'
endif
if has_key(job, 'on_stderr')
let job_options.err_cb = funcref('s:_err_cb', [job])
2020-06-13 14:06:35 +08:00
else
let job_options.err_io = 'null'
endif
if has_key(job, 'on_exit')
let job_options.exit_cb = funcref('s:_exit_cb', [job])
2020-06-13 14:06:35 +08:00
endif
if has_key(job, 'cwd') && has('patch-8.0.0902')
let job_options.cwd = job.cwd
endif
if has_key(job, 'env') && has('patch-8.0.0902')
let job_options.env = job.env
endif
2020-06-13 14:06:35 +08:00
let job.__job = job_start(a:args, job_options)
let job.args = a:args
return job
endfunction
function! s:_out_cb(job, channel, msg) abort
call a:job.on_stdout(split(a:msg, "\n", 1))
endfunction
function! s:_err_cb(job, channel, msg) abort
call a:job.on_stderr(split(a:msg, "\n", 1))
endfunction
function! s:_exit_cb(job, channel, exitval) abort
" Make sure on_stdout/on_stderr are called prior to on_exit.
if has_key(a:job, 'on_stdout')
let options = {'part': 'out'}
while ch_status(a:channel, options) ==# 'open'
sleep 1m
endwhile
while ch_status(a:channel, options) ==# 'buffered'
call s:_out_cb(a:job, a:channel, ch_readraw(a:channel, options))
endwhile
endif
if has_key(a:job, 'on_stderr')
let options = {'part': 'err'}
while ch_status(a:channel, options) ==# 'open'
sleep 1m
endwhile
while ch_status(a:channel, options) ==# 'buffered'
call s:_err_cb(a:job, a:channel, ch_readraw(a:channel, options))
endwhile
endif
call a:job.on_exit(a:exitval)
endfunction
" Instance -------------------------------------------------------------------
function! s:_job_id() abort dict
if &verbose
echohl WarningMsg
echo 'vital: System.Job: job.id() is deprecated. Use job.pid() instead.'
echohl None
endif
return self.pid()
endfunction
function! s:_job_pid() abort dict
return job_info(self.__job).process
endfunction
" NOTE:
" On Unix a non-existing command results in "dead" instead
" So returns "dead" instead of "fail" even in non Unix.
function! s:_job_status() abort dict
let status = job_status(self.__job)
return status ==# 'fail' ? 'dead' : status
endfunction
" NOTE:
" A Null character (\0) is used as a terminator of a string in Vim.
" Neovim can send \0 by using \n splitted list but in Vim.
" So replace all \n in \n splitted list to ''
function! s:_job_send(data) abort dict
let data = type(a:data) == v:t_list
2020-06-13 14:06:35 +08:00
\ ? join(map(a:data, 'substitute(v:val, "\n", '''', ''g'')'), "\n")
\ : a:data
return ch_sendraw(self.__job, data)
endfunction
function! s:_job_close() abort dict
call ch_close_in(self.__job)
endfunction
function! s:_job_stop() abort dict
call job_stop(self.__job)
call timer_start(s:KILL_TIMEOUT_MS, { -> job_stop(self.__job, 'kill') })
endfunction
function! s:_job_wait(...) abort dict
let timeout = a:0 ? a:1 : v:null
let timeout = timeout is# v:null ? v:null : timeout / 1000.0
let start_time = reltime()
let job = self.__job
try
while timeout is# v:null || timeout > reltimefloat(reltime(start_time))
let status = job_status(job)
if status !=# 'run'
return status ==# 'dead' ? job_info(job).exitval : -3
endif
sleep 1m
endwhile
catch /^Vim:Interrupt$/
call self.stop()
return -2
endtry
return -1
endfunction
" To make debug easier, use funcref instead.
let s:job = {
\ 'id': funcref('s:_job_id'),
\ 'pid': funcref('s:_job_pid'),
\ 'status': funcref('s:_job_status'),
\ 'send': funcref('s:_job_send'),
\ 'close': funcref('s:_job_close'),
\ 'stop': funcref('s:_job_stop'),
\ 'wait': funcref('s:_job_wait'),
2020-06-13 14:06:35 +08:00
\}