112 lines
3.2 KiB
VimL
112 lines
3.2 KiB
VimL
|
if exists('g:autoloaded_copilot_job')
|
||
|
finish
|
||
|
endif
|
||
|
let g:autoloaded_copilot_job = 1
|
||
|
|
||
|
scriptencoding utf-8
|
||
|
|
||
|
function copilot#job#Nop(...) abort
|
||
|
endfunction
|
||
|
|
||
|
function! s:Jobs(job_or_jobs) abort
|
||
|
let jobs = type(a:job_or_jobs) == v:t_list ? copy(a:job_or_jobs) : [a:job_or_jobs]
|
||
|
call map(jobs, { k, v -> type(v) == v:t_dict ? get(v, 'job', '') : v })
|
||
|
call filter(jobs, { k, v -> type(v) !=# type('') })
|
||
|
return jobs
|
||
|
endfunction
|
||
|
|
||
|
let s:job_stop = exists('*job_stop') ? 'job_stop' : 'jobstop'
|
||
|
function! copilot#job#Stop(job) abort
|
||
|
for job in s:Jobs(a:job)
|
||
|
call call(s:job_stop, [job])
|
||
|
endfor
|
||
|
return copilot#job#Wait(a:job)
|
||
|
endfunction
|
||
|
|
||
|
let s:sleep = has('patch-8.2.2366') ? 'sleep! 1m' : 'sleep 1m'
|
||
|
function! copilot#job#Wait(jobs) abort
|
||
|
let jobs = s:Jobs(a:jobs)
|
||
|
if exists('*jobwait')
|
||
|
call jobwait(jobs)
|
||
|
else
|
||
|
for job in jobs
|
||
|
while ch_status(job) !=# 'closed' || job_status(job) ==# 'run'
|
||
|
exe s:sleep
|
||
|
endwhile
|
||
|
endfor
|
||
|
endif
|
||
|
return a:jobs
|
||
|
endfunction
|
||
|
|
||
|
function! s:VimExitCallback(result, exit_cb, job, data) abort
|
||
|
let a:result.exit_status = a:data
|
||
|
if !has_key(a:result, 'closed')
|
||
|
return
|
||
|
endif
|
||
|
call remove(a:result, 'closed')
|
||
|
call a:exit_cb(a:result.exit_status)
|
||
|
endfunction
|
||
|
|
||
|
function! s:VimCloseCallback(result, exit_cb, job) abort
|
||
|
if !has_key(a:result, 'exit_status')
|
||
|
let a:result.closed = v:true
|
||
|
return
|
||
|
endif
|
||
|
call a:exit_cb(a:result.exit_status)
|
||
|
endfunction
|
||
|
|
||
|
function! s:NvimCallback(cb, job, data, type) dict abort
|
||
|
let self[a:type][0] .= remove(a:data, 0)
|
||
|
call extend(self[a:type], a:data)
|
||
|
while len(self[a:type]) > 1
|
||
|
call a:cb(substitute(remove(self[a:type], 0), "\r$", '', ''))
|
||
|
endwhile
|
||
|
endfunction
|
||
|
|
||
|
function! s:NvimExitCallback(out_cb, err_cb, exit_cb, job, data, type) dict abort
|
||
|
if len(self.stderr[0])
|
||
|
call a:err_cb(substitute(self.stderr[0], "\r$", '', ''))
|
||
|
endif
|
||
|
call a:exit_cb(a:data)
|
||
|
endfunction
|
||
|
|
||
|
function! copilot#job#Cwd() abort
|
||
|
let home = expand("~")
|
||
|
if !isdirectory(home) && isdirectory($VIM)
|
||
|
return $VIM
|
||
|
endif
|
||
|
return home
|
||
|
endfunction
|
||
|
|
||
|
function! copilot#job#Stream(argv, out_cb, err_cb, ...) abort
|
||
|
let exit_status = []
|
||
|
let ExitCb = function(a:0 && !empty(a:1) ? a:1 : { e -> add(exit_status, e) }, a:000[2:-1])
|
||
|
let OutCb = function(empty(a:out_cb) ? 'copilot#job#Nop' : a:out_cb, a:000[2:-1])
|
||
|
let ErrCb = function(empty(a:err_cb) ? 'copilot#job#Nop' : a:err_cb, a:000[2:-1])
|
||
|
let state = {'headers': {}, 'mode': 'headers', 'buffer': ''}
|
||
|
if exists('*job_start')
|
||
|
let result = {}
|
||
|
let job = job_start(a:argv, {
|
||
|
\ 'cwd': copilot#job#Cwd(),
|
||
|
\ 'out_mode': 'raw',
|
||
|
\ 'out_cb': { j, d -> OutCb(d) },
|
||
|
\ 'err_cb': { j, d -> ErrCb(d) },
|
||
|
\ 'exit_cb': function('s:VimExitCallback', [result, ExitCb]),
|
||
|
\ 'close_cb': function('s:VimCloseCallback', [result, ExitCb]),
|
||
|
\ })
|
||
|
else
|
||
|
let jopts = {
|
||
|
\ 'cwd': copilot#job#Cwd(),
|
||
|
\ 'stderr': [''],
|
||
|
\ 'on_stdout': { j, d, t -> OutCb(join(d, "\n")) },
|
||
|
\ 'on_stderr': function('s:NvimCallback', [ErrCb]),
|
||
|
\ 'on_exit': function('s:NvimExitCallback', [OutCb, ErrCb, ExitCb])}
|
||
|
let job = jobstart(a:argv, jopts)
|
||
|
endif
|
||
|
if a:0
|
||
|
return job
|
||
|
endif
|
||
|
call copilot#job#Wait(job)
|
||
|
return exit_status[0]
|
||
|
endfunction
|