" 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