mirror of
https://github.com/sheerun/vim-polyglot.git
synced 2025-11-11 21:13:50 -05:00
Change latex provider to luatex, closes #476
This commit is contained in:
218
autoload/vimtex/compiler/arara.vim
Normal file
218
autoload/vimtex/compiler/arara.vim
Normal file
@@ -0,0 +1,218 @@
|
||||
if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'latex') == -1
|
||||
|
||||
" vimtex - LaTeX plugin for Vim
|
||||
"
|
||||
" Maintainer: Karl Yngve Lervåg
|
||||
" Email: karl.yngve@gmail.com
|
||||
"
|
||||
|
||||
function! vimtex#compiler#arara#init(options) abort " {{{1
|
||||
let l:compiler = deepcopy(s:compiler)
|
||||
|
||||
call l:compiler.init(extend(a:options,
|
||||
\ get(g:, 'vimtex_compiler_arara', {}), 'keep'))
|
||||
|
||||
return l:compiler
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
|
||||
let s:compiler = {
|
||||
\ 'name' : 'arara',
|
||||
\ 'backend' : has('nvim') ? 'nvim'
|
||||
\ : v:version >= 800 ? 'jobs' : 'process',
|
||||
\ 'root' : '',
|
||||
\ 'target' : '',
|
||||
\ 'target_path' : '',
|
||||
\ 'background' : 1,
|
||||
\ 'output' : tempname(),
|
||||
\ 'options' : ['--log'],
|
||||
\}
|
||||
|
||||
function! s:compiler.init(options) abort dict " {{{1
|
||||
call extend(self, a:options)
|
||||
|
||||
if !executable('arara')
|
||||
call vimtex#log#warning('arara is not executable!')
|
||||
throw 'vimtex: Requirements not met'
|
||||
endif
|
||||
|
||||
call extend(self, deepcopy(s:compiler_{self.backend}))
|
||||
|
||||
" Processes run with the new jobs api will not run in the foreground
|
||||
if self.backend !=# 'process'
|
||||
let self.background = 1
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
|
||||
function! s:compiler.build_cmd() abort dict " {{{1
|
||||
let l:cmd = 'arara'
|
||||
|
||||
for l:opt in self.options
|
||||
let l:cmd .= ' ' . l:opt
|
||||
endfor
|
||||
|
||||
return l:cmd . ' ' . vimtex#util#shellescape(self.target)
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
function! s:compiler.cleanup() abort dict " {{{1
|
||||
" Pass
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
function! s:compiler.pprint_items() abort dict " {{{1
|
||||
let l:configuration = []
|
||||
|
||||
if self.backend ==# 'process'
|
||||
call add(l:configuration, ['background', self.background])
|
||||
endif
|
||||
|
||||
call add(l:configuration, ['arara options', self.options])
|
||||
|
||||
let l:list = []
|
||||
call add(l:list, ['backend', self.backend])
|
||||
if self.background
|
||||
call add(l:list, ['output', self.output])
|
||||
endif
|
||||
|
||||
if self.target_path !=# b:vimtex.tex
|
||||
call add(l:list, ['root', self.root])
|
||||
call add(l:list, ['target', self.target_path])
|
||||
endif
|
||||
|
||||
call add(l:list, ['configuration', l:configuration])
|
||||
|
||||
if has_key(self, 'process')
|
||||
call add(l:list, ['process', self.process])
|
||||
endif
|
||||
|
||||
if has_key(self, 'job')
|
||||
call add(l:list, ['cmd', self.cmd])
|
||||
endif
|
||||
|
||||
return l:list
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
|
||||
function! s:compiler.clean(...) abort dict " {{{1
|
||||
call vimtex#log#warning('Clean not implemented for arara')
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
function! s:compiler.start(...) abort dict " {{{1
|
||||
call self.exec()
|
||||
|
||||
if self.background
|
||||
call vimtex#log#info('Compiler started in background')
|
||||
else
|
||||
call vimtex#compiler#callback(!vimtex#qf#inquire(self.target))
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
function! s:compiler.start_single() abort dict " {{{1
|
||||
call self.start()
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
function! s:compiler.stop() abort dict " {{{1
|
||||
" Pass
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
function! s:compiler.is_running() abort dict " {{{1
|
||||
return 0
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
function! s:compiler.kill() abort dict " {{{1
|
||||
" Pass
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
function! s:compiler.get_pid() abort dict " {{{1
|
||||
return 0
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
|
||||
let s:compiler_process = {}
|
||||
function! s:compiler_process.exec() abort dict " {{{1
|
||||
let self.process = vimtex#process#new()
|
||||
let self.process.name = 'arara'
|
||||
let self.process.background = self.background
|
||||
let self.process.workdir = self.root
|
||||
let self.process.output = self.output
|
||||
let self.process.cmd = self.build_cmd()
|
||||
call self.process.run()
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
|
||||
let s:compiler_jobs = {}
|
||||
function! s:compiler_jobs.exec() abort dict " {{{1
|
||||
let self.cmd = self.build_cmd()
|
||||
let l:cmd = has('win32')
|
||||
\ ? 'cmd /s /c "' . self.cmd . '"'
|
||||
\ : ['sh', '-c', self.cmd]
|
||||
let l:options = {
|
||||
\ 'out_io' : 'file',
|
||||
\ 'err_io' : 'file',
|
||||
\ 'out_name' : self.output,
|
||||
\ 'err_name' : self.output,
|
||||
\}
|
||||
|
||||
let s:cb_target = self.target_path !=# b:vimtex.tex ? self.target_path : ''
|
||||
let l:options.exit_cb = function('s:callback')
|
||||
|
||||
call vimtex#paths#pushd(self.root)
|
||||
let self.job = job_start(l:cmd, l:options)
|
||||
call vimtex#paths#popd()
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
function! s:callback(ch, msg) abort " {{{1
|
||||
call vimtex#compiler#callback(!vimtex#qf#inquire(s:cb_target))
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
|
||||
let s:compiler_nvim = {}
|
||||
function! s:compiler_nvim.exec() abort dict " {{{1
|
||||
let self.cmd = self.build_cmd()
|
||||
let l:cmd = has('win32')
|
||||
\ ? 'cmd /s /c "' . self.cmd . '"'
|
||||
\ : ['sh', '-c', self.cmd]
|
||||
|
||||
let l:shell = {
|
||||
\ 'on_stdout' : function('s:callback_nvim_output'),
|
||||
\ 'on_stderr' : function('s:callback_nvim_output'),
|
||||
\ 'on_exit' : function('s:callback_nvim_exit'),
|
||||
\ 'cwd' : self.root,
|
||||
\ 'target' : self.target_path,
|
||||
\ 'output' : self.output,
|
||||
\}
|
||||
|
||||
let self.job = jobstart(l:cmd, l:shell)
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
function! s:callback_nvim_output(id, data, event) abort dict " {{{1
|
||||
if !empty(a:data)
|
||||
call writefile(filter(a:data, '!empty(v:val)'), self.output, 'a')
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
function! s:callback_nvim_exit(id, data, event) abort dict " {{{1
|
||||
let l:target = self.target !=# b:vimtex.tex ? self.target : ''
|
||||
call vimtex#compiler#callback(!vimtex#qf#inquire(l:target))
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
|
||||
endif
|
||||
700
autoload/vimtex/compiler/latexmk.vim
Normal file
700
autoload/vimtex/compiler/latexmk.vim
Normal file
@@ -0,0 +1,700 @@
|
||||
if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'latex') == -1
|
||||
|
||||
" vimtex - LaTeX plugin for Vim
|
||||
"
|
||||
" Maintainer: Karl Yngve Lervåg
|
||||
" Email: karl.yngve@gmail.com
|
||||
"
|
||||
|
||||
function! vimtex#compiler#latexmk#init(options) abort " {{{1
|
||||
let l:compiler = deepcopy(s:compiler)
|
||||
|
||||
call l:compiler.init(extend(a:options,
|
||||
\ get(g:, 'vimtex_compiler_latexmk', {}), 'keep'))
|
||||
|
||||
return l:compiler
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
function! vimtex#compiler#latexmk#wrap_option(name, value) abort " {{{1
|
||||
return has('win32')
|
||||
\ ? ' -e "$' . a:name . ' = ''' . a:value . '''"'
|
||||
\ : ' -e ''$' . a:name . ' = "' . a:value . '"'''
|
||||
endfunction
|
||||
|
||||
"}}}1
|
||||
|
||||
function! vimtex#compiler#latexmk#get_rc_opt(root, opt, type, default) abort " {{{1
|
||||
"
|
||||
" Parse option from .latexmkrc.
|
||||
"
|
||||
" Arguments:
|
||||
" root Root of LaTeX project
|
||||
" opt Name of options
|
||||
" type 0 if string, 1 if integer, 2 if list
|
||||
" default Value to return if option not found in latexmkrc file
|
||||
"
|
||||
" Output:
|
||||
" [value, location]
|
||||
"
|
||||
" value Option value (integer or string)
|
||||
" location An integer that indicates where option was found
|
||||
" -1: not found (default value returned)
|
||||
" 0: global latexmkrc file
|
||||
" 1: local latexmkrc file
|
||||
"
|
||||
|
||||
if a:type == 0
|
||||
let l:pattern = '^\s*\$' . a:opt . '\s*=\s*[''"]\(.\+\)[''"]'
|
||||
elseif a:type == 1
|
||||
let l:pattern = '^\s*\$' . a:opt . '\s*=\s*\(\d\+\)'
|
||||
elseif a:type == 2
|
||||
let l:pattern = '^\s*@' . a:opt . '\s*=\s*(\(.*\))'
|
||||
else
|
||||
throw 'vimtex: argument error'
|
||||
endif
|
||||
|
||||
" Candidate files
|
||||
" - each element is a pair [path_to_file, is_local_rc_file].
|
||||
let l:files = [
|
||||
\ [a:root . '/latexmkrc', 1],
|
||||
\ [a:root . '/.latexmkrc', 1],
|
||||
\ [fnamemodify('~/.latexmkrc', ':p'), 0],
|
||||
\]
|
||||
if !empty($XDG_CONFIG_HOME)
|
||||
call add(l:files, [$XDG_CONFIG_HOME . '/latexmk/latexmkrc', 0])
|
||||
endif
|
||||
|
||||
let l:result = [a:default, -1]
|
||||
|
||||
for [l:file, l:is_local] in l:files
|
||||
if filereadable(l:file)
|
||||
let l:match = matchlist(readfile(l:file), l:pattern)
|
||||
if len(l:match) > 1
|
||||
let l:result = [l:match[1], l:is_local]
|
||||
break
|
||||
end
|
||||
endif
|
||||
endfor
|
||||
|
||||
" Parse the list
|
||||
if a:type == 2 && l:result[1] > -1
|
||||
let l:array = split(l:result[0], ',')
|
||||
let l:result[0] = []
|
||||
for l:x in l:array
|
||||
let l:x = substitute(l:x, "^'", '', '')
|
||||
let l:x = substitute(l:x, "'$", '', '')
|
||||
let l:result[0] += [l:x]
|
||||
endfor
|
||||
endif
|
||||
|
||||
return l:result
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
|
||||
let s:compiler = {
|
||||
\ 'name' : 'latexmk',
|
||||
\ 'executable' : 'latexmk',
|
||||
\ 'backend' : has('nvim') ? 'nvim'
|
||||
\ : v:version >= 800 ? 'jobs' : 'process',
|
||||
\ 'root' : '',
|
||||
\ 'target' : '',
|
||||
\ 'target_path' : '',
|
||||
\ 'background' : 1,
|
||||
\ 'build_dir' : '',
|
||||
\ 'callback' : 1,
|
||||
\ 'continuous' : 1,
|
||||
\ 'output' : tempname(),
|
||||
\ 'options' : [
|
||||
\ '-verbose',
|
||||
\ '-file-line-error',
|
||||
\ '-synctex=1',
|
||||
\ '-interaction=nonstopmode',
|
||||
\ ],
|
||||
\ 'hooks' : [],
|
||||
\ 'shell' : fnamemodify(&shell, ':t'),
|
||||
\}
|
||||
|
||||
function! s:compiler.init(options) abort dict " {{{1
|
||||
call extend(self, a:options)
|
||||
|
||||
call self.init_check_requirements()
|
||||
call self.init_build_dir_option()
|
||||
call self.init_pdf_mode_option()
|
||||
|
||||
call extend(self, deepcopy(s:compiler_{self.backend}))
|
||||
|
||||
" Continuous processes can't run in foreground, neither can processes run
|
||||
" with the new jobs api
|
||||
if self.continuous || self.backend !=# 'process'
|
||||
let self.background = 1
|
||||
endif
|
||||
|
||||
if self.backend !=# 'process'
|
||||
let self.shell = 'sh'
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
function! s:compiler.init_build_dir_option() abort dict " {{{1
|
||||
"
|
||||
" Check if .latexmkrc sets the build_dir - if so this should be respected
|
||||
"
|
||||
let l:out_dir =
|
||||
\ vimtex#compiler#latexmk#get_rc_opt(self.root, 'out_dir', 0, '')[0]
|
||||
|
||||
if !empty(l:out_dir)
|
||||
if !empty(self.build_dir) && (self.build_dir !=# l:out_dir)
|
||||
call vimtex#log#warning(
|
||||
\ 'Setting out_dir from latexmkrc overrides build_dir!',
|
||||
\ 'Changed build_dir from: ' . self.build_dir,
|
||||
\ 'Changed build_dir to: ' . l:out_dir)
|
||||
endif
|
||||
let self.build_dir = l:out_dir
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
function! s:compiler.init_pdf_mode_option() abort dict " {{{1
|
||||
" If the TeX program directive was not set, and if the pdf_mode is set in
|
||||
" a .latexmkrc file, then deduce the compiler engine from the value of
|
||||
" pdf_mode.
|
||||
|
||||
" Parse the pdf_mode option. If not found, it is set to -1.
|
||||
let [l:pdf_mode, l:is_local] =
|
||||
\ vimtex#compiler#latexmk#get_rc_opt(self.root, 'pdf_mode', 1, -1)
|
||||
|
||||
" If pdf_mode has a supported value (1: pdflatex, 4: lualatex, 5: xelatex),
|
||||
" override the value of self.tex_program.
|
||||
if l:pdf_mode == 1
|
||||
let l:tex_program = 'pdflatex'
|
||||
elseif l:pdf_mode == 3
|
||||
let l:tex_program = 'pdfdvi'
|
||||
elseif l:pdf_mode == 4
|
||||
let l:tex_program = 'lualatex'
|
||||
elseif l:pdf_mode == 5
|
||||
let l:tex_program = 'xelatex'
|
||||
else
|
||||
return
|
||||
endif
|
||||
|
||||
if self.tex_program ==# '_'
|
||||
" The TeX program directive was not specified
|
||||
let self.tex_program = l:tex_program
|
||||
elseif l:is_local && self.tex_program !=# l:tex_program
|
||||
call vimtex#log#warning(
|
||||
\ 'Value of pdf_mode from latexmkrc is inconsistent with ' .
|
||||
\ 'TeX program directive!',
|
||||
\ 'TeX program: ' . self.tex_program,
|
||||
\ 'pdf_mode: ' . l:tex_program,
|
||||
\ 'The value of pdf_mode will be ignored.')
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
function! s:compiler.init_check_requirements() abort dict " {{{1
|
||||
" Check option validity
|
||||
if self.callback
|
||||
if !(has('clientserver') || has('nvim') || has('job'))
|
||||
let self.callback = 0
|
||||
call vimtex#log#warning(
|
||||
\ 'Can''t use callbacks without +job, +nvim, or +clientserver',
|
||||
\ 'Callback option has been disabled.')
|
||||
endif
|
||||
endif
|
||||
|
||||
" Check for required executables
|
||||
let l:required = [self.executable]
|
||||
if self.continuous && !(has('win32') || has('win32unix'))
|
||||
let l:required += ['pgrep']
|
||||
endif
|
||||
let l:missing = filter(l:required, '!executable(v:val)')
|
||||
|
||||
" Disable latexmk if required programs are missing
|
||||
if len(l:missing) > 0
|
||||
for l:cmd in l:missing
|
||||
call vimtex#log#warning(l:cmd . ' is not executable')
|
||||
endfor
|
||||
throw 'vimtex: Requirements not met'
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
|
||||
function! s:compiler.build_cmd() abort dict " {{{1
|
||||
if has('win32')
|
||||
let l:cmd = 'set max_print_line=2000 & ' . self.executable
|
||||
else
|
||||
if self.shell ==# 'fish'
|
||||
let l:cmd = 'set max_print_line 2000; and ' . self.executable
|
||||
else
|
||||
let l:cmd = 'max_print_line=2000 ' . self.executable
|
||||
endif
|
||||
endif
|
||||
|
||||
for l:opt in self.options
|
||||
let l:cmd .= ' ' . l:opt
|
||||
endfor
|
||||
|
||||
let l:cmd .= ' ' . self.get_engine()
|
||||
|
||||
if !empty(self.build_dir)
|
||||
let l:cmd .= ' -outdir=' . fnameescape(self.build_dir)
|
||||
endif
|
||||
|
||||
if self.continuous
|
||||
let l:cmd .= ' -pvc'
|
||||
|
||||
" Set viewer options
|
||||
if !get(g:, 'vimtex_view_automatic', 1)
|
||||
\ || get(get(b:vimtex, 'viewer', {}), 'xwin_id') > 0
|
||||
\ || get(s:, 'silence_next_callback', 0)
|
||||
let l:cmd .= ' -view=none'
|
||||
elseif g:vimtex_view_enabled
|
||||
\ && has_key(b:vimtex.viewer, 'latexmk_append_argument')
|
||||
let l:cmd .= b:vimtex.viewer.latexmk_append_argument()
|
||||
endif
|
||||
|
||||
if self.callback
|
||||
if has('job') || has('nvim')
|
||||
for [l:opt, l:val] in items({
|
||||
\ 'success_cmd' : 'vimtex_compiler_callback_success',
|
||||
\ 'failure_cmd' : 'vimtex_compiler_callback_failure',
|
||||
\})
|
||||
let l:func = 'echo ' . l:val
|
||||
let l:cmd .= vimtex#compiler#latexmk#wrap_option(l:opt, l:func)
|
||||
endfor
|
||||
elseif empty(v:servername)
|
||||
call vimtex#log#warning('Can''t use callbacks with empty v:servername')
|
||||
else
|
||||
" Some notes:
|
||||
" - We excape the v:servername because this seems necessary on Windows
|
||||
" for neovim, see e.g. Github Issue #877
|
||||
for [l:opt, l:val] in items({'success_cmd' : 1, 'failure_cmd' : 0})
|
||||
let l:callback = has('win32')
|
||||
\ ? '"vimtex#compiler#callback(' . l:val . ')"'
|
||||
\ : '\"vimtex\#compiler\#callback(' . l:val . ')\"'
|
||||
let l:func = vimtex#util#shellescape('""')
|
||||
\ . g:vimtex_compiler_progname
|
||||
\ . vimtex#util#shellescape('""')
|
||||
\ . ' --servername ' . vimtex#util#shellescape(v:servername)
|
||||
\ . ' --remote-expr ' . l:callback
|
||||
let l:cmd .= vimtex#compiler#latexmk#wrap_option(l:opt, l:func)
|
||||
endfor
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
return l:cmd . ' ' . vimtex#util#shellescape(self.target)
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
function! s:compiler.get_engine() abort dict " {{{1
|
||||
return get(extend(g:vimtex_compiler_latexmk_engines,
|
||||
\ {
|
||||
\ 'pdfdvi' : '-pdfdvi',
|
||||
\ 'pdflatex' : '-pdf',
|
||||
\ 'luatex' : '-lualatex',
|
||||
\ 'lualatex' : '-lualatex',
|
||||
\ 'xelatex' : '-xelatex',
|
||||
\ 'context (pdftex)' : '-pdf -pdflatex=texexec',
|
||||
\ 'context (luatex)' : '-pdf -pdflatex=context',
|
||||
\ 'context (xetex)' : '-pdf -pdflatex=''texexec --xtx''',
|
||||
\ }, 'keep'), self.tex_program, '-pdf')
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
function! s:compiler.cleanup() abort dict " {{{1
|
||||
if self.is_running()
|
||||
call self.kill()
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
function! s:compiler.pprint_items() abort dict " {{{1
|
||||
let l:configuration = [
|
||||
\ ['continuous', self.continuous],
|
||||
\ ['callback', self.callback],
|
||||
\]
|
||||
|
||||
if self.backend ==# 'process' && !self.continuous
|
||||
call add(l:configuration, ['background', self.background])
|
||||
endif
|
||||
|
||||
if !empty(self.build_dir)
|
||||
call add(l:configuration, ['build_dir', self.build_dir])
|
||||
endif
|
||||
call add(l:configuration, ['latexmk options', self.options])
|
||||
call add(l:configuration, ['latexmk engine', self.get_engine()])
|
||||
|
||||
let l:list = []
|
||||
call add(l:list, ['backend', self.backend])
|
||||
if self.executable !=# s:compiler.executable
|
||||
call add(l:list, ['latexmk executable', self.executable])
|
||||
endif
|
||||
if self.background
|
||||
call add(l:list, ['output', self.output])
|
||||
endif
|
||||
|
||||
if self.target_path !=# b:vimtex.tex
|
||||
call add(l:list, ['root', self.root])
|
||||
call add(l:list, ['target', self.target_path])
|
||||
endif
|
||||
|
||||
call add(l:list, ['configuration', l:configuration])
|
||||
|
||||
if has_key(self, 'process')
|
||||
call add(l:list, ['process', self.process])
|
||||
endif
|
||||
|
||||
if has_key(self, 'job')
|
||||
if self.continuous
|
||||
if self.backend ==# 'jobs'
|
||||
call add(l:list, ['job', self.job])
|
||||
else
|
||||
call add(l:list, ['pid', self.get_pid()])
|
||||
endif
|
||||
endif
|
||||
call add(l:list, ['cmd', self.cmd])
|
||||
endif
|
||||
|
||||
return l:list
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
|
||||
function! s:compiler.clean(full) abort dict " {{{1
|
||||
let l:restart = self.is_running()
|
||||
if l:restart
|
||||
call self.stop()
|
||||
endif
|
||||
|
||||
" Define and run the latexmk clean cmd
|
||||
let l:cmd = (has('win32')
|
||||
\ ? 'cd /D "' . self.root . '" & '
|
||||
\ : 'cd ' . vimtex#util#shellescape(self.root) . '; ')
|
||||
\ . 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.target)
|
||||
call vimtex#process#run(l:cmd)
|
||||
|
||||
call vimtex#log#info('Compiler clean finished' . (a:full ? ' (full)' : ''))
|
||||
|
||||
if l:restart
|
||||
let self.silent_next_callback = 1
|
||||
silent call self.start()
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
function! s:compiler.start(...) abort dict " {{{1
|
||||
if self.is_running()
|
||||
call vimtex#log#warning(
|
||||
\ 'Compiler is already running for `' . self.target . "'")
|
||||
return
|
||||
endif
|
||||
|
||||
"
|
||||
" Create build dir if it does not exist
|
||||
"
|
||||
if !empty(self.build_dir)
|
||||
let l:dirs = split(glob(self.root . '/**/*.tex'), '\n')
|
||||
call map(l:dirs, 'fnamemodify(v:val, '':h'')')
|
||||
call map(l:dirs, 'strpart(v:val, strlen(self.root) + 1)')
|
||||
call vimtex#util#uniq(sort(filter(l:dirs, "v:val !=# ''")))
|
||||
call map(l:dirs,
|
||||
\ (vimtex#paths#is_abs(self.build_dir) ? '' : "self.root . '/' . ")
|
||||
\ . "self.build_dir . '/' . v:val")
|
||||
call filter(l:dirs, '!isdirectory(v:val)')
|
||||
|
||||
" Create the non-existing directories
|
||||
for l:dir in l:dirs
|
||||
call mkdir(l:dir, 'p')
|
||||
endfor
|
||||
endif
|
||||
|
||||
call self.exec()
|
||||
|
||||
if self.continuous
|
||||
call vimtex#log#info('Compiler started in continuous mode'
|
||||
\ . (a:0 > 0 ? ' (single shot)' : ''))
|
||||
if exists('#User#VimtexEventCompileStarted')
|
||||
doautocmd <nomodeline> User VimtexEventCompileStarted
|
||||
endif
|
||||
else
|
||||
if self.background
|
||||
call vimtex#log#info('Compiler started in background!')
|
||||
else
|
||||
call vimtex#compiler#callback(!vimtex#qf#inquire(self.target))
|
||||
endif
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
function! s:compiler.stop() abort dict " {{{1
|
||||
if self.is_running()
|
||||
call self.kill()
|
||||
call vimtex#log#info('Compiler stopped (' . self.target . ')')
|
||||
if exists('#User#VimtexEventCompileStopped')
|
||||
doautocmd <nomodeline> User VimtexEventCompileStopped
|
||||
endif
|
||||
else
|
||||
call vimtex#log#warning(
|
||||
\ 'There is no process to stop (' . self.target . ')')
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
|
||||
let s:compiler_process = {}
|
||||
function! s:compiler_process.exec() abort dict " {{{1
|
||||
let l:process = vimtex#process#new()
|
||||
let l:process.name = 'latexmk'
|
||||
let l:process.continuous = self.continuous
|
||||
let l:process.background = self.background
|
||||
let l:process.workdir = self.root
|
||||
let l:process.output = self.output
|
||||
let l:process.cmd = self.build_cmd()
|
||||
|
||||
if l:process.continuous
|
||||
if (has('win32') || has('win32unix'))
|
||||
" Not implemented
|
||||
else
|
||||
for l:pid in split(system(
|
||||
\ 'pgrep -f "^[^ ]*perl.*latexmk.*' . self.target . '"'), "\n")
|
||||
let l:path = resolve('/proc/' . l:pid . '/cwd') . '/' . self.target
|
||||
if l:path ==# self.target_path
|
||||
let l:process.pid = str2nr(l:pid)
|
||||
break
|
||||
endif
|
||||
endfor
|
||||
endif
|
||||
endif
|
||||
|
||||
function! l:process.set_pid() abort dict " {{{2
|
||||
if (has('win32') || has('win32unix'))
|
||||
let pidcmd = 'tasklist /fi "imagename eq latexmk.exe"'
|
||||
let pidinfo = vimtex#process#capture(pidcmd)[-1]
|
||||
let self.pid = str2nr(split(pidinfo,'\s\+')[1])
|
||||
else
|
||||
let self.pid = str2nr(system('pgrep -nf "^[^ ]*perl.*latexmk"')[:-2])
|
||||
endif
|
||||
|
||||
return self.pid
|
||||
endfunction
|
||||
|
||||
" }}}2
|
||||
|
||||
let self.process = l:process
|
||||
call self.process.run()
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
function! s:compiler_process.start_single() abort dict " {{{1
|
||||
let l:continuous = self.continuous
|
||||
let self.continuous = self.background && self.callback && !empty(v:servername)
|
||||
|
||||
if self.continuous
|
||||
let g:vimtex_compiler_callback_hooks += ['VimtexSSCallback']
|
||||
function! VimtexSSCallback(status) abort
|
||||
silent call vimtex#compiler#stop()
|
||||
call remove(g:vimtex_compiler_callback_hooks, 'VimtexSSCallback')
|
||||
endfunction
|
||||
endif
|
||||
|
||||
call self.start(1)
|
||||
let self.continuous = l:continuous
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
function! s:compiler_process.is_running() abort dict " {{{1
|
||||
return exists('self.process.pid') && self.process.pid > 0
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
function! s:compiler_process.kill() abort dict " {{{1
|
||||
call self.process.stop()
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
function! s:compiler_process.get_pid() abort dict " {{{1
|
||||
return has_key(self, 'process') ? self.process.pid : 0
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
|
||||
let s:compiler_jobs = {}
|
||||
function! s:compiler_jobs.exec() abort dict " {{{1
|
||||
let self.cmd = self.build_cmd()
|
||||
let l:cmd = has('win32')
|
||||
\ ? 'cmd /s /c "' . self.cmd . '"'
|
||||
\ : ['sh', '-c', self.cmd]
|
||||
|
||||
let l:options = {
|
||||
\ 'out_io' : 'file',
|
||||
\ 'err_io' : 'file',
|
||||
\ 'out_name' : self.output,
|
||||
\ 'err_name' : self.output,
|
||||
\}
|
||||
if self.continuous
|
||||
let l:options.out_io = 'pipe'
|
||||
let l:options.err_io = 'pipe'
|
||||
let l:options.out_cb = function('s:callback_continuous_output')
|
||||
let l:options.err_cb = function('s:callback_continuous_output')
|
||||
call writefile([], self.output, 'a')
|
||||
else
|
||||
let s:cb_target = self.target_path !=# b:vimtex.tex
|
||||
\ ? self.target_path : ''
|
||||
let l:options.exit_cb = function('s:callback')
|
||||
endif
|
||||
|
||||
call vimtex#paths#pushd(self.root)
|
||||
let self.job = job_start(l:cmd, l:options)
|
||||
call vimtex#paths#popd()
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
function! s:compiler_jobs.start_single() abort dict " {{{1
|
||||
let l:continuous = self.continuous
|
||||
let self.continuous = 0
|
||||
call self.start()
|
||||
let self.continuous = l:continuous
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
function! s:compiler_jobs.kill() abort dict " {{{1
|
||||
call job_stop(self.job)
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
function! s:compiler_jobs.is_running() abort dict " {{{1
|
||||
return has_key(self, 'job') && job_status(self.job) ==# 'run'
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
function! s:compiler_jobs.get_pid() abort dict " {{{1
|
||||
return has_key(self, 'job')
|
||||
\ ? get(job_info(self.job), 'process') : 0
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
function! s:callback(ch, msg) abort " {{{1
|
||||
call vimtex#compiler#callback(!vimtex#qf#inquire(s:cb_target))
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
function! s:callback_continuous_output(channel, msg) abort " {{{1
|
||||
if exists('b:vimtex') && filewritable(b:vimtex.compiler.output)
|
||||
call writefile([a:msg], b:vimtex.compiler.output, 'a')
|
||||
endif
|
||||
|
||||
if a:msg ==# 'vimtex_compiler_callback_success'
|
||||
call vimtex#compiler#callback(1)
|
||||
elseif a:msg ==# 'vimtex_compiler_callback_failure'
|
||||
call vimtex#compiler#callback(0)
|
||||
endif
|
||||
|
||||
try
|
||||
for l:Hook in get(get(get(b:, 'vimtex', {}), 'compiler', {}), 'hooks', [])
|
||||
call l:Hook(a:msg)
|
||||
endfor
|
||||
catch /E716/
|
||||
endtry
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
|
||||
let s:compiler_nvim = {}
|
||||
function! s:compiler_nvim.exec() abort dict " {{{1
|
||||
let self.cmd = self.build_cmd()
|
||||
let l:cmd = has('win32')
|
||||
\ ? 'cmd /s /c "' . self.cmd . '"'
|
||||
\ : ['sh', '-c', self.cmd]
|
||||
|
||||
let l:shell = {
|
||||
\ 'on_stdout' : function('s:callback_nvim_output'),
|
||||
\ 'on_stderr' : function('s:callback_nvim_output'),
|
||||
\ 'cwd' : self.root,
|
||||
\ 'target' : self.target_path,
|
||||
\ 'output' : self.output,
|
||||
\}
|
||||
|
||||
if !self.continuous
|
||||
let l:shell.on_exit = function('s:callback_nvim_exit')
|
||||
endif
|
||||
|
||||
" Initialize output file
|
||||
try
|
||||
call writefile([], self.output)
|
||||
endtry
|
||||
|
||||
let self.job = jobstart(l:cmd, l:shell)
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
function! s:compiler_nvim.start_single() abort dict " {{{1
|
||||
let l:continuous = self.continuous
|
||||
let self.continuous = 0
|
||||
call self.start()
|
||||
let self.continuous = l:continuous
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
function! s:compiler_nvim.kill() abort dict " {{{1
|
||||
call jobstop(self.job)
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
function! s:compiler_nvim.is_running() abort dict " {{{1
|
||||
try
|
||||
let pid = jobpid(self.job)
|
||||
return 1
|
||||
catch
|
||||
return 0
|
||||
endtry
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
function! s:compiler_nvim.get_pid() abort dict " {{{1
|
||||
try
|
||||
return jobpid(self.job)
|
||||
catch
|
||||
return 0
|
||||
endtry
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
function! s:callback_nvim_output(id, data, event) abort dict " {{{1
|
||||
" Filter out unwanted newlines
|
||||
let l:data = split(substitute(join(a:data, 'QQ'), '^QQ\|QQ$', '', ''), 'QQ')
|
||||
|
||||
if !empty(l:data) && filewritable(self.output)
|
||||
call writefile(l:data, self.output, 'a')
|
||||
endif
|
||||
|
||||
if match(a:data, 'vimtex_compiler_callback_success') != -1
|
||||
call vimtex#compiler#callback(!vimtex#qf#inquire(self.target))
|
||||
elseif match(a:data, 'vimtex_compiler_callback_failure') != -1
|
||||
call vimtex#compiler#callback(0)
|
||||
endif
|
||||
|
||||
try
|
||||
for l:Hook in get(get(get(b:, 'vimtex', {}), 'compiler', {}), 'hooks', [])
|
||||
call l:Hook(join(a:data, "\n"))
|
||||
endfor
|
||||
catch /E716/
|
||||
endtry
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
function! s:callback_nvim_exit(id, data, event) abort dict " {{{1
|
||||
let l:target = self.target !=# b:vimtex.tex ? self.target : ''
|
||||
call vimtex#compiler#callback(!vimtex#qf#inquire(l:target))
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
|
||||
endif
|
||||
250
autoload/vimtex/compiler/latexrun.vim
Normal file
250
autoload/vimtex/compiler/latexrun.vim
Normal file
@@ -0,0 +1,250 @@
|
||||
if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'latex') == -1
|
||||
|
||||
" vimtex - LaTeX plugin for Vim
|
||||
"
|
||||
" Maintainer: Karl Yngve Lervåg
|
||||
" Email: karl.yngve@gmail.com
|
||||
"
|
||||
|
||||
function! vimtex#compiler#latexrun#init(options) abort " {{{1
|
||||
let l:compiler = deepcopy(s:compiler)
|
||||
|
||||
call l:compiler.init(extend(a:options,
|
||||
\ get(g:, 'vimtex_compiler_latexrun', {}), 'keep'))
|
||||
|
||||
return l:compiler
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
|
||||
let s:compiler = {
|
||||
\ 'name' : 'latexrun',
|
||||
\ 'backend' : has('nvim') ? 'nvim'
|
||||
\ : v:version >= 800 ? 'jobs' : 'process',
|
||||
\ 'root' : '',
|
||||
\ 'target' : '',
|
||||
\ 'target_path' : '',
|
||||
\ 'background' : 1,
|
||||
\ 'build_dir' : '',
|
||||
\ 'output' : tempname(),
|
||||
\ 'options' : [
|
||||
\ '--verbose-cmds',
|
||||
\ '--latex-args="-synctex=1"',
|
||||
\ ],
|
||||
\}
|
||||
|
||||
function! s:compiler.init(options) abort dict " {{{1
|
||||
call extend(self, a:options)
|
||||
|
||||
if !executable('latexrun')
|
||||
call vimtex#log#warning('latexrun is not executable!')
|
||||
throw 'vimtex: Requirements not met'
|
||||
endif
|
||||
|
||||
call extend(self, deepcopy(s:compiler_{self.backend}))
|
||||
|
||||
" Processes run with the new jobs api will not run in the foreground
|
||||
if self.backend !=# 'process'
|
||||
let self.background = 1
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
|
||||
function! s:compiler.build_cmd() abort dict " {{{1
|
||||
let l:cmd = 'latexrun'
|
||||
|
||||
for l:opt in self.options
|
||||
let l:cmd .= ' ' . l:opt
|
||||
endfor
|
||||
|
||||
let l:cmd .= ' --latex-cmd ' . self.get_engine()
|
||||
|
||||
let l:cmd .= ' -O '
|
||||
\ . (empty(self.build_dir) ? '.' : fnameescape(self.build_dir))
|
||||
|
||||
return l:cmd . ' ' . vimtex#util#shellescape(self.target)
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
function! s:compiler.get_engine() abort dict " {{{1
|
||||
return get(extend(g:vimtex_compiler_latexrun_engines,
|
||||
\ {
|
||||
\ '_' : 'pdflatex',
|
||||
\ 'pdflatex' : 'pdflatex',
|
||||
\ 'lualatex' : 'lualatex',
|
||||
\ 'xelatex' : 'xelatex',
|
||||
\ }, 'keep'), self.tex_program, '_')
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
function! s:compiler.cleanup() abort dict " {{{1
|
||||
" Pass
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
function! s:compiler.pprint_items() abort dict " {{{1
|
||||
let l:configuration = []
|
||||
|
||||
if self.backend ==# 'process'
|
||||
call add(l:configuration, ['background', self.background])
|
||||
endif
|
||||
|
||||
if !empty(self.build_dir)
|
||||
call add(l:configuration, ['build_dir', self.build_dir])
|
||||
endif
|
||||
call add(l:configuration, ['latexrun options', self.options])
|
||||
call add(l:configuration, ['latexrun engine', self.get_engine()])
|
||||
|
||||
let l:list = []
|
||||
call add(l:list, ['backend', self.backend])
|
||||
if self.background
|
||||
call add(l:list, ['output', self.output])
|
||||
endif
|
||||
|
||||
if self.target_path !=# b:vimtex.tex
|
||||
call add(l:list, ['root', self.root])
|
||||
call add(l:list, ['target', self.target_path])
|
||||
endif
|
||||
|
||||
call add(l:list, ['configuration', l:configuration])
|
||||
|
||||
if has_key(self, 'process')
|
||||
call add(l:list, ['process', self.process])
|
||||
endif
|
||||
|
||||
if has_key(self, 'job')
|
||||
call add(l:list, ['cmd', self.cmd])
|
||||
endif
|
||||
|
||||
return l:list
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
|
||||
function! s:compiler.clean(...) abort dict " {{{1
|
||||
let l:cmd = (has('win32')
|
||||
\ ? 'cd /D "' . self.root . '" & '
|
||||
\ : 'cd ' . vimtex#util#shellescape(self.root) . '; ')
|
||||
\ . 'latexrun --clean-all'
|
||||
\ . ' -O '
|
||||
\ . (empty(self.build_dir) ? '.' : fnameescape(self.build_dir))
|
||||
call vimtex#process#run(l:cmd)
|
||||
|
||||
call vimtex#log#info('Compiler clean finished')
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
function! s:compiler.start(...) abort dict " {{{1
|
||||
call self.exec()
|
||||
|
||||
if self.background
|
||||
call vimtex#log#info('Compiler started in background')
|
||||
else
|
||||
call vimtex#compiler#callback(!vimtex#qf#inquire(self.target))
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
function! s:compiler.start_single() abort dict " {{{1
|
||||
call self.start()
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
function! s:compiler.stop() abort dict " {{{1
|
||||
" Pass
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
function! s:compiler.is_running() abort dict " {{{1
|
||||
return 0
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
function! s:compiler.kill() abort dict " {{{1
|
||||
" Pass
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
function! s:compiler.get_pid() abort dict " {{{1
|
||||
return 0
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
|
||||
let s:compiler_process = {}
|
||||
function! s:compiler_process.exec() abort dict " {{{1
|
||||
let self.process = vimtex#process#new()
|
||||
let self.process.name = 'latexrun'
|
||||
let self.process.background = self.background
|
||||
let self.process.workdir = self.root
|
||||
let self.process.output = self.output
|
||||
let self.process.cmd = self.build_cmd()
|
||||
call self.process.run()
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
|
||||
let s:compiler_jobs = {}
|
||||
function! s:compiler_jobs.exec() abort dict " {{{1
|
||||
let self.cmd = self.build_cmd()
|
||||
let l:cmd = has('win32')
|
||||
\ ? 'cmd /s /c "' . self.cmd . '"'
|
||||
\ : ['sh', '-c', self.cmd]
|
||||
let l:options = {
|
||||
\ 'out_io' : 'file',
|
||||
\ 'err_io' : 'file',
|
||||
\ 'out_name' : self.output,
|
||||
\ 'err_name' : self.output,
|
||||
\}
|
||||
|
||||
let s:cb_target = self.target_path !=# b:vimtex.tex ? self.target_path : ''
|
||||
let l:options.exit_cb = function('s:callback')
|
||||
|
||||
call vimtex#paths#pushd(self.root)
|
||||
let self.job = job_start(l:cmd, l:options)
|
||||
call vimtex#paths#popd()
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
function! s:callback(ch, msg) abort " {{{1
|
||||
call vimtex#compiler#callback(!vimtex#qf#inquire(s:cb_target))
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
|
||||
let s:compiler_nvim = {}
|
||||
function! s:compiler_nvim.exec() abort dict " {{{1
|
||||
let self.cmd = self.build_cmd()
|
||||
let l:cmd = has('win32')
|
||||
\ ? 'cmd /s /c "' . self.cmd . '"'
|
||||
\ : ['sh', '-c', self.cmd]
|
||||
|
||||
let l:shell = {
|
||||
\ 'on_stdout' : function('s:callback_nvim_output'),
|
||||
\ 'on_stderr' : function('s:callback_nvim_output'),
|
||||
\ 'on_exit' : function('s:callback_nvim_exit'),
|
||||
\ 'cwd' : self.root,
|
||||
\ 'target' : self.target_path,
|
||||
\ 'output' : self.output,
|
||||
\}
|
||||
|
||||
let self.job = jobstart(l:cmd, l:shell)
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
function! s:callback_nvim_output(id, data, event) abort dict " {{{1
|
||||
if !empty(a:data)
|
||||
call writefile(filter(a:data, '!empty(v:val)'), self.output, 'a')
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
function! s:callback_nvim_exit(id, data, event) abort dict " {{{1
|
||||
let l:target = self.target !=# b:vimtex.tex ? self.target : ''
|
||||
call vimtex#compiler#callback(!vimtex#qf#inquire(l:target))
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
|
||||
endif
|
||||
255
autoload/vimtex/compiler/tectonic.vim
Normal file
255
autoload/vimtex/compiler/tectonic.vim
Normal file
@@ -0,0 +1,255 @@
|
||||
if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'latex') == -1
|
||||
|
||||
" vimtex - LaTeX plugin for Vim
|
||||
"
|
||||
" Maintainer: Karl Yngve Lervåg
|
||||
" Email: karl.yngve@gmail.com
|
||||
"
|
||||
|
||||
function! vimtex#compiler#tectonic#init(options) abort " {{{1
|
||||
let l:compiler = deepcopy(s:compiler)
|
||||
|
||||
call l:compiler.init(extend(a:options,
|
||||
\ get(g:, 'vimtex_compiler_tectonic', {}), 'keep'))
|
||||
|
||||
return l:compiler
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
|
||||
let s:compiler = {
|
||||
\ 'name' : 'tectonic',
|
||||
\ 'backend' : has('nvim') ? 'nvim'
|
||||
\ : v:version >= 800 ? 'jobs' : 'process',
|
||||
\ 'root' : '',
|
||||
\ 'target' : '',
|
||||
\ 'target_path' : '',
|
||||
\ 'background' : 1,
|
||||
\ 'build_dir' : '',
|
||||
\ 'output' : tempname(),
|
||||
\ 'options' : [
|
||||
\ '--keep-logs',
|
||||
\ '--synctex'
|
||||
\ ],
|
||||
\}
|
||||
|
||||
function! s:compiler.init(options) abort dict " {{{1
|
||||
call extend(self, a:options)
|
||||
|
||||
if !executable('tectonic')
|
||||
call vimtex#log#warning('tectonic is not executable!')
|
||||
throw 'vimtex: Requirements not met'
|
||||
endif
|
||||
|
||||
call extend(self, deepcopy(s:compiler_{self.backend}))
|
||||
|
||||
" Processes run with the new jobs api will not run in the foreground
|
||||
if self.backend !=# 'process'
|
||||
let self.background = 1
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
|
||||
function! s:compiler.build_cmd() abort dict " {{{1
|
||||
let l:cmd = 'tectonic'
|
||||
|
||||
for l:opt in self.options
|
||||
if l:opt =~# '^-\%(o\|-outdir\)'
|
||||
call vimtex#log#warning("Don't use --outdir or -o in compiler options,"
|
||||
\ . ' use build_dir instead, see :help g:vimtex_compiler_tectonic'
|
||||
\ . ' for more details')
|
||||
continue
|
||||
endif
|
||||
|
||||
let l:cmd .= ' ' . l:opt
|
||||
endfor
|
||||
|
||||
if empty(self.build_dir)
|
||||
let self.build_dir = fnamemodify(self.target_path, ':p:h')
|
||||
elseif !isdirectory(self.build_dir)
|
||||
call vimtex#log#warning(
|
||||
\ "build_dir doesn't exist, it will be created: " . self.build_dir)
|
||||
call mkdir(self.build_dir, 'p')
|
||||
endif
|
||||
|
||||
return l:cmd
|
||||
\ . ' --outdir=' . self.build_dir
|
||||
\ . ' ' . vimtex#util#shellescape(self.target)
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
function! s:compiler.cleanup() abort dict " {{{1
|
||||
" Pass
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
function! s:compiler.pprint_items() abort dict " {{{1
|
||||
let l:configuration = []
|
||||
|
||||
if self.backend ==# 'process'
|
||||
call add(l:configuration, ['background', self.background])
|
||||
endif
|
||||
|
||||
call add(l:configuration, ['tectonic options', self.options])
|
||||
|
||||
let l:list = []
|
||||
call add(l:list, ['backend', self.backend])
|
||||
if self.background
|
||||
call add(l:list, ['output', self.output])
|
||||
endif
|
||||
|
||||
if self.target_path !=# b:vimtex.tex
|
||||
call add(l:list, ['root', self.root])
|
||||
call add(l:list, ['target', self.target_path])
|
||||
endif
|
||||
|
||||
call add(l:list, ['configuration', l:configuration])
|
||||
|
||||
if has_key(self, 'process')
|
||||
call add(l:list, ['process', self.process])
|
||||
endif
|
||||
|
||||
if has_key(self, 'job')
|
||||
call add(l:list, ['cmd', self.cmd])
|
||||
endif
|
||||
|
||||
return l:list
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
|
||||
function! s:compiler.clean(...) abort dict " {{{1
|
||||
let l:files = ['synctex.gz', 'toc', 'out', 'aux', 'log']
|
||||
|
||||
" If a full clean is required
|
||||
if a:0 > 0 && a:1
|
||||
call extend(l:intermediate, ['pdf'])
|
||||
endif
|
||||
|
||||
let l:basename = self.build_dir . '/' . fnamemodify(self.target_path, ':t:r')
|
||||
call map(l:files, 'l:basename . v:val')
|
||||
|
||||
call vimtex#process#run('rm -f ' . join(l:files))
|
||||
call vimtex#log#info('Compiler clean finished')
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
function! s:compiler.start(...) abort dict " {{{1
|
||||
call self.exec()
|
||||
|
||||
if self.background
|
||||
call vimtex#log#info('Compiler started in background')
|
||||
else
|
||||
call vimtex#compiler#callback(!vimtex#qf#inquire(self.target))
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
function! s:compiler.start_single() abort dict " {{{1
|
||||
call self.start()
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
function! s:compiler.stop() abort dict " {{{1
|
||||
" Pass
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
function! s:compiler.is_running() abort dict " {{{1
|
||||
return 0
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
function! s:compiler.kill() abort dict " {{{1
|
||||
" Pass
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
function! s:compiler.get_pid() abort dict " {{{1
|
||||
return 0
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
|
||||
let s:compiler_process = {}
|
||||
function! s:compiler_process.exec() abort dict " {{{1
|
||||
let self.process = vimtex#process#new()
|
||||
let self.process.name = 'tectonic'
|
||||
let self.process.background = self.background
|
||||
let self.process.workdir = self.root
|
||||
let self.process.output = self.output
|
||||
let self.process.cmd = self.build_cmd()
|
||||
call self.process.run()
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
|
||||
let s:compiler_jobs = {}
|
||||
function! s:compiler_jobs.exec() abort dict " {{{1
|
||||
let self.cmd = self.build_cmd()
|
||||
let l:cmd = has('win32')
|
||||
\ ? 'cmd /s /c "' . self.cmd . '"'
|
||||
\ : ['sh', '-c', self.cmd]
|
||||
let l:options = {
|
||||
\ 'out_io' : 'file',
|
||||
\ 'err_io' : 'file',
|
||||
\ 'out_name' : self.output,
|
||||
\ 'err_name' : self.output,
|
||||
\}
|
||||
|
||||
let s:cb_target = self.target_path !=# b:vimtex.tex ? self.target_path : ''
|
||||
let l:options.exit_cb = function('s:callback')
|
||||
|
||||
if !empty(self.root)
|
||||
let l:save_pwd = getcwd()
|
||||
execute 'lcd' fnameescape(self.root)
|
||||
endif
|
||||
let self.job = job_start(l:cmd, l:options)
|
||||
if !empty(self.root)
|
||||
execute 'lcd' fnameescape(l:save_pwd)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
function! s:callback(ch, msg) abort " {{{1
|
||||
call vimtex#compiler#callback(!vimtex#qf#inquire(s:cb_target))
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
|
||||
let s:compiler_nvim = {}
|
||||
function! s:compiler_nvim.exec() abort dict " {{{1
|
||||
let self.cmd = self.build_cmd()
|
||||
let l:cmd = has('win32')
|
||||
\ ? 'cmd /s /c "' . self.cmd . '"'
|
||||
\ : ['sh', '-c', self.cmd]
|
||||
|
||||
let l:shell = {
|
||||
\ 'on_stdout' : function('s:callback_nvim_output'),
|
||||
\ 'on_stderr' : function('s:callback_nvim_output'),
|
||||
\ 'on_exit' : function('s:callback_nvim_exit'),
|
||||
\ 'cwd' : self.root,
|
||||
\ 'target' : self.target_path,
|
||||
\ 'output' : self.output,
|
||||
\}
|
||||
|
||||
let self.job = jobstart(l:cmd, l:shell)
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
function! s:callback_nvim_output(id, data, event) abort dict " {{{1
|
||||
if !empty(a:data)
|
||||
call writefile(filter(a:data, '!empty(v:val)'), self.output, 'a')
|
||||
endif
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
function! s:callback_nvim_exit(id, data, event) abort dict " {{{1
|
||||
let l:target = self.target !=# b:vimtex.tex ? self.target : ''
|
||||
call vimtex#compiler#callback(!vimtex#qf#inquire(l:target))
|
||||
endfunction
|
||||
|
||||
" }}}1
|
||||
|
||||
endif
|
||||
Reference in New Issue
Block a user