1
0
mirror of https://github.com/SpaceVim/SpaceVim.git synced 2025-01-24 09:40:06 +08:00
SpaceVim/bundle/vim-dispatch/autoload/dispatch/job.vim

143 lines
4.0 KiB
VimL
Vendored

" dispatch.vim job strategy
if exists('g:autoloaded_dispatch_job')
finish
endif
let g:autoloaded_dispatch_job = 1
if !exists('s:waiting')
let s:waiting = {}
endif
let g:dispatch_waiting_jobs = s:waiting
function! dispatch#job#handle(request) abort
if !get(g:, 'dispatch_experimental', 1)
return 0
endif
if a:request.action !=# 'make'
return 0
endif
if exists('*job_start')
if has('win32')
let cmd = &shell . ' ' . &shellcmdflag . ' ' . dispatch#windows#escape(a:request.expanded)
else
let cmd = split(&shell) + split(&shellcmdflag) + [a:request.expanded]
endif
let job = job_start(cmd, {
\ 'mode': 'raw',
\ 'callback': function('s:output'),
\ 'close_cb': function('s:closed'),
\ 'exit_cb': function('s:exit'),
\ })
call ch_close_in(job)
let a:request.pid = job_info(job).process
let a:request.job = job
let ch_id = ch_info(job_info(job).channel).id
let s:waiting[ch_id] = {'request': a:request, 'output': ['']}
elseif exists('*jobpid') && exists('*jobstart')
let job_id = jobstart(a:request.expanded, {
\ 'on_stdout': function('s:output'),
\ 'on_stderr': function('s:output'),
\ 'on_exit': function('s:complete'),
\ })
call chanclose(job_id, 'stdin')
let a:request.pid = jobpid(job_id)
let a:request.job = job_id
let s:waiting[job_id] = {'request': a:request, 'output': ['']}
else
return 0
endif
let a:request.handler = 'job'
call writefile([], a:request.file)
call writefile([a:request.pid], a:request.file . '.pid')
return 2
endfunction
function! s:complete(id, status, ...) abort
let waiting = remove(s:waiting, a:id)
call writefile([a:status], waiting.request.file . '.complete')
call DispatchComplete(waiting.request.id)
endfunction
function! s:closed(ch) abort
let id = ch_info(a:ch).id
if has_key(s:waiting, id) && has_key(s:waiting[id], 'exit_status')
call s:complete(id, s:waiting[id].exit_status)
endif
endfunction
function! s:exit(job, status) abort
let ch = job_info(a:job).channel
let info = ch_info(ch)
if info.status ==# 'closed'
return s:complete(info.id, a:status)
else
let s:waiting[info.id].exit_status = a:status
endif
endfunction
function! s:output(ch, output, ...) abort
if a:0
" nvim
let waiting = s:waiting[a:ch]
let output = a:output
else
" vim
let waiting = s:waiting[ch_info(a:ch).id]
let output = split(a:output, "\n", 1)
endif
let request = waiting.request
call writefile(output, request.file, 'ab')
let waiting.output[-1] .= remove(output, 0)
call extend(waiting.output, output)
if dispatch#request(get(getqflist({'title': 1}), 'title', '')) is# request && len(waiting.output) > 1
let lefm = &l:efm
let gefm = &g:efm
let makeprg = &l:makeprg
let compiler = get(b:, 'current_compiler', '')
let cd = exists('*haslocaldir') && haslocaldir() ? 'lcd' : exists(':tcd') && haslocaldir(-1) ? 'tcd' : 'cd'
let dir = getcwd()
let modelines = &modelines
try
let &modelines = 0
let b:current_compiler = get(request, 'compiler', '')
if empty(b:current_compiler)
unlet! b:current_compiler
endif
exe cd fnameescape(request.directory)
let &l:efm = request.format
let &g:efm = request.format
let &l:makeprg = request.command
caddexpr remove(waiting.output, 0, -2)
finally
let &modelines = modelines
exe cd fnameescape(dir)
let &l:efm = lefm
let &g:efm = gefm
let &l:makeprg = makeprg
if empty(compiler)
unlet! b:current_compiler
else
let b:current_compiler = compiler
endif
endtry
cbottom
endif
endfunction
function! dispatch#job#kill(pid, force) abort
let request = dispatch#request('job/' . a:pid)
if exists('*job_stop')
return job_stop(request.job, a:force ? 'kill' : 'hup')
elseif exists('*jobstop')
call jobstop(request.job)
return 1
endif
endfunction
function! dispatch#job#activate(pid) abort
return 0
endfunction