2015-03-07 17:02:15 -05:00
|
|
|
" vimtex - LaTeX plugin for Vim
|
2014-07-22 18:08:57 -04:00
|
|
|
"
|
|
|
|
" Maintainer: Karl Yngve Lervåg
|
|
|
|
" Email: karl.yngve@gmail.com
|
|
|
|
"
|
|
|
|
|
2015-03-07 17:02:15 -05:00
|
|
|
" vimtex is not initialized until vimtex#init() has been run once
|
2013-10-05 07:53:42 -04:00
|
|
|
let s:initialized = 0
|
2014-07-15 08:52:45 -04:00
|
|
|
|
2015-03-07 17:02:15 -05:00
|
|
|
function! vimtex#init() " {{{1
|
2014-07-16 17:08:00 -04:00
|
|
|
call s:init_options()
|
2013-10-05 07:53:42 -04:00
|
|
|
call s:init_environment()
|
|
|
|
|
2015-03-07 17:02:15 -05:00
|
|
|
call vimtex#toc#init(s:initialized)
|
2015-03-10 17:28:33 -04:00
|
|
|
call vimtex#echo#init(s:initialized)
|
2015-03-07 17:02:15 -05:00
|
|
|
call vimtex#fold#init(s:initialized)
|
|
|
|
call vimtex#view#init(s:initialized)
|
|
|
|
call vimtex#motion#init(s:initialized)
|
|
|
|
call vimtex#labels#init(s:initialized)
|
|
|
|
call vimtex#change#init(s:initialized)
|
|
|
|
call vimtex#latexmk#init(s:initialized)
|
|
|
|
call vimtex#complete#init(s:initialized)
|
|
|
|
call vimtex#mappings#init(s:initialized)
|
2013-10-05 07:53:42 -04:00
|
|
|
|
|
|
|
"
|
|
|
|
" This variable is used to allow a distinction between global and buffer
|
|
|
|
" initialization
|
|
|
|
"
|
|
|
|
let s:initialized = 1
|
|
|
|
endfunction
|
|
|
|
|
2015-03-07 17:02:15 -05:00
|
|
|
function! vimtex#info() " {{{1
|
2014-07-16 05:10:34 -04:00
|
|
|
if !s:initialized
|
2015-03-07 17:02:15 -05:00
|
|
|
echoerr "Error: vimtex has not been initialized!"
|
2014-07-16 05:10:34 -04:00
|
|
|
return
|
|
|
|
endif
|
|
|
|
|
2014-08-03 03:14:05 -04:00
|
|
|
" Print buffer data
|
2015-03-10 17:28:33 -04:00
|
|
|
call vimtex#echo#echo("b:vimtex\n")
|
2015-03-07 17:02:15 -05:00
|
|
|
call s:print_dict(b:vimtex)
|
2013-10-05 07:53:42 -04:00
|
|
|
|
2014-08-03 03:14:05 -04:00
|
|
|
" Print global data
|
|
|
|
let n = 0
|
2015-03-07 17:02:15 -05:00
|
|
|
for data in g:vimtex#data
|
2015-02-27 02:30:58 -05:00
|
|
|
" Prepare for printing
|
|
|
|
let d = deepcopy(data)
|
2014-08-03 03:14:05 -04:00
|
|
|
for f in ['aux', 'out', 'log']
|
2015-02-27 02:30:58 -05:00
|
|
|
silent execute 'let d.' . f . ' = data.' . f . '()'
|
2013-10-05 07:53:42 -04:00
|
|
|
endfor
|
2014-08-03 03:14:05 -04:00
|
|
|
|
2015-02-27 02:30:58 -05:00
|
|
|
" Print data blob title line
|
2015-03-10 17:28:33 -04:00
|
|
|
call vimtex#echo#formatted([
|
|
|
|
\ "\n\ng:vimtex#data[",
|
|
|
|
\ ['VimtexSuccess', n],
|
|
|
|
\ '] : ',
|
|
|
|
\ ['VimtexSuccess', remove(d, 'name') . "\n"]])
|
2015-02-27 02:30:58 -05:00
|
|
|
call s:print_dict(d)
|
2014-08-03 03:14:05 -04:00
|
|
|
let n += 1
|
2013-10-05 07:53:42 -04:00
|
|
|
endfor
|
|
|
|
endfunction
|
|
|
|
|
2015-03-07 17:02:15 -05:00
|
|
|
function! vimtex#help() " {{{1
|
|
|
|
if g:vimtex_mappings_enabled
|
2013-10-05 07:53:42 -04:00
|
|
|
nmap <buffer>
|
2014-07-27 15:18:01 -04:00
|
|
|
xmap <buffer>
|
2013-10-05 07:53:42 -04:00
|
|
|
omap <buffer>
|
2013-10-11 17:13:41 -04:00
|
|
|
else
|
2015-03-10 17:28:33 -04:00
|
|
|
call vimtex#echo#warning('vimtex mappings are not enabled')
|
2013-10-05 07:53:42 -04:00
|
|
|
endif
|
|
|
|
endfunction
|
|
|
|
|
2015-03-07 17:02:15 -05:00
|
|
|
function! vimtex#reinit() " {{{1
|
2013-10-05 07:53:42 -04:00
|
|
|
"
|
|
|
|
" Stop latexmk processes (if running)
|
|
|
|
"
|
2015-03-07 17:02:15 -05:00
|
|
|
call vimtex#latexmk#stop_all()
|
2013-10-05 07:53:42 -04:00
|
|
|
|
|
|
|
"
|
2013-10-06 05:44:50 -04:00
|
|
|
" Reset global variables
|
2013-10-05 07:53:42 -04:00
|
|
|
"
|
|
|
|
let s:initialized = 0
|
2015-03-07 17:02:15 -05:00
|
|
|
unlet g:vimtex#data
|
2013-10-05 07:53:42 -04:00
|
|
|
|
|
|
|
"
|
2013-10-06 05:44:50 -04:00
|
|
|
" Reset and reinitialize buffers
|
2013-10-05 07:53:42 -04:00
|
|
|
"
|
2013-10-10 15:48:52 -04:00
|
|
|
let n = bufnr('%')
|
2013-10-06 05:44:50 -04:00
|
|
|
bufdo if getbufvar('%', '&filetype') == 'tex' |
|
2015-03-10 17:28:33 -04:00
|
|
|
\ unlet b:vimtex |
|
|
|
|
\ call vimtex#init() |
|
2013-10-06 05:44:50 -04:00
|
|
|
\ endif
|
2013-10-10 15:48:52 -04:00
|
|
|
silent execute 'buffer ' . n
|
2013-10-05 07:53:42 -04:00
|
|
|
endfunction
|
|
|
|
" }}}1
|
|
|
|
|
2014-07-15 08:52:45 -04:00
|
|
|
function! s:init_environment() " {{{1
|
2013-10-05 07:53:42 -04:00
|
|
|
" Initialize global and local data blobs
|
2015-03-07 17:02:15 -05:00
|
|
|
call vimtex#util#set_default('g:vimtex#data', [])
|
|
|
|
call vimtex#util#set_default('b:vimtex', {})
|
2013-10-05 07:53:42 -04:00
|
|
|
|
2015-03-10 09:30:40 -04:00
|
|
|
" Ensure tex files are prioritized when listing files
|
|
|
|
for suf in [
|
|
|
|
\ '.log',
|
|
|
|
\ '.aux',
|
|
|
|
\ '.bbl',
|
|
|
|
\ '.out',
|
|
|
|
\ '.blg',
|
|
|
|
\ '.brf',
|
|
|
|
\ '.cb',
|
|
|
|
\ '.dvi',
|
|
|
|
\ '.fdb_latexmk',
|
|
|
|
\ '.fls',
|
|
|
|
\ '.idx',
|
|
|
|
\ '.ilg',
|
|
|
|
\ '.ind',
|
|
|
|
\ '.inx',
|
|
|
|
\ '.pdf',
|
|
|
|
\ '.synctex.gz',
|
|
|
|
\ '.toc',
|
|
|
|
\ ]
|
|
|
|
execute 'set suffixes+=' . suf
|
|
|
|
endfor
|
|
|
|
|
2014-07-16 17:08:00 -04:00
|
|
|
" Set some file type specific vim options
|
2014-08-03 02:06:12 -04:00
|
|
|
setlocal suffixesadd+=.tex
|
|
|
|
setlocal commentstring=\%\ %s
|
2014-07-16 17:08:00 -04:00
|
|
|
|
2014-08-03 03:14:05 -04:00
|
|
|
" Create new or link to existing blob
|
2013-12-10 11:42:25 -05:00
|
|
|
let main = s:get_main()
|
2013-10-05 07:53:42 -04:00
|
|
|
let id = s:get_id(main)
|
|
|
|
if id >= 0
|
2015-03-07 17:02:15 -05:00
|
|
|
let b:vimtex.id = id
|
2013-10-05 07:53:42 -04:00
|
|
|
else
|
|
|
|
let data = {}
|
2014-02-04 07:16:48 -05:00
|
|
|
let data.tex = main
|
|
|
|
let data.root = fnamemodify(data.tex, ':h')
|
|
|
|
let data.base = fnamemodify(data.tex, ':t')
|
|
|
|
let data.name = fnamemodify(data.tex, ':t:r')
|
2013-10-05 07:53:42 -04:00
|
|
|
function data.aux() dict
|
|
|
|
return s:get_main_ext(self, 'aux')
|
|
|
|
endfunction
|
|
|
|
function data.log() dict
|
|
|
|
return s:get_main_ext(self, 'log')
|
|
|
|
endfunction
|
|
|
|
function data.out() dict
|
2015-01-01 09:20:07 -05:00
|
|
|
return s:get_main_out(self)
|
2013-10-05 07:53:42 -04:00
|
|
|
endfunction
|
|
|
|
|
2015-03-07 17:02:15 -05:00
|
|
|
call add(g:vimtex#data, data)
|
|
|
|
let b:vimtex.id = len(g:vimtex#data) - 1
|
2013-10-05 07:53:42 -04:00
|
|
|
endif
|
|
|
|
|
2015-01-30 07:02:27 -05:00
|
|
|
" Define commands
|
2015-03-20 16:29:49 -04:00
|
|
|
command! -buffer VimtexInfo call vimtex#info()
|
2015-03-07 17:02:15 -05:00
|
|
|
command! -buffer VimtexHelp call vimtex#help()
|
|
|
|
command! -buffer VimtexReinitialize call vimtex#reinit()
|
2014-07-15 08:52:45 -04:00
|
|
|
|
2015-01-30 07:02:27 -05:00
|
|
|
" Define mappings
|
2015-03-07 17:02:15 -05:00
|
|
|
nnoremap <buffer> <plug>(vimtex-info) :call vimtex#info()<cr>
|
|
|
|
nnoremap <buffer> <plug>(vimtex-help) :call vimtex#help()<cr>
|
|
|
|
nnoremap <buffer> <plug>(vimtex-reinit) :call vimtex#reinit()<cr>
|
2013-10-05 07:53:42 -04:00
|
|
|
endfunction
|
|
|
|
|
2014-07-16 17:08:00 -04:00
|
|
|
function! s:init_options() " {{{1
|
2015-03-07 17:02:15 -05:00
|
|
|
call vimtex#util#set_default('g:vimtex_quickfix_ignore_all_warnings', 0)
|
|
|
|
call vimtex#util#set_default('g:vimtex_quickfix_ignored_warnings', [])
|
2015-01-26 09:41:40 -05:00
|
|
|
|
2015-03-07 17:02:15 -05:00
|
|
|
call vimtex#util#error_deprecated('g:vimtex_errorformat_ignore_warnings')
|
|
|
|
call vimtex#util#error_deprecated('g:vimtex_errorformat_show_warnings')
|
2014-07-16 17:08:00 -04:00
|
|
|
endfunction
|
|
|
|
" }}}1
|
2013-10-05 07:53:42 -04:00
|
|
|
|
2014-07-15 08:52:45 -04:00
|
|
|
function! s:get_id(main) " {{{1
|
2015-03-07 17:02:15 -05:00
|
|
|
if exists('g:vimtex#data') && !empty(g:vimtex#data)
|
2013-10-05 07:53:42 -04:00
|
|
|
let id = 0
|
2015-03-07 17:02:15 -05:00
|
|
|
while id < len(g:vimtex#data)
|
|
|
|
if g:vimtex#data[id].tex == a:main
|
2013-10-05 07:53:42 -04:00
|
|
|
return id
|
|
|
|
endif
|
|
|
|
let id += 1
|
|
|
|
endwhile
|
|
|
|
endif
|
|
|
|
|
|
|
|
return -1
|
|
|
|
endfunction
|
|
|
|
|
2014-07-15 08:52:45 -04:00
|
|
|
function! s:get_main() " {{{1
|
2013-12-10 11:42:25 -05:00
|
|
|
"
|
|
|
|
" Search for main file specifier at the beginning of file. This is similar
|
|
|
|
" to the method used by several other plugins and editors, such as vim with
|
|
|
|
" LaTeX-Box, TextMate, TexWorks, and texmaker.
|
|
|
|
"
|
|
|
|
for line in getline(1, 5)
|
|
|
|
let candidate = matchstr(line,
|
|
|
|
\ '^\s*%\s*!\s*[tT][eE][xX]\s\+root\s*=\s*\zs.*\ze\s*$')
|
|
|
|
if len(candidate) > 0
|
|
|
|
let main = fnamemodify(candidate, ':p')
|
|
|
|
if filereadable(main)
|
|
|
|
return main
|
2013-12-08 13:32:30 -05:00
|
|
|
endif
|
2013-12-10 11:42:25 -05:00
|
|
|
endif
|
|
|
|
endfor
|
|
|
|
|
|
|
|
"
|
|
|
|
" Search for main file recursively through \input and \include specifiers
|
|
|
|
"
|
|
|
|
let main = s:get_main_recurse(expand('%:p'))
|
|
|
|
if filereadable(main)
|
|
|
|
return main
|
|
|
|
endif
|
|
|
|
|
|
|
|
"
|
|
|
|
" If not found, use current file
|
|
|
|
"
|
|
|
|
return expand('%:p')
|
|
|
|
endfunction
|
|
|
|
|
2014-07-15 08:52:45 -04:00
|
|
|
function! s:get_main_recurse(file) " {{{1
|
2013-12-26 06:19:53 -05:00
|
|
|
"
|
|
|
|
" Check if file is readable
|
|
|
|
"
|
|
|
|
if !filereadable(a:file)
|
|
|
|
return 0
|
|
|
|
endif
|
|
|
|
|
2013-12-10 11:42:25 -05:00
|
|
|
"
|
|
|
|
" Check if current file is a main file
|
|
|
|
"
|
|
|
|
if len(filter(readfile(a:file),
|
|
|
|
\ 'v:val =~ ''\C\\begin\_\s*{document}''')) > 0
|
|
|
|
return fnamemodify(a:file, ':p')
|
2013-12-08 13:32:30 -05:00
|
|
|
endif
|
2013-12-10 11:42:25 -05:00
|
|
|
|
|
|
|
"
|
2014-07-16 05:37:39 -04:00
|
|
|
" Gather candidate files
|
2013-12-10 11:42:25 -05:00
|
|
|
"
|
2014-07-16 05:37:39 -04:00
|
|
|
let l:path = expand('%:p:h')
|
|
|
|
let l:dirs = l:path
|
2014-07-17 12:43:44 -04:00
|
|
|
while l:path != fnamemodify(l:path, ':h')
|
2014-07-16 05:37:39 -04:00
|
|
|
let l:path = fnamemodify(l:path, ':h')
|
|
|
|
let l:dirs .= ',' . l:path
|
|
|
|
endwhile
|
2014-10-30 14:54:49 -04:00
|
|
|
let l:candidates = split(globpath(l:dirs, '*.tex'), '\n')
|
2014-07-16 05:37:39 -04:00
|
|
|
|
|
|
|
"
|
|
|
|
" Search through candidates for \include{current file}
|
|
|
|
"
|
|
|
|
for l:file in l:candidates
|
2013-12-10 11:42:25 -05:00
|
|
|
if len(filter(readfile(l:file), 'v:val =~ ''\v\\(input|include)\{'
|
2014-11-19 03:58:48 -05:00
|
|
|
\ . '\s*((.*)\/)?'
|
|
|
|
\ . fnamemodify(a:file, ':t:r') . '(\.tex)?\s*''')) > 0
|
2013-12-10 11:42:25 -05:00
|
|
|
return s:get_main_recurse(l:file)
|
|
|
|
endif
|
|
|
|
endfor
|
|
|
|
|
|
|
|
"
|
|
|
|
" If not found, return 0
|
|
|
|
"
|
|
|
|
return 0
|
2013-10-05 07:53:42 -04:00
|
|
|
endfunction
|
|
|
|
|
2014-07-15 08:52:45 -04:00
|
|
|
function! s:get_main_ext(texdata, ext) " {{{1
|
2013-10-05 07:53:42 -04:00
|
|
|
" Create set of candidates
|
|
|
|
let candidates = [
|
|
|
|
\ a:texdata.name,
|
2015-03-07 17:02:15 -05:00
|
|
|
\ g:vimtex_latexmk_build_dir . '/' . a:texdata.name,
|
2013-10-05 07:53:42 -04:00
|
|
|
\ ]
|
|
|
|
|
|
|
|
" Search through the candidates
|
|
|
|
for f in map(candidates,
|
|
|
|
\ 'a:texdata.root . ''/'' . v:val . ''.'' . a:ext')
|
|
|
|
if filereadable(f)
|
2014-07-21 19:26:27 -04:00
|
|
|
return fnamemodify(f, ':p')
|
2013-10-05 07:53:42 -04:00
|
|
|
endif
|
|
|
|
endfor
|
|
|
|
|
|
|
|
" Return empty string if no entry is found
|
|
|
|
return ''
|
|
|
|
endfunction
|
|
|
|
|
2015-01-01 09:20:07 -05:00
|
|
|
function! s:get_main_out(texdata) " {{{1
|
|
|
|
" Create set of candidates
|
|
|
|
let candidates = [
|
|
|
|
\ a:texdata.name,
|
2015-03-07 17:02:15 -05:00
|
|
|
\ g:vimtex_latexmk_build_dir . '/' . a:texdata.name,
|
2015-01-01 09:20:07 -05:00
|
|
|
\ ]
|
|
|
|
|
|
|
|
" Check for pdf files
|
|
|
|
for f in map(candidates,
|
|
|
|
\ 'a:texdata.root . ''/'' . v:val . ''.pdf''')
|
|
|
|
if filereadable(f)
|
|
|
|
return fnamemodify(f, ':p')
|
|
|
|
endif
|
|
|
|
endfor
|
|
|
|
|
|
|
|
" Check for dvi files
|
|
|
|
for f in map(candidates,
|
|
|
|
\ 'a:texdata.root . ''/'' . v:val . ''.dvi''')
|
|
|
|
if filereadable(f)
|
|
|
|
return fnamemodify(f, ':p')
|
|
|
|
endif
|
|
|
|
endfor
|
|
|
|
|
|
|
|
" Return empty string if no entry is found
|
|
|
|
return ''
|
|
|
|
endfunction
|
|
|
|
|
2015-02-27 02:30:58 -05:00
|
|
|
" }}}1
|
|
|
|
|
|
|
|
function! s:print_dict(dict, ...) " {{{1
|
|
|
|
let level = a:0 > 0 ? a:1 : 0
|
|
|
|
|
|
|
|
for entry in sort(sort(items(a:dict),
|
|
|
|
\ "s:print_dict_sort_2"),
|
|
|
|
\ "s:print_dict_sort_1")
|
2015-03-10 17:28:33 -04:00
|
|
|
let title = repeat(' ', 2 + 2*level) . entry[0]
|
2015-02-27 02:30:58 -05:00
|
|
|
if type(entry[1]) == type([])
|
2015-03-10 17:28:33 -04:00
|
|
|
call vimtex#echo#echo(title)
|
2015-02-27 02:30:58 -05:00
|
|
|
for val in entry[1]
|
2015-03-10 17:28:33 -04:00
|
|
|
call vimtex#echo#echo(repeat(' ', 4 + 2*level) . string(val), 'None')
|
2015-02-27 02:30:58 -05:00
|
|
|
endfor
|
|
|
|
elseif type(entry[1]) == type({})
|
2015-03-10 17:28:33 -04:00
|
|
|
call vimtex#echo#echo(title . "\n")
|
2015-02-27 02:30:58 -05:00
|
|
|
call s:print_dict(entry[1], level + 1)
|
|
|
|
else
|
2015-03-10 17:28:33 -04:00
|
|
|
call vimtex#echo#formatted([title . ' : ',
|
|
|
|
\ ['None', string(entry[1]) . "\n"]])
|
2015-02-27 02:30:58 -05:00
|
|
|
endif
|
|
|
|
endfor
|
2013-10-05 07:53:42 -04:00
|
|
|
endfunction
|
2015-02-27 02:30:58 -05:00
|
|
|
|
|
|
|
" }}}1
|
|
|
|
function! s:print_dict_sort_1(i1, i2) " {{{1
|
|
|
|
return type(a:i1[1]) - type(a:i2[1])
|
|
|
|
endfunction
|
|
|
|
|
|
|
|
" }}}1
|
|
|
|
function! s:print_dict_sort_2(i1, i2) " {{{1
|
|
|
|
return string(a:i1[1]) == string(a:i2[1]) ? 0
|
|
|
|
\ : string(a:i1[1]) > string(a:i2[1]) ? 1
|
|
|
|
\ : -1
|
|
|
|
endfunction
|
|
|
|
|
2013-10-05 07:53:42 -04:00
|
|
|
" }}}1
|
|
|
|
|
2014-12-08 14:44:17 -05:00
|
|
|
" vim: fdm=marker sw=2
|