1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
|
" VimTeX - LaTeX plugin for Vim
"
" Maintainer: Karl Yngve LervÄg
" Email: karl.yngve@gmail.com
"
function! vimtex#include#expr() abort " {{{1
call s:visited.timeout()
let l:fname = substitute(v:fname, '^\s*\|\s*$', '', 'g')
" Check if v:fname matches exactly
if filereadable(l:fname)
return s:visited.check(l:fname)
endif
" Parse \include or \input style lines
let l:file = s:parse_input(l:fname, 'tex')
for l:candidate in [l:file, l:file . '.tex']
if filereadable(l:candidate)
return s:visited.check(l:candidate)
endif
endfor
" Parse \bibliography or \addbibresource
let l:candidate = s:parse_input(l:fname, 'bib')
if filereadable(l:candidate)
return s:visited.check(l:candidate)
endif
" Check if v:fname matches in $TEXINPUTS
let l:candidate = s:search_candidates_texinputs(l:fname)
if !empty(l:candidate)
return s:visited.check(l:candidate)
endif
" Search for file with kpsewhich
if g:vimtex_include_search_enabled
" Parse package or documentclass commands
let l:fname = s:parse_package_documentclass(l:fname)
let l:candidate = s:search_candidates_kpsewhich(l:fname)
if !empty(l:candidate)
return s:visited.check(l:candidate)
endif
endif
return s:visited.check(l:fname)
endfunction
" }}}1
function! s:parse_input(fname, type) abort " {{{1
let [l:lnum, l:cnum] = searchpos(g:vimtex#re#{a:type}_input, 'bcn', line('.'))
if l:lnum == 0 | return a:fname | endif
let l:cmd = vimtex#cmd#get_at(l:lnum, l:cnum)
if empty(l:cmd) | return a:fname | endif
let l:file = join(
\ map(get(l:cmd, 'args', [{}]), {_, x -> get(x, 'text', '')}),
\ '')
let l:file = substitute(l:file, '^\s*"\|"\s*$', '', 'g')
let l:file = substitute(l:file, '\\space', '', 'g')
if l:file[-3:] !=# a:type
let l:file .= '.' . a:type
endif
return l:file
endfunction
" }}}1
function! s:parse_package_documentclass(fname) abort " {{{1
let [l:lnum, l:cnum] = searchpos(s:re_cmds, 'bcn', line('.'))
if l:lnum == 0 | return a:fname | endif
let l:cmd = vimtex#cmd#get_at(l:lnum, l:cnum)
if empty(l:cmd) | return a:fname | endif
let l:args = get(l:cmd, 'args', [{}])
if l:cmd.name =~# 'PassOptionsTo'
let l:result = l:args[1].text
else
let l:result = l:args[0].text
endif
return trim(l:result)
endfunction
let s:re_cmds = '\v\s*\\%(' . join([
\ 'documentclass',
\ 'LoadClass',
\ 'usepackage',
\ 'RequirePackage',
\ 'PassOptionsToClass',
\ 'PassOptionsToPackage'
\], '|') . ')'
" }}}1
function! s:search_candidates_texinputs(fname) abort " {{{1
for l:suffix in [''] + split(&l:suffixesadd, ',')
let l:candidates = glob(b:vimtex.root . '/**/'
\ . fnameescape(a:fname) . l:suffix, 0, 1)
if !empty(l:candidates)
return l:candidates[0]
endif
endfor
return ''
endfunction
" }}}1
function! s:search_candidates_kpsewhich(fname) abort " {{{1
" Split input list on commas, and if applicable, ensure that the entry that
" the cursor is on is placed first in the queue
let l:files = split(a:fname, '\s*,\s*')
let l:current = expand('<cword>')
let l:index = index(l:files, l:current)
if l:index >= 0
call remove(l:files, l:index)
let l:files = [l:current] + l:files
endif
" Add file extensions to create the final list of candidate files
let l:candidates = []
for l:file in l:files
if !empty(fnamemodify(l:file, ':e'))
call add(l:candidates, l:file)
else
call extend(l:candidates, map(split(&l:suffixesadd, ','), 'l:file . v:val'))
endif
endfor
for l:file in l:candidates
let l:candidate = get(vimtex#kpsewhich#run(fnameescape(l:file)), 0, '')
if !empty(l:candidate) && filereadable(l:candidate) | return l:candidate | endif
endfor
return ''
endfunction
" }}}1
let s:visited = {
\ 'time' : 0,
\ 'list' : [],
\}
function! s:visited.timeout() abort dict " {{{1
if localtime() - self.time > 1
let self.time = localtime()
let self.list = [expand('%:p')]
endif
endfunction
" }}}1
function! s:visited.check(fname) abort dict " {{{1
if index(self.list, fnamemodify(a:fname, ':p')) < 0
call add(self.list, fnamemodify(a:fname, ':p'))
return a:fname
endif
return ''
endfunction
" }}}1
|