Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create modern jobs api for simple processes #2195

Closed
wants to merge 10 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 26 additions & 18 deletions autoload/vimtex/compiler/_template.vim
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ function! s:compiler.__pprint() abort dict " {{{1
if self.continuous
call add(l:job, ['pid', self.get_pid()])
endif
call add(l:list, ['process', l:job])
call add(l:list, ['job', l:job])
endif

return l:list
Expand All @@ -105,7 +105,7 @@ function! s:compiler.clean(full) abort dict " {{{1
call map(l:files, {_, x -> printf('%s/%s.%s',
\ self.build_dir, fnamemodify(self.state.tex, ':t:r:S'), x)})

call vimtex#process#run('rm -f ' . join(l:files))
call vimtex#jobs#run('rm -f ' . join(l:files), {'cwd': self.state.root})
endfunction

" }}}1
Expand Down Expand Up @@ -152,18 +152,6 @@ function! s:compiler.stop() abort dict " {{{1
endif
endfunction

" }}}1
function! s:compiler.wait() abort dict " {{{1
for l:dummy in range(50)
sleep 100m
if !self.is_running()
return
endif
endfor

call self.stop()
endfunction

" }}}1

function! s:compiler.create_build_dir() abort dict " {{{1
Expand Down Expand Up @@ -221,6 +209,7 @@ function! s:compiler_jobs.exec(cmd) abort dict " {{{1
\ 'err_io' : 'file',
\ 'out_name' : self.output,
\ 'err_name' : self.output,
\ 'cwd': self.state.root,
\}
if self.continuous
let l:options.out_io = 'pipe'
Expand All @@ -232,14 +221,23 @@ function! s:compiler_jobs.exec(cmd) abort dict " {{{1
let l:options.exit_cb = function('s:callback')
endif

call vimtex#paths#pushd(self.state.root)
let self.job = job_start(a:cmd, l:options)
call vimtex#paths#popd()
endfunction

" }}}1
function! s:compiler_jobs.kill() abort dict " {{{1
call job_stop(self.job)
sleep 25m
endfunction

" }}}1
function! s:compiler_jobs.wait() abort dict " {{{1
for l:dummy in range(500)
sleep 10m
if !self.is_running() | return | endif
endfor

call self.stop()
endfunction

" }}}1
Expand Down Expand Up @@ -300,13 +298,23 @@ function! s:compiler_nvim.kill() abort dict " {{{1
call jobstop(self.job)
endfunction

" }}}1
function! s:compiler_nvim.wait() abort dict " {{{1
let l:retvals = jobwait([self.job], 5000)
if empty(l:retvals) | return | endif
let l:status = l:retvals[0]
if l:status >= 0 | return | endif

if l:status == -1 | call self.stop() | endif
endfunction

" }}}1
function! s:compiler_nvim.is_running() abort dict " {{{1
try
let pid = jobpid(self.job)
return 1
return l:pid > 0
catch
return 0
return v:false
endtry
endfunction

Expand Down
7 changes: 2 additions & 5 deletions autoload/vimtex/compiler/latexmk.vim
Original file line number Diff line number Diff line change
Expand Up @@ -191,16 +191,13 @@ endfunction
" }}}1

function! s:compiler.clean(full) abort dict " {{{1
let l:cmd = (has('win32')
\ ? 'cd /D "' . self.state.root . '" & '
\ : 'cd ' . vimtex#util#shellescape(self.state.root) . '; ')
\ . self.executable . ' ' . (a:full ? '-C ' : '-c ')
let l:cmd = self.executable . ' ' . (a:full ? '-C ' : '-c ')
if !empty(self.build_dir)
let l:cmd .= printf(' -outdir=%s ', fnameescape(self.build_dir))
endif
let l:cmd .= vimtex#util#shellescape(self.state.base)

call vimtex#process#run(l:cmd)
call vimtex#jobs#run(l:cmd, {'cwd': self.state.root})
endfunction

" }}}1
Expand Down
10 changes: 3 additions & 7 deletions autoload/vimtex/compiler/latexrun.vim
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,9 @@ endfunction
" }}}1

function! s:compiler.clean(...) abort dict " {{{1
let l:cmd = (has('win32')
\ ? 'cd /D "' . self.state.root . '" & '
\ : 'cd ' . vimtex#util#shellescape(self.state.root) . '; ')
\ . 'latexrun --clean-all'
\ . ' -O '
\ . (empty(self.build_dir) ? '.' : fnameescape(self.build_dir))
call vimtex#process#run(l:cmd)
let l:cmd = printf('latexrun --clean-all -O %s',
\ empty(self.build_dir) ? '.' : fnameescape(self.build_dir))
call vimtex#jobs#run(l:cmd, {'cwd': self.state.root})
endfunction

" }}}1
Expand Down
2 changes: 1 addition & 1 deletion autoload/vimtex/context/cite.vim
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ function! s:actions.open_pdf() abort dict " {{{1
\})
if empty(l:file) | return | endif

call vimtex#process#start(
call vimtex#jobs#start(
\ g:vimtex_context_pdf_viewer
\ . ' ' . vimtex#util#shellescape(l:file))
endfunction
Expand Down
2 changes: 1 addition & 1 deletion autoload/vimtex/info.vim
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ function! s:get_os_info() abort " {{{1
return l:name . ' ' . l:version . ' (' . l:build . ')'
else
if !exists('s:win_info')
let s:win_info = vimtex#process#capture('systeminfo')
let s:win_info = vimtex#jobs#capture('systeminfo')
endif

try
Expand Down
214 changes: 214 additions & 0 deletions autoload/vimtex/jobs.vim
Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@
" VimTeX - LaTeX plugin for Vim
"
" Maintainer: Karl Yngve Lervåg
" Email: karl.yngve@gmail.com
"

function! vimtex#jobs#start(cmd, ...) abort " {{{1
let l:opts = a:0 > 0 ? a:1 : {}
return s:job.start(a:cmd, l:opts)
endfunction

" }}}1
function! vimtex#jobs#run(cmd, ...) abort " {{{1
let l:opts = a:0 > 0 ? a:1 : {}
let l:job = s:job.start(a:cmd, l:opts)
call l:job.wait()
endfunction

" }}}1
function! vimtex#jobs#capture(cmd, ...) abort " {{{1
let l:opts = a:0 > 0 ? a:1 : {}
let l:opts.collect_output = v:true
let l:job = s:job.start(a:cmd, l:opts)
return l:job.output()
endfunction

" }}}1


let s:job = {}

function! s:job.start(cmd, opts) abort dict " {{{1
let l:job = deepcopy(self)
unlet l:job.start

let l:job.cmd_raw = a:cmd
let l:job.cwd = get(a:opts, 'cwd',
\ exists('b:vimtex.root') ? b:vimtex.root : '')
let l:job.wait_timeout = str2nr(get(a:opts, 'wait_timeout', 5000))
let l:job.collect_output = get(a:opts, 'collect_output', v:false)

let l:job.cmd = has('win32')
\ ? 'cmd /s /c "' . l:job.cmd_raw . '"'
\ : ['sh', '-c', l:job.cmd_raw]

call l:job.exec()

return l:job
endfunction

" }}}1

function! s:job.__pprint() abort dict " {{{1
let l:pid = self.get_pid()

return [
\ ['pid', l:pid ? l:pid : '-'],
\ ['cmd', self.cmd_raw],
\]
endfunction

" }}}1

if has('nvim')
function! s:job.exec() abort dict " {{{1
let l:options = {}

if self.collect_output
let self._output = []
let l:options.on_stdout = function('s:__callback')
let l:options.on_stderr = function('s:__callback')
let l:options.stdout_buffered = v:true
let l:options.stderr_buffered = v:true
let l:options.output = self._output
endif
if !empty(self.cwd)
let l:options.cwd = self.cwd
endif

let self.job = jobstart(self.cmd, l:options)
endfunction

function! s:__callback(id, data, event) abort dict
call extend(self.output, a:data)
endfunction

" }}}1
function! s:job.stop() abort dict " {{{1
call jobstop(self.job)
endfunction

" }}}1
function! s:job.wait() abort dict " {{{1
let l:retvals = jobwait([self.job], self.wait_timeout)
if empty(l:retvals) | return | endif
let l:status = l:retvals[0]
if l:status >= 0 | return | endif

if l:status == -1
call vimtex#log#warning('Job timed out while waiting!', join(self.cmd))
call self.stop()
elseif l:status == -2
call vimtex#log#warning('Job interrupted!', self.cmd)
endif
endfunction

" }}}1
function! s:job.is_running() abort dict " {{{1
try
let l:pid = jobpid(self.job)
return l:pid > 0
catch
return v:false
endtry
endfunction

" }}}1
function! s:job.get_pid() abort dict " {{{1
if !has_key(self, 'pid')
try
let self.pid = jobpid(self.job)
catch
let self.pid = 0
endtry
endif

return self.pid
endfunction

" }}}1
function! s:job.output() abort dict " {{{1
call self.wait()

if !self.collect_output | return [] | endif

" Trim output
while len(self._output) > 0
if !empty(self._output[0]) | break | endif
call remove(self._output, 0)
endwhile
while len(self._output) > 0
if !empty(self._output[-1]) | break | endif
call remove(self._output, -1)
endwhile

return self._output
endfunction

" }}}1
else
function! s:job.exec() abort dict " {{{1
let l:options = {}

if self.collect_output
let self._output = tempname()
let l:options.out_io = 'file'
let l:options.err_io = 'file'
let l:options.out_name = self._output
let l:options.err_name = self._output
else
let l:options.in_io = 'null'
let l:options.out_io = 'null'
let l:options.err_io = 'null'
endif
if !empty(self.cwd)
let l:options.cwd = self.cwd
endif

let self.job = job_start(self.cmd, l:options)
endfunction

" }}}1
function! s:job.stop() abort dict " {{{1
call job_stop(self.job)
sleep 25m
endfunction

" }}}1
function! s:job.wait() abort dict " {{{1
for l:dummy in range(self.wait_timeout/10)
sleep 10m
if !self.is_running() | return | endif
endfor

call vimtex#log#warning('Job timed out while waiting!', join(self.cmd))
call self.stop()
endfunction

" }}}1
function! s:job.is_running() abort dict " {{{1
return job_status(self.job) ==# 'run'
endfunction

" }}}1
function! s:job.get_pid() abort dict " {{{1
if !has_key(self, 'pid')
try
return get(job_info(self.job), 'process')
catch
return 0
endtry
endif

return self.pid
endfunction

" }}}1
function! s:job.output() abort dict " {{{1
call self.wait()
return self.collect_output ? readfile(self._output) : []
endfunction

" }}}1
endif
2 changes: 1 addition & 1 deletion autoload/vimtex/kpsewhich.vim
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ function! vimtex#kpsewhich#run(args) abort " {{{1
if exists('b:vimtex.root')
call vimtex#paths#pushd(b:vimtex.root)
endif
let l:output = vimtex#process#capture('kpsewhich ' . a:args)
let l:output = vimtex#jobs#capture('kpsewhich ' . a:args)
if exists('b:vimtex.root')
call vimtex#paths#popd()
endif
Expand Down
Loading