summaryrefslogtreecommitdiffstats
path: root/ftplugin
diff options
context:
space:
mode:
Diffstat (limited to 'ftplugin')
-rw-r--r--ftplugin/ansible.vim2
-rw-r--r--ftplugin/latex-box/common.vim417
-rw-r--r--ftplugin/latex-box/complete.vim936
-rw-r--r--ftplugin/latex-box/findmain.vim66
-rw-r--r--ftplugin/latex-box/folding.vim382
-rw-r--r--ftplugin/latex-box/latexmk.vim558
-rw-r--r--ftplugin/latex-box/mappings.vim110
-rw-r--r--ftplugin/latex-box/motion.vim548
-rw-r--r--ftplugin/latextoc.vim206
-rw-r--r--ftplugin/tex_LatexBox.vim37
-rw-r--r--ftplugin/vue.vim7
11 files changed, 3268 insertions, 1 deletions
diff --git a/ftplugin/ansible.vim b/ftplugin/ansible.vim
index bbfd05df..e068dd3a 100644
--- a/ftplugin/ansible.vim
+++ b/ftplugin/ansible.vim
@@ -4,6 +4,6 @@ if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'ansible') == -1
if exists('+regexpengine') && ('&regexpengine' == 0)
setlocal regexpengine=1
endif
-set path+=./../templates,./../files
+set path+=./../templates,./../files,templates,files
endif
diff --git a/ftplugin/latex-box/common.vim b/ftplugin/latex-box/common.vim
new file mode 100644
index 00000000..20488846
--- /dev/null
+++ b/ftplugin/latex-box/common.vim
@@ -0,0 +1,417 @@
+if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'latex') == -1
+
+" LaTeX Box common functions
+
+" Error Format {{{
+" Note: The error formats assume we're using the -file-line-error with
+" [pdf]latex.
+" Note: See |errorformat-LaTeX| for more info.
+
+" Check for options
+if !exists("g:LatexBox_show_warnings")
+ let g:LatexBox_show_warnings=1
+endif
+if !exists("g:LatexBox_ignore_warnings")
+ let g:LatexBox_ignore_warnings =
+ \['Underfull',
+ \ 'Overfull',
+ \ 'specifier changed to']
+endif
+
+" Standard error message formats
+" Note: We consider statements that starts with "!" as errors
+setlocal efm=%E!\ LaTeX\ %trror:\ %m
+setlocal efm+=%E%f:%l:\ %m
+setlocal efm+=%E!\ %m
+
+" More info for undefined control sequences
+setlocal efm+=%Z<argument>\ %m
+
+" More info for some errors
+setlocal efm+=%Cl.%l\ %m
+
+" Show or ignore warnings
+if g:LatexBox_show_warnings
+ " Parse biblatex warnings
+ setlocal efm+=%-C(biblatex)%.%#in\ t%.%#
+ setlocal efm+=%-C(biblatex)%.%#Please\ v%.%#
+ setlocal efm+=%-C(biblatex)%.%#LaTeX\ a%.%#
+ setlocal efm+=%-Z(biblatex)%m
+
+ " Parse hyperref warnings
+ setlocal efm+=%-C(hyperref)%.%#on\ input\ line\ %l.
+
+ for w in g:LatexBox_ignore_warnings
+ let warning = escape(substitute(w, '[\,]', '%\\\\&', 'g'), ' ')
+ exe 'setlocal efm+=%-G%.%#'. warning .'%.%#'
+ endfor
+ setlocal efm+=%+WLaTeX\ %.%#Warning:\ %.%#line\ %l%.%#
+ setlocal efm+=%+W%.%#\ at\ lines\ %l--%*\\d
+ setlocal efm+=%+WLaTeX\ %.%#Warning:\ %m
+ setlocal efm+=%+W%.%#Warning:\ %m
+else
+ setlocal efm+=%-WLaTeX\ %.%#Warning:\ %.%#line\ %l%.%#
+ setlocal efm+=%-W%.%#\ at\ lines\ %l--%*\\d
+ setlocal efm+=%-WLaTeX\ %.%#Warning:\ %m
+ setlocal efm+=%-W%.%#Warning:\ %m
+endif
+
+" Push file to file stack
+setlocal efm+=%+P**%f
+setlocal efm+=%+P**\"%f\"
+
+" Ignore unmatched lines
+setlocal efm+=%-G%.%#
+" }}}
+
+" Vim Windows {{{
+
+" Type of split, "new" for horiz. "vnew" for vert.
+if !exists('g:LatexBox_split_type')
+ let g:LatexBox_split_type = "vnew"
+endif
+
+" Length of vertical splits
+if !exists('g:LatexBox_split_length')
+ let g:LatexBox_split_length = 15
+endif
+
+" Width of horizontal splits
+if !exists('g:LatexBox_split_width')
+ let g:LatexBox_split_width = 30
+endif
+
+" Where splits appear
+if !exists('g:LatexBox_split_side')
+ let g:LatexBox_split_side = "aboveleft"
+endif
+
+" Resize when split?
+if !exists('g:LatexBox_split_resize')
+ let g:LatexBox_split_resize = 0
+endif
+
+" Toggle help info
+if !exists('g:LatexBox_toc_hidehelp')
+ let g:LatexBox_toc_hidehelp = 0
+endif
+" }}}
+
+" Filename utilities {{{
+function! LatexBox_GetMainTexFile()
+
+ " 1. check for the b:main_tex_file variable
+ if exists('b:main_tex_file') && filereadable(b:main_tex_file)
+ return b:main_tex_file
+ endif
+
+
+ " 2. scan the first few lines of the file for root = filename
+ for linenum in range(1,5)
+ let linecontents = getline(linenum)
+ if linecontents =~ 'root\s*='
+ " Remove everything but the filename
+ let b:main_tex_file = substitute(linecontents,
+ \ '.*root\s*=\s*', "", "")
+ let b:main_tex_file = substitute(b:main_tex_file, '\s*$', "", "")
+ " Prepend current directory if this isn't an absolute path
+ if b:main_tex_file !~ '^/'
+ let b:main_tex_file = expand('%:p:h') . '/' . b:main_tex_file
+ endif
+ let b:main_tex_file = fnamemodify(b:main_tex_file, ":p")
+ if b:main_tex_file !~ '\.tex$'
+ let b:main_tex_file .= '.tex'
+ endif
+ return b:main_tex_file
+ endif
+ endfor
+
+ " 3. scan current file for "\begin{document}"
+ if &filetype == 'tex' && search('\m\C\\begin\_\s*{document}', 'nw') != 0
+ return expand('%:p')
+ endif
+
+ " 4. use 'main.tex' if it exists in the same directory (and is readable)
+ let s:main_dot_tex_file=expand('%:p:h') . '/main.tex'
+ if filereadable(s:main_dot_tex_file)
+ let b:main_tex_file=s:main_dot_tex_file
+ return b:main_tex_file
+ endif
+
+ " 5. borrow the Vim-Latex-Suite method of finding it
+ if LatexBox_GetMainFileName() != expand('%:p')
+ let b:main_tex_file = LatexBox_GetMainFileName()
+ return b:main_tex_file
+ endif
+
+ " 6. prompt for file with completion
+ let b:main_tex_file = s:PromptForMainFile()
+ return b:main_tex_file
+endfunction
+
+function! s:PromptForMainFile()
+ let saved_dir = getcwd()
+ execute 'cd ' . fnameescape(expand('%:p:h'))
+
+ " Prompt for file
+ let l:file = ''
+ while !filereadable(l:file)
+ let l:file = input('main LaTeX file: ', '', 'file')
+ if l:file !~ '\.tex$'
+ let l:file .= '.tex'
+ endif
+ endwhile
+ let l:file = fnamemodify(l:file, ':p')
+
+ " Make persistent
+ let l:persistent = ''
+ while l:persistent !~ '\v^(y|n)'
+ let l:persistent = input('make choice persistent? (y, n) ')
+ if l:persistent == 'y'
+ call writefile([], l:file . '.latexmain')
+ endif
+ endwhile
+
+ execute 'cd ' . fnameescape(saved_dir)
+ return l:file
+endfunction
+
+" Return the directory of the main tex file
+function! LatexBox_GetTexRoot()
+ return fnamemodify(LatexBox_GetMainTexFile(), ':h')
+endfunction
+
+function! LatexBox_GetBuildBasename(with_dir)
+ " 1. Check for g:LatexBox_jobname
+ if exists('g:LatexBox_jobname')
+ return g:LatexBox_jobname
+ endif
+
+ " 2. Get the basename from the main tex file
+ if a:with_dir
+ return fnamemodify(LatexBox_GetMainTexFile(), ':r')
+ else
+ return fnamemodify(LatexBox_GetMainTexFile(), ':t:r')
+ endif
+endfunction
+
+function! LatexBox_GetAuxFile()
+ " 1. check for b:build_dir variable
+ if exists('b:build_dir') && isdirectory(b:build_dir)
+ return b:build_dir . '/' . LatexBox_GetBuildBasename(0) . '.aux'
+ endif
+
+ " 2. check for g:LatexBox_build_dir variable
+ if exists('g:LatexBox_build_dir') && isdirectory(g:LatexBox_build_dir)
+ return g:LatexBox_build_dir . '/' . LatexBox_GetBuildBasename(0) . '.aux'
+ endif
+
+ " 3. use the base name of main tex file
+ return LatexBox_GetBuildBasename(1) . '.aux'
+endfunction
+
+function! LatexBox_GetLogFile()
+ " 1. check for b:build_dir variable
+ if exists('b:build_dir') && isdirectory(b:build_dir)
+ return b:build_dir . '/' . LatexBox_GetBuildBasename(0) . '.log'
+ endif
+
+ " 2. check for g:LatexBox_build_dir variable
+ if exists('g:LatexBox_build_dir') && isdirectory(g:LatexBox_build_dir)
+ return g:LatexBox_build_dir . '/' . LatexBox_GetBuildBasename(0) . '.log'
+ endif
+
+ " 3. use the base name of main tex file
+ return LatexBox_GetBuildBasename(1) . '.log'
+endfunction
+
+function! LatexBox_GetOutputFile()
+ " 1. check for b:build_dir variable
+ if exists('b:build_dir') && isdirectory(b:build_dir)
+ return b:build_dir . '/' . LatexBox_GetBuildBasename(0)
+ \ . '.' . g:LatexBox_output_type
+ endif
+
+ " 2. check for g:LatexBox_build_dir variable
+ if exists('g:LatexBox_build_dir') && isdirectory(g:LatexBox_build_dir)
+ return g:LatexBox_build_dir . '/' . LatexBox_GetBuildBasename(0)
+ \ . '.' . g:LatexBox_output_type
+ endif
+
+ " 3. use the base name of main tex file
+ return LatexBox_GetBuildBasename(1) . '.' . g:LatexBox_output_type
+endfunction
+" }}}
+
+" View Output {{{
+
+" Default pdf viewer
+if !exists('g:LatexBox_viewer')
+ " On windows, 'running' a file will open it with the default program
+ let s:viewer = ''
+ if has('unix')
+ " echo -n necessary as uname -s will append \n otherwise
+ let s:uname = system('echo -n $(uname -s)')
+ if s:uname == "Darwin"
+ let s:viewer = 'open'
+ else
+ let s:viewer = 'xdg-open'
+ endif
+ endif
+ let g:LatexBox_viewer = s:viewer
+endif
+
+function! LatexBox_View(...)
+ let lvargs = join(a:000, ' ')
+ let outfile = LatexBox_GetOutputFile()
+ if !filereadable(outfile)
+ echomsg fnamemodify(outfile, ':.') . ' is not readable'
+ return
+ endif
+ let cmd = g:LatexBox_viewer . ' ' . lvargs . ' ' . shellescape(outfile)
+ if has('win32')
+ let cmd = '!start /b ' . cmd . ' >nul'
+ else
+ let cmd = '!' . cmd . ' '
+ if fnamemodify(&shell, ':t') ==# 'fish'
+ let cmd .= ' >/dev/null ^/dev/null &'
+ else
+ let cmd .= ' &>/dev/null &'
+ endif
+ endif
+ silent execute cmd
+ if !has("gui_running")
+ redraw!
+ endif
+endfunction
+
+command! -nargs=* LatexView call LatexBox_View('<args>')
+" }}}
+
+" In Comment {{{
+
+" LatexBox_InComment([line], [col])
+" return true if inside comment
+function! LatexBox_InComment(...)
+ let line = a:0 >= 1 ? a:1 : line('.')
+ let col = a:0 >= 2 ? a:2 : col('.')
+ return synIDattr(synID(line, col, 0), "name") =~# '^texComment'
+endfunction
+" }}}
+
+" Get Current Environment {{{
+
+" LatexBox_GetCurrentEnvironment([with_pos])
+" Returns:
+" - environment
+" if with_pos is not given
+" - [envirnoment, lnum_begin, cnum_begin, lnum_end, cnum_end]
+" if with_pos is nonzero
+function! LatexBox_GetCurrentEnvironment(...)
+ if a:0 > 0
+ let with_pos = a:1
+ else
+ let with_pos = 0
+ endif
+
+ let begin_pat = '\C\\begin\_\s*{[^}]*}\|\\\@<!\\\[\|\\\@<!\\('
+ let end_pat = '\C\\end\_\s*{[^}]*}\|\\\@<!\\\]\|\\\@<!\\)'
+ let saved_pos = getpos('.')
+
+ " move to the left until on a backslash
+ let [bufnum, lnum, cnum, off] = getpos('.')
+ let line = getline(lnum)
+ while cnum > 1 && line[cnum - 1] != '\'
+ let cnum -= 1
+ endwhile
+ call cursor(lnum, cnum)
+
+ " match begin/end pairs but skip comments
+ let flags = 'bnW'
+ if strpart(getline('.'), col('.') - 1) =~ '^\%(' . begin_pat . '\)'
+ let flags .= 'c'
+ endif
+ let [lnum1, cnum1] = searchpairpos(begin_pat, '', end_pat, flags,
+ \ 'LatexBox_InComment()')
+
+ let env = ''
+
+ if lnum1
+ let line = strpart(getline(lnum1), cnum1 - 1)
+
+ if empty(env)
+ let env = matchstr(line, '^\C\\begin\_\s*{\zs[^}]*\ze}')
+ endif
+ if empty(env)
+ let env = matchstr(line, '^\\\[')
+ endif
+ if empty(env)
+ let env = matchstr(line, '^\\(')
+ endif
+ endif
+
+ if with_pos == 1
+ let flags = 'nW'
+ if !(lnum1 == lnum && cnum1 == cnum)
+ let flags .= 'c'
+ endif
+
+ let [lnum2, cnum2] = searchpairpos(begin_pat, '', end_pat, flags,
+ \ 'LatexBox_InComment()')
+
+ call setpos('.', saved_pos)
+ return [env, lnum1, cnum1, lnum2, cnum2]
+ else
+ call setpos('.', saved_pos)
+ return env
+ endif
+endfunction
+" }}}
+
+" Tex To Tree {{{
+" stores nested braces in a tree structure
+function! LatexBox_TexToTree(str)
+ let tree = []
+ let i1 = 0
+ let i2 = -1
+ let depth = 0
+ while i2 < len(a:str)
+ let i2 = match(a:str, '[{}]', i2 + 1)
+ if i2 < 0
+ let i2 = len(a:str)
+ endif
+ if i2 >= len(a:str) || a:str[i2] == '{'
+ if depth == 0
+ let item = substitute(strpart(a:str, i1, i2 - i1),
+ \ '^\s*\|\s*$', '', 'g')
+ if !empty(item)
+ call add(tree, item)
+ endif
+ let i1 = i2 + 1
+ endif
+ let depth += 1
+ else
+ let depth -= 1
+ if depth == 0
+ call add(tree, LatexBox_TexToTree(strpart(a:str, i1, i2 - i1)))
+ let i1 = i2 + 1
+ endif
+ endif
+ endwhile
+ return tree
+endfunction
+" }}}
+
+" Tree To Tex {{{
+function! LatexBox_TreeToTex(tree)
+ if type(a:tree) == type('')
+ return a:tree
+ else
+ return '{' . join(map(a:tree, 'LatexBox_TreeToTex(v:val)'), '') . '}'
+ endif
+endfunction
+" }}}
+
+" vim:fdm=marker:ff=unix:noet:ts=4:sw=4
+
+endif
diff --git a/ftplugin/latex-box/complete.vim b/ftplugin/latex-box/complete.vim
new file mode 100644
index 00000000..aecb0d8d
--- /dev/null
+++ b/ftplugin/latex-box/complete.vim
@@ -0,0 +1,936 @@
+if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'latex') == -1
+
+" LaTeX Box completion
+
+setlocal omnifunc=LatexBox_Complete
+
+" <SID> Wrap {{{
+function! s:GetSID()
+ return matchstr(expand('<sfile>'), '\zs<SNR>\d\+_\ze.*$')
+endfunction
+let s:SID = s:GetSID()
+function! s:SIDWrap(func)
+ return s:SID . a:func
+endfunction
+" }}}
+
+" Completion {{{
+if !exists('g:LatexBox_completion_close_braces')
+ let g:LatexBox_completion_close_braces = 1
+endif
+if !exists('g:LatexBox_bibtex_wild_spaces')
+ let g:LatexBox_bibtex_wild_spaces = 1
+endif
+
+if !exists('g:LatexBox_cite_pattern')
+ let g:LatexBox_cite_pattern = '\C\\\a*cite\a*\*\?\(\[[^\]]*\]\)*\_\s*{'
+endif
+if !exists('g:LatexBox_ref_pattern')
+ let g:LatexBox_ref_pattern = '\C\\v\?\(eq\|page\|[cC]\|labelc\|name\|auto\)\?ref\*\?\_\s*{'
+endif
+
+if !exists('g:LatexBox_completion_environments')
+ let g:LatexBox_completion_environments = [
+ \ {'word': 'itemize', 'menu': 'bullet list' },
+ \ {'word': 'enumerate', 'menu': 'numbered list' },
+ \ {'word': 'description', 'menu': 'description' },
+ \ {'word': 'center', 'menu': 'centered text' },
+ \ {'word': 'figure', 'menu': 'floating figure' },
+ \ {'word': 'table', 'menu': 'floating table' },
+ \ {'word': 'equation', 'menu': 'equation (numbered)' },
+ \ {'word': 'align', 'menu': 'aligned equations (numbered)' },
+ \ {'word': 'align*', 'menu': 'aligned equations' },
+ \ {'word': 'document' },
+ \ {'word': 'abstract' },
+ \ ]
+endif
+
+if !exists('g:LatexBox_completion_commands')
+ let g:LatexBox_completion_commands = [
+ \ {'word': '\begin{' },
+ \ {'word': '\end{' },
+ \ {'word': '\item' },
+ \ {'word': '\label{' },
+ \ {'word': '\ref{' },
+ \ {'word': '\eqref{eq:' },
+ \ {'word': '\cite{' },
+ \ {'word': '\chapter{' },
+ \ {'word': '\section{' },
+ \ {'word': '\subsection{' },
+ \ {'word': '\subsubsection{' },
+ \ {'word': '\paragraph{' },
+ \ {'word': '\nonumber' },
+ \ {'word': '\bibliography' },
+ \ {'word': '\bibliographystyle' },
+ \ ]
+endif
+
+if !exists('g:LatexBox_complete_inlineMath')
+ let g:LatexBox_complete_inlineMath = 0
+endif
+
+if !exists('g:LatexBox_eq_env_patterns')
+ let g:LatexBox_eq_env_patterns = 'equation\|gather\|multiline\|align\|flalign\|alignat\|eqnarray'
+endif
+
+" }}}
+
+"LatexBox_kpsewhich {{{
+function! LatexBox_kpsewhich(file)
+ let old_dir = getcwd()
+ execute 'lcd ' . fnameescape(LatexBox_GetTexRoot())
+ let out = system('kpsewhich "' . a:file . '"')
+
+ " If kpsewhich has found something, it returns a non-empty string with a
+ " newline at the end; otherwise the string is empty
+ if len(out)
+ " Remove the trailing newline
+ let out = fnamemodify(out[:-2], ':p')
+ endif
+
+ execute 'lcd ' . fnameescape(old_dir)
+
+ return out
+endfunction
+"}}}
+
+" Omni Completion {{{
+
+let s:completion_type = ''
+
+function! LatexBox_Complete(findstart, base)
+ if a:findstart
+ " return the starting position of the word
+ let line = getline('.')
+ let pos = col('.') - 1
+ while pos > 0 && line[pos - 1] !~ '\\\|{'
+ let pos -= 1
+ endwhile
+
+ let line_start = line[:pos-1]
+ if line_start =~ '\m\C\\begin\_\s*{$'
+ let s:completion_type = 'begin'
+ elseif line_start =~ '\m\C\\end\_\s*{$'
+ let s:completion_type = 'end'
+ elseif line_start =~ '\m' . g:LatexBox_ref_pattern . '$'
+ let s:completion_type = 'ref'
+ elseif line_start =~ '\m' . g:LatexBox_cite_pattern . '$'
+ let s:completion_type = 'bib'
+ " check for multiple citations
+ let pos = col('.') - 1
+ while pos > 0 && line[pos - 1] !~ '{\|,'
+ let pos -= 1
+ endwhile
+ elseif s:LatexBox_complete_inlineMath_or_not()
+ let s:completion_type = 'inlineMath'
+ let pos = s:eq_pos
+ else
+ let s:completion_type = 'command'
+ if line[pos - 1] == '\'
+ let pos -= 1
+ endif
+ endif
+ return pos
+ else
+ " return suggestions in an array
+ let suggestions = []
+
+ if s:completion_type == 'begin'
+ " suggest known environments
+ for entry in g:LatexBox_completion_environments
+ if entry.word =~ '^' . escape(a:base, '\')
+ if g:LatexBox_completion_close_braces && !s:NextCharsMatch('^}')
+ " add trailing '}'
+ let entry = copy(entry)
+ let entry.abbr = entry.word
+ let entry.word = entry.word . '}'
+ endif
+ call add(suggestions, entry)
+ endif
+ endfor
+ elseif s:completion_type == 'end'
+ " suggest known environments
+ let env = LatexBox_GetCurrentEnvironment()
+ if env != ''
+ if g:LatexBox_completion_close_braces && !s:NextCharsMatch('^\s*[,}]')
+ call add(suggestions, {'word': env . '}', 'abbr': env})
+ else
+ call add(suggestions, env)
+ endif
+ endif
+ elseif s:completion_type == 'command'
+ " suggest known commands
+ for entry in g:LatexBox_completion_commands
+ if entry.word =~ '^' . escape(a:base, '\')
+ " do not display trailing '{'
+ if entry.word =~ '{'
+ let entry.abbr = entry.word[0:-2]
+ endif
+ call add(suggestions, entry)
+ endif
+ endfor
+ elseif s:completion_type == 'ref'
+ let suggestions = s:CompleteLabels(a:base)
+ elseif s:completion_type == 'bib'
+ " suggest BibTeX entries
+ let suggestions = LatexBox_BibComplete(a:base)
+ elseif s:completion_type == 'inlineMath'
+ let suggestions = s:LatexBox_inlineMath_completion(a:base)
+ endif
+ if !has('gui_running')
+ redraw!
+ endif
+ return suggestions
+ endif
+endfunction
+" }}}
+
+" BibTeX search {{{
+
+" find the \bibliography{...} commands
+" the optional argument is the file name to be searched
+
+function! s:FindBibData(...)
+ if a:0 == 0
+ let file = LatexBox_GetMainTexFile()
+ else
+ let file = a:1
+ endif
+
+ if !filereadable(file)
+ return []
+ endif
+ let lines = readfile(file)
+ let bibdata_list = []
+
+ "
+ " Search for added bibliographies
+ "
+ let bibliography_cmds = [
+ \ '\\bibliography',
+ \ '\\addbibresource',
+ \ '\\addglobalbib',
+ \ '\\addsectionbib',
+ \ ]
+ for cmd in bibliography_cmds
+ let filtered = filter(copy(lines),
+ \ 'v:val =~ ''\C' . cmd . '\s*{[^}]\+}''')
+ let files = map(filtered,
+ \ 'matchstr(v:val, ''\C' . cmd . '\s*{\zs[^}]\+\ze}'')')
+ for file in files
+ let bibdata_list += map(split(file, ','),
+ \ 'fnamemodify(v:val, '':r'')')
+ endfor
+ endfor
+
+ "
+ " Also search included files
+ "
+ for input in filter(lines,
+ \ 'v:val =~ ''\C\\\%(input\|include\)\s*{[^}]\+}''')
+ let bibdata_list += s:FindBibData(LatexBox_kpsewhich(
+ \ matchstr(input,
+ \ '\C\\\%(input\|include\)\s*{\zs[^}]\+\ze}')))
+ endfor
+
+ return bibdata_list
+endfunction
+
+let s:bstfile = expand('<sfile>:p:h') . '/vimcomplete'
+
+function! LatexBox_BibSearch(regexp)
+ let res = []
+
+ " Find data from bib files
+ let bibdata = join(s:FindBibData(), ',')
+ if bibdata != ''
+
+ " write temporary aux file
+ let tmpbase = LatexBox_GetTexRoot() . '/_LatexBox_BibComplete'
+ let auxfile = tmpbase . '.aux'
+ let bblfile = tmpbase . '.bbl'
+ let blgfile = tmpbase . '.blg'
+
+ call writefile(['\citation{*}', '\bibstyle{' . s:bstfile . '}',
+ \ '\bibdata{' . bibdata . '}'], auxfile)
+
+ if has('win32')
+ let l:old_shellslash = &l:shellslash
+ setlocal noshellslash
+ call system('cd ' . shellescape(LatexBox_GetTexRoot()) .
+ \ ' & bibtex -terse '
+ \ . fnamemodify(auxfile, ':t') . ' >nul')
+ let &l:shellslash = l:old_shellslash
+ else
+ call system('cd ' . shellescape(LatexBox_GetTexRoot()) .
+ \ ' ; bibtex -terse '
+ \ . fnamemodify(auxfile, ':t') . ' >/dev/null')
+ endif
+
+ let lines = split(substitute(join(readfile(bblfile), "\n"),
+ \ '\n\n\@!\(\s\=\)\s*\|{\|}', '\1', 'g'), "\n")
+
+ for line in filter(lines, 'v:val =~ a:regexp')
+ let matches = matchlist(line,
+ \ '^\(.*\)||\(.*\)||\(.*\)||\(.*\)||\(.*\)')
+ if !empty(matches) && !empty(matches[1])
+ let s:type_length = max([s:type_length,
+ \ len(matches[2]) + 3])
+ call add(res, {
+ \ 'key': matches[1],
+ \ 'type': matches[2],
+ \ 'author': matches[3],
+ \ 'year': matches[4],
+ \ 'title': matches[5],
+ \ })
+ endif
+ endfor
+
+ call delete(auxfile)
+ call delete(bblfile)
+ call delete(blgfile)
+ endif
+
+ " Find data from 'thebibliography' environments
+ let lines = readfile(LatexBox_GetMainTexFile())
+ if match(lines, '\C\\begin{thebibliography}') >= 0
+ for line in filter(filter(lines, 'v:val =~ ''\C\\bibitem'''),
+ \ 'v:val =~ a:regexp')
+ let match = matchlist(line, '\\bibitem{\([^}]*\)')[1]
+ call add(res, {
+ \ 'key': match,
+ \ 'type': '',
+ \ 'author': '',
+ \ 'year': '',
+ \ 'title': match,
+ \ })
+ endfor
+ endif
+
+ return res
+endfunction
+" }}}
+
+" BibTeX completion {{{
+let s:type_length=0
+function! LatexBox_BibComplete(regexp)
+
+ " treat spaces as '.*' if needed
+ if g:LatexBox_bibtex_wild_spaces
+ "let regexp = substitute(a:regexp, '\s\+', '.*', 'g')
+ let regexp = '.*' . substitute(a:regexp, '\s\+', '\\\&.*', 'g')
+ else
+ let regexp = a:regexp
+ endif
+
+ let res = []
+ let s:type_length = 4
+ for m in LatexBox_BibSearch(regexp)
+ let type = m['type'] == '' ? '[-]' : '[' . m['type'] . '] '
+ let type = printf('%-' . s:type_length . 's', type)
+ let auth = m['author'] == '' ? '' : m['author'][:20] . ' '
+ let auth = substitute(auth, '\~', ' ', 'g')
+ let auth = substitute(auth, ',.*\ze', ' et al. ', '')
+ let year = m['year'] == '' ? '' : '(' . m['year'] . ')'
+ let w = { 'word': m['key'],
+ \ 'abbr': type . auth . year,
+ \ 'menu': m['title'] }
+
+ " close braces if needed
+ if g:LatexBox_completion_close_braces && !s:NextCharsMatch('^\s*[,}]')
+ let w.word = w.word . '}'
+ endif
+
+ call add(res, w)
+ endfor
+ return res
+endfunction
+" }}}
+
+" ExtractLabels {{{
+" Generate list of \newlabel commands in current buffer.
+"
+" Searches the current buffer for commands of the form
+" \newlabel{name}{{number}{page}.*
+" and returns list of [ name, number, page ] tuples.
+function! s:ExtractLabels()
+ call cursor(1,1)
+
+ let matches = []
+ let [lblline, lblbegin] = searchpos( '\\newlabel{', 'ecW' )
+
+ while [lblline, lblbegin] != [0,0]
+ let [nln, nameend] = searchpairpos( '{', '', '}', 'W' )
+ if nln != lblline
+ let [lblline, lblbegin] = searchpos( '\\newlabel{', 'ecW' )
+ continue
+ endif
+ let curname = strpart( getline( lblline ), lblbegin, nameend - lblbegin - 1 )
+
+ " Ignore cref entries (because they are duplicates)
+ if curname =~# "@cref$"
+ let [lblline, lblbegin] = searchpos( '\\newlabel{', 'ecW' )
+ continue
+ endif
+
+ if 0 == search( '\m{\w*{', 'ce', lblline )
+ let [lblline, lblbegin] = searchpos( '\\newlabel{', 'ecW' )
+ continue
+ endif
+
+ let numberbegin = getpos('.')[2]
+ let [nln, numberend] = searchpairpos( '{', '', '}', 'W' )
+ if nln != lblline
+ let [lblline, lblbegin] = searchpos( '\\newlabel{', 'ecW' )
+ continue
+ endif
+ let curnumber = strpart( getline( lblline ), numberbegin, numberend - numberbegin - 1 )
+
+ if 0 == search( '\m\w*{', 'ce', lblline )
+ let [lblline, lblbegin] = searchpos( '\\newlabel{', 'ecW' )
+ continue
+ endif
+
+ let pagebegin = getpos('.')[2]
+ let [nln, pageend] = searchpairpos( '{', '', '}', 'W' )
+ if nln != lblline
+ let [lblline, lblbegin] = searchpos( '\\newlabel{', 'ecW' )
+ continue
+ endif
+ let curpage = strpart( getline( lblline ), pagebegin, pageend - pagebegin - 1 )
+
+ let matches += [ [ curname, curnumber, curpage ] ]
+
+ let [lblline, lblbegin] = searchpos( '\\newlabel{', 'ecW' )
+ endwhile
+
+ return matches
+endfunction
+"}}}
+
+" ExtractInputs {{{
+" Generate list of \@input commands in current buffer.
+"
+" Searches the current buffer for \@input{file} entries and
+" returns list of all files.
+function! s:ExtractInputs()
+ call cursor(1,1)
+
+ let matches = []
+ let [inline, inbegin] = searchpos( '\\@input{', 'ecW' )
+
+ while [inline, inbegin] != [0,0]
+ let [nln, inend] = searchpairpos( '{', '', '}', 'W' )
+ if nln != inline
+ let [inline, inbegin] = searchpos( '\\@input{', 'ecW' )
+ continue
+ endif
+ let matches += [ LatexBox_kpsewhich(strpart( getline( inline ), inbegin, inend - inbegin - 1 )) ]
+
+ let [inline, inbegin] = searchpos( '\\@input{', 'ecW' )
+ endwhile
+
+ " Remove empty strings for nonexistant .aux files
+ return filter(matches, 'v:val != ""')
+endfunction
+"}}}
+
+" LabelCache {{{
+" Cache of all labels.
+"
+" LabelCache is a dictionary mapping filenames to tuples
+" [ time, labels, inputs ]
+" where
+" * time is modification time of the cache entry
+" * labels is a list like returned by ExtractLabels
+" * inputs is a list like returned by ExtractInputs
+let s:LabelCache = {}
+"}}}
+
+" GetLabelCache {{{
+" Extract labels from LabelCache and update it.
+"
+" Compares modification time of each entry in the label
+" cache and updates it, if necessary. During traversal of
+" the LabelCache, all current labels are collected and
+" returned.
+function! s:GetLabelCache(file)
+ if !filereadable(a:file)
+ return []
+ endif
+
+ if !has_key(s:LabelCache , a:file) || s:LabelCache[a:file][0] != getftime(a:file)
+ " Open file in temporary split window for label extraction.
+ let main_tex_file = LatexBox_GetMainTexFile()
+ silent execute '1sp +let\ b:main_tex_file=main_tex_file|let\ labels=s:ExtractLabels()|let\ inputs=s:ExtractInputs()|quit! ' . fnameescape(a:file)
+ let s:LabelCache[a:file] = [ getftime(a:file), labels, inputs ]
+ endif
+
+ " We need to create a copy of s:LabelCache[fid][1], otherwise all inputs'
+ " labels would be added to the current file's label cache upon each
+ " completion call, leading to duplicates/triplicates/etc. and decreased
+ " performance.
+ " Also, because we don't anything with the list besides matching copies,
+ " we can get away with a shallow copy for now.
+ let labels = copy(s:LabelCache[a:file][1])
+
+ for input in s:LabelCache[a:file][2]
+ let labels += s:GetLabelCache(input)
+ endfor
+
+ return labels
+endfunction
+"}}}
+
+" Complete Labels {{{
+function! s:CompleteLabels(regex)
+ let labels = s:GetLabelCache(LatexBox_GetAuxFile())
+
+ let matches = filter( copy(labels), 'match(v:val[0], "' . a:regex . '") != -1' )
+ if empty(matches)
+ " also try to match label and number
+ let regex_split = split(a:regex)
+ if len(regex_split) > 1
+ let base = regex_split[0]
+ let number = escape(join(regex_split[1:], ' '), '.')
+ let matches = filter( copy(labels), 'match(v:val[0], "' . base . '") != -1 && match(v:val[1], "' . number . '") != -1' )
+ endif
+ endif
+ if empty(matches)
+ " also try to match number
+ let matches = filter( copy(labels), 'match(v:val[1], "' . a:regex . '") != -1' )
+ endif
+
+ let suggestions = []
+ for m in matches
+ let entry = {'word': m[0], 'menu': printf("%7s [p. %s]", '('.m[1].')', m[2])}
+ if g:LatexBox_completion_close_braces && !s:NextCharsMatch('^\s*[,}]')
+ " add trailing '}'
+ let entry = copy(entry)
+ let entry.abbr = entry.word
+ let entry.word = entry.word . '}'
+ endif
+ call add(suggestions, entry)
+ endfor
+
+ return suggestions
+endfunction
+" }}}
+
+" Complete Inline Math Or Not {{{
+" Return 1, when cursor is in a math env:
+" 1, there is a single $ in the current line on the left of cursor
+" 2, there is an open-eq-env on/above the current line
+" (open-eq-env : \(, \[, and \begin{eq-env} )
+" Return 0, when cursor is not in a math env
+function! s:LatexBox_complete_inlineMath_or_not()
+
+ " switch of inline math completion feature
+ if g:LatexBox_complete_inlineMath == 0
+ return 0
+ endif
+
+ " env names that can't appear in an eq env
+ if !exists('s:LatexBox_doc_structure_patterns')
+ let s:LatexBox_doc_structure_patterns = '\%(' . '\\begin\s*{document}\|' .
+ \ '\\\%(chapter\|section\|subsection\|subsubsection\)\*\?\s*{' . '\)'
+ endif
+
+ if !exists('s:LatexBox_eq_env_open_patterns')
+ let s:LatexBox_eq_env_open_patterns = ['\\(','\\\[']
+ endif
+ if !exists('s:LatexBox_eq_env_close_patterns')
+ let s:LatexBox_eq_env_close_patterns = ['\\)','\\\]']
+ endif
+
+ let notcomment = '\%(\%(\\\@<!\%(\\\\\)*\)\@<=%.*\)\@<!'
+
+ let lnum_saved = line('.')
+ let cnum_saved = col('.') -1
+
+ let line = getline('.')
+ let line_start_2_cnum_saved = line[:cnum_saved]
+
+ " determine whether there is a single $ before cursor
+ let cursor_dollar_pair = 0
+ while matchend(line_start_2_cnum_saved, '\$[^$]\+\$', cursor_dollar_pair) >= 0
+ " find the end of dollar pair
+ let cursor_dollar_pair = matchend(line_start_2_cnum_saved, '\$[^$]\+\$', cursor_dollar_pair)
+ endwhile
+ " find single $ after cursor_dollar_pair
+ let cursor_single_dollar = matchend(line_start_2_cnum_saved, '\$', cursor_dollar_pair)
+
+ " if single $ is found
+ if cursor_single_dollar >= 0
+ " check whether $ is in \(...\), \[...\], or \begin{eq}...\end{eq}
+
+ " check current line,
+ " search for LatexBox_eq_env_close_patterns: \[ and \(
+ let lnum = line('.')
+ for i in range(0, (len(s:LatexBox_eq_env_open_patterns)-1))
+ call cursor(lnum_saved, cnum_saved)
+ let cnum_close = searchpos(''. s:LatexBox_eq_env_close_patterns[i].'', 'cbW', lnum_saved)[1]
+ let cnum_open = matchend(line_start_2_cnum_saved, s:LatexBox_eq_env_open_patterns[i], cnum_close)
+ if cnum_open >= 0
+ let s:eq_dollar_parenthesis_bracket_empty = ''
+ let s:eq_pos = cursor_single_dollar - 1
+ return 1
+ end
+ endfor
+
+ " check the lines above
+ " search for s:LatexBox_doc_structure_patterns, and end-of-math-env
+ let lnum -= 1
+ while lnum > 0
+ let line = getline(lnum)
+ if line =~ notcomment . '\(' . s:LatexBox_doc_structure_patterns .
+ \ '\|' . '\\end\s*{\(' . g:LatexBox_eq_env_patterns . '\)\*\?}\)'
+ " when s:LatexBox_doc_structure_patterns or g:LatexBox_eq_env_patterns
+ " are found first, complete math, leave with $ at both sides
+ let s:eq_dollar_parenthesis_bracket_empty = '$'
+ let s:eq_pos = cursor_single_dollar
+ break
+ elseif line =~ notcomment . '\\begin\s*{\(' . g:LatexBox_eq_env_patterns . '\)\*\?}'
+ " g:LatexBox_eq_env_patterns is found, complete math, remove $
+ let s:eq_dollar_parenthesis_bracket_empty = ''
+ let s:eq_pos = cursor_single_dollar - 1
+ break
+ endif
+ let lnum -= 1
+ endwhile
+
+ return 1
+ else
+ " no $ is found, then search for \( or \[ in current line
+ " 1, whether there is \(
+ call cursor(lnum_saved, cnum_saved)
+ let cnum_parenthesis_close = searchpos('\\)', 'cbW', lnum_saved)[1]
+ let cnum_parenthesis_open = matchend(line_start_2_cnum_saved, '\\(', cnum_parenthesis_close)
+ if cnum_parenthesis_open >= 0
+ let s:eq_dollar_parenthesis_bracket_empty = '\)'
+ let s:eq_pos = cnum_parenthesis_open
+ return 1
+ end
+
+ " 2, whether there is \[
+ call cursor(lnum_saved, cnum_saved)
+ let cnum_bracket_close = searchpos('\\\]', 'cbW', lnum_saved)[1]
+ let cnum_bracket_open = matchend(line_start_2_cnum_saved, '\\\[', cnum_bracket_close)
+ if cnum_bracket_open >= 0
+ let s:eq_dollar_parenthesis_bracket_empty = '\]'
+ let s:eq_pos = cnum_bracket_open
+ return 1
+ end
+
+ " not inline math completion
+ return 0
+ endif
+
+endfunction
+" }}}
+
+" Complete inline euqation{{{
+function! s:LatexBox_inlineMath_completion(regex, ...)
+
+ if a:0 == 0
+ let file = LatexBox_GetMainTexFile()
+ else
+ let file = a:1
+ endif
+
+ if empty(glob(file, 1))
+ return ''
+ endif
+
+ if empty(s:eq_dollar_parenthesis_bracket_empty)
+ let inline_pattern1 = '\$\s*\(' . escape(substitute(a:regex[1:], '^\s\+', '', ""), '\.*^') . '[^$]*\)\s*\$'
+ let inline_pattern2 = '\\(\s*\(' . escape(substitute(a:regex[1:], '^\s\+', '', ""), '\.*^') . '.*\)\s*\\)'
+ else
+ let inline_pattern1 = '\$\s*\(' . escape(substitute(a:regex, '^\s\+', '', ""), '\.*^') . '[^$]*\)\s*\$'
+ let inline_pattern2 = '\\(\s*\(' . escape(substitute(a:regex, '^\s\+', '', ""), '\.*^') . '.*\)\s*\\)'
+ endif
+
+
+ let suggestions = []
+ let line_num = 0
+ for line in readfile(file)
+ let line_num = line_num + 1
+
+ let suggestions += s:LatexBox_inlineMath_mathlist(line,inline_pattern1 , line_num) + s:LatexBox_inlineMath_mathlist( line,inline_pattern2, line_num)
+
+ " search for included files
+ let included_file = matchstr(line, '^\\@input{\zs[^}]*\ze}')
+ if included_file != ''
+ let included_file = LatexBox_kpsewhich(included_file)
+ call extend(suggestions, s:LatexBox_inlineMath_completion(a:regex, included_file))
+ endif
+ endfor
+
+ return suggestions
+endfunction
+" }}}
+
+" Search for inline maths {{{
+" search for $ ... $ and \( ... \) in each line
+function! s:LatexBox_inlineMath_mathlist(line,inline_pattern, line_num)
+ let col_start = 0
+ let suggestions = []
+ while 1
+ let matches = matchlist(a:line, a:inline_pattern, col_start)
+ if !empty(matches)
+
+ " show line number of inline math
+ let entry = {'word': matches[1], 'menu': '[' . a:line_num . ']'}
+
+ if s:eq_dollar_parenthesis_bracket_empty != ''
+ let entry = copy(entry)
+ let entry.abbr = entry.word
+ let entry.word = entry.word . s:eq_dollar_parenthesis_bracket_empty
+ endif
+ call add(suggestions, entry)
+
+ " update col_start
+ let col_start = matchend(a:line, a:inline_pattern, col_start)
+ else
+ break
+ endif
+ endwhile
+
+ return suggestions
+endfunction
+" }}}
+
+" Close Current Environment {{{
+function! s:CloseCurEnv()
+ " first, try with \left/\right pairs
+ let [lnum, cnum] = searchpairpos('\C\\left\>', '', '\C\\right\>', 'bnW', 'LatexBox_InComment()')
+ if lnum
+ let line = strpart(getline(lnum), cnum - 1)
+ let bracket = matchstr(line, '^\\left\zs\((\|\[\|\\{\||\|\.\)\ze')
+ for [open, close] in [['(', ')'], ['\[', '\]'], ['\\{', '\\}'], ['|', '|'], ['\.', '|']]
+ let bracket = substitute(bracket, open, close, 'g')
+ endfor
+ return '\right' . bracket
+ endif
+
+ " second, try with environments
+ let env = LatexBox_GetCurrentEnvironment()
+ if env == '\['
+ return '\]'
+ elseif env == '\('
+ return '\)'
+ elseif env != ''
+ return '\end{' . env . '}'
+ endif
+ return ''
+endfunction
+" }}}
+
+" Wrap Selection {{{
+function! s:WrapSelection(wrapper)
+ keepjumps normal! `>a}
+ execute 'keepjumps normal! `<i\' . a:wrapper . '{'
+endfunction
+" }}}
+
+" Wrap Selection in Environment with Prompt {{{
+function! s:PromptEnvWrapSelection(...)
+ let env = input('environment: ', '', 'customlist,' . s:SIDWrap('GetEnvironmentList'))
+ if empty(env)
+ return
+ endif
+ " LaTeXBox's custom indentation can interfere with environment
+ " insertion when environments are indented (common for nested
+ " environments). Temporarily disable it for this operation:
+ let ieOld = &indentexpr
+ setlocal indentexpr=""
+ if visualmode() ==# 'V'
+ execute 'keepjumps normal! `>o\end{' . env . '}'
+ execute 'keepjumps normal! `<O\begin{' . env . '}'
+ " indent and format, if requested.
+ if a:0 && a:1
+ normal! gv>
+ normal! gvgq
+ endif
+ else
+ execute 'keepjumps normal! `>a\end{' . env . '}'
+ execute 'keepjumps normal! `<i\begin{' . env . '}'
+ endif
+ exe "setlocal indentexpr=" . ieOld
+endfunction
+" }}}
+
+" List Labels with Prompt {{{
+function! s:PromptLabelList(...)
+ " Check if window already exists
+ let winnr = bufwinnr(bufnr('LaTeX Labels'))
+ if winnr >= 0
+ if a:0 == 0
+ silent execute winnr . 'wincmd w'
+ else
+ " Supplying an argument to this function causes toggling instead
+ " of jumping to the labels window
+ if g:LatexBox_split_resize
+ silent exe "set columns-=" . g:LatexBox_split_width
+ endif
+ silent execute 'bwipeout' . bufnr('LaTeX Labels')
+ endif
+ return
+ endif
+
+ " Get label suggestions
+ let regexp = input('filter labels with regexp: ', '')
+ let labels = s:CompleteLabels(regexp)
+
+ let calling_buf = bufnr('%')
+
+ " Create labels window and set local settings
+ if g:LatexBox_split_resize
+ silent exe "set columns+=" . g:LatexBox_split_width
+ endif
+ silent exe g:LatexBox_split_side g:LatexBox_split_width . 'vnew LaTeX\ Labels'
+ let b:toc = []
+ let b:toc_numbers = 1
+ let b:calling_win = bufwinnr(calling_buf)
+ setlocal filetype=latextoc
+
+ " Add label entries and jump to the closest section
+ for entry in labels
+ let number = matchstr(entry['menu'], '^\s*(\zs[^)]\+\ze)')
+ let page = matchstr(entry['menu'], '^[^)]*)\s*\[\zs[^]]\+\ze\]')
+ let e = {'file': bufname(calling_buf),
+ \ 'level': 'label',
+ \ 'number': number,
+ \ 'text': entry['abbr'],
+ \ 'page': page}
+ call add(b:toc, e)
+ if b:toc_numbers
+ call append('$', e['number'] . "\t" . e['text'])
+ else
+ call append('$', e['text'])
+ endif
+ endfor
+ if !g:LatexBox_toc_hidehelp
+ call append('$', "")
+ call append('$', "<Esc>/q: close")
+ call append('$', "<Space>: jump")
+ call append('$', "<Enter>: jump and close")
+ call append('$', "s: hide numbering")
+ endif
+ 0delete _
+
+ " Lock buffer
+ setlocal nomodifiable
+endfunction
+" }}}
+
+" Change Environment {{{
+function! s:ChangeEnvPrompt()
+
+ let [env, lnum, cnum, lnum2, cnum2] = LatexBox_GetCurrentEnvironment(1)
+
+ let new_env = input('change ' . env . ' for: ', '', 'customlist,' . s:SIDWrap('GetEnvironmentList'))
+ if empty(new_env)
+ return
+ endif
+
+ if new_env == '\[' || new_env == '['
+ let begin = '\['
+ let end = '\]'
+ elseif new_env == '\(' || new_env == '('
+ let begin = '\('
+ let end = '\)'
+ else
+ let l:begin = '\begin{' . new_env . '}'
+ let l:end = '\end{' . new_env . '}'
+ endif
+
+ if env == '\[' || env == '\('
+ let line = getline(lnum2)
+ let line = strpart(line, 0, cnum2 - 1) . l:end . strpart(line, cnum2 + 1)
+ call setline(lnum2, line)
+
+ let line = getline(lnum)
+ let line = strpart(line, 0, cnum - 1) . l:begin . strpart(line, cnum + 1)
+ call setline(lnum, line)
+ else
+ let line = getline(lnum2)
+ let line = strpart(line, 0, cnum2 - 1) . l:end . strpart(line, cnum2 + len(env) + 5)
+ call setline(lnum2, line)
+
+ let line = getline(lnum)
+ let line = strpart(line, 0, cnum - 1) . l:begin . strpart(line, cnum + len(env) + 7)
+ call setline(lnum, line)
+ endif
+endfunction
+
+function! s:GetEnvironmentList(lead, cmdline, pos)
+ let suggestions = []
+ for entry in g:LatexBox_completion_environments
+ let env = entry.word
+ if env =~ '^' . a:lead
+ call add(suggestions, env)
+ endif
+ endfor
+ return suggestions
+endfunction
+
+function! s:LatexToggleStarEnv()
+ let [env, lnum, cnum, lnum2, cnum2] = LatexBox_GetCurrentEnvironment(1)
+
+ if env == '\('
+ return
+ elseif env == '\['
+ let begin = '\begin{equation}'
+ let end = '\end{equation}'
+ elseif env[-1:] == '*'
+ let begin = '\begin{' . env[:-2] . '}'
+ let end = '\end{' . env[:-2] . '}'
+ else
+ let begin = '\begin{' . env . '*}'
+ let end = '\end{' . env . '*}'
+ endif
+
+ if env == '\['
+ let line = getline(lnum2)
+ let line = strpart(line, 0, cnum2 - 1) . l:end . strpart(line, cnum2 + 1)
+ call setline(lnum2, line)
+
+ let line = getline(lnum)
+ let line = strpart(line, 0, cnum - 1) . l:begin . strpart(line, cnum + 1)
+ call setline(lnum, line)
+ else
+ let line = getline(lnum2)
+ let line = strpart(line, 0, cnum2 - 1) . l:end . strpart(line, cnum2 + len(env) + 5)
+ call setline(lnum2, line)
+
+ let line = getline(lnum)
+ let line = strpart(line, 0, cnum - 1) . l:begin . strpart(line, cnum + len(env) + 7)
+ call setline(lnum, line)
+ endif
+endfunction
+" }}}
+
+" Next Charaters Match {{{
+function! s:NextCharsMatch(regex)
+ let rest_of_line = strpart(getline('.'), col('.') - 1)
+ return rest_of_line =~ a:regex
+endfunction
+" }}}
+
+" Mappings {{{
+inoremap <silent> <Plug>LatexCloseCurEnv <C-R>=<SID>CloseCurEnv()<CR>
+vnoremap <silent> <Plug>LatexWrapSelection :<c-u>call <SID>WrapSelection('')<CR>i
+vnoremap <silent> <Plug>LatexEnvWrapSelection :<c-u>call <SID>PromptEnvWrapSelection()<CR>
+vnoremap <silent> <Plug>LatexEnvWrapFmtSelection :<c-u>call <SID>PromptEnvWrapSelection(1)<CR>
+nnoremap <silent> <Plug>LatexChangeEnv :call <SID>ChangeEnvPrompt()<CR>
+nnoremap <silent> <Plug>LatexToggleStarEnv :call <SID>LatexToggleStarEnv()<CR>
+" }}}
+
+" Commands {{{
+command! LatexLabels call <SID>PromptLabelList()
+" }}}
+
+" vim:fdm=marker:ff=unix:noet:ts=4:sw=4
+
+endif
diff --git a/ftplugin/latex-box/findmain.vim b/ftplugin/latex-box/findmain.vim
new file mode 100644
index 00000000..3b81b0d7
--- /dev/null
+++ b/ftplugin/latex-box/findmain.vim
@@ -0,0 +1,66 @@
+if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'latex') == -1
+
+" LatexBox_GetMainFileName: gets the name of the main file being compiled. {{{
+" Description: returns the full path name of the main file.
+" This function checks for the existence of a .latexmain file
+" which might point to the location of a "main" latex file.
+" If .latexmain exists, then return the full path name of the
+" file being pointed to by it.
+"
+" Otherwise, return the full path name of the current buffer.
+"
+" You can supply an optional "modifier" argument to the
+" function, which will optionally modify the file name before
+" returning.
+" NOTE: From version 1.6 onwards, this function always trims
+" away the .latexmain part of the file name before applying the
+" modifier argument.
+" NOTE: This function is copied from the Latex-Suite project!
+function! LatexBox_GetMainFileName(...)
+ if a:0 > 0
+ let modifier = a:1
+ else
+ let modifier = ':p'
+ endif
+
+ let s:origdir = fnameescape(getcwd())
+
+ let dirmodifier = '%:p:h'
+ let dirLast = fnameescape(expand(dirmodifier))
+ exe 'cd '.dirLast
+
+ " move up the directory tree until we find a .latexmain file.
+ " TODO: Should we be doing this recursion by default, or should there be a
+ " setting?
+ while glob('*.latexmain',1) == ''
+ let dirmodifier = dirmodifier.':h'
+ let dirNew = fnameescape(expand(dirmodifier))
+ " break from the loop if we cannot go up any further.
+ if dirNew == dirLast
+ break
+ endif
+ let dirLast = dirNew
+ exe 'cd '.dirLast
+ endwhile
+
+ let lheadfile = glob('*.latexmain',1)
+ if lheadfile != ''
+ " Remove the trailing .latexmain part of the filename... We never want
+ " that.
+ let lheadfile = fnamemodify(substitute(lheadfile, '\.latexmain$', '', ''), modifier)
+ else
+ " If we cannot find any main file, just modify the filename of the
+ " current buffer.
+ let lheadfile = expand('%'.modifier)
+ endif
+
+ exe 'cd '.s:origdir
+
+ " NOTE: The caller of this function needs to escape the file name with
+ " fnameescape() . The reason its not done here is that escaping is not
+ " safe if this file is to be used as part of an external command on
+ " certain platforms.
+ return lheadfile
+endfunction
+
+endif
diff --git a/ftplugin/latex-box/folding.vim b/ftplugin/latex-box/folding.vim
new file mode 100644
index 00000000..d6f36272
--- /dev/null
+++ b/ftplugin/latex-box/folding.vim
@@ -0,0 +1,382 @@
+if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'latex') == -1
+
+" Folding support for LaTeX
+
+"
+" Options
+" g:LatexBox_Folding - Turn on/off folding
+" g:LatexBox_fold_text - Turn on/off LatexBox fold text function
+" g:LatexBox_fold_preamble - Turn on/off folding of preamble
+" g:LatexBox_fold_parts - Define parts (eq. appendix, frontmatter) to fold
+" g:LatexBox_fold_sections - Define section levels to fold
+" g:LatexBox_fold_envs - Turn on/off folding of environments
+" g:LatexBox_fold_toc - Turn on/off folding of TOC
+" g:LatexBox_fold_toc_levels - Set max TOC fold level
+"
+" {{{1 Initialize options to default values.
+if !exists('g:LatexBox_Folding')
+ let g:LatexBox_Folding=0
+endif
+if !exists('g:LatexBox_fold_text')
+ let g:LatexBox_fold_text=1
+endif
+if !exists('g:LatexBox_fold_preamble')
+ let g:LatexBox_fold_preamble=1
+endif
+if !exists('g:LatexBox_fold_envs')
+ let g:LatexBox_fold_envs=1
+endif
+if !exists('g:LatexBox_fold_envs_force')
+ let g:LatexBox_fold_envs_force = []
+endif
+if !exists('g:LatexBox_fold_parts')
+ let g:LatexBox_fold_parts=[
+ \ "appendix",
+ \ "frontmatter",
+ \ "mainmatter",
+ \ "backmatter"
+ \ ]
+endif
+if !exists('g:LatexBox_fold_sections')
+ let g:LatexBox_fold_sections=[
+ \ "part",
+ \ "chapter",
+ \ "section",
+ \ "subsection",
+ \ "subsubsection"
+ \ ]
+endif
+if !exists('g:LatexBox_fold_toc')
+ let g:LatexBox_fold_toc=0
+endif
+if !exists('g:LatexBox_fold_toc_levels')
+ let g:LatexBox_fold_toc_levels=1
+endif
+if !exists('g:LatexBox_fold_automatic')
+ let g:LatexBox_fold_automatic=1
+endif
+" }}}1
+
+if g:LatexBox_Folding == 0
+ finish
+endif
+
+" {{{1 Set folding options for vim
+setl foldexpr=LatexBox_FoldLevel(v:lnum)
+if g:LatexBox_fold_text == 1
+ setl foldtext=LatexBox_FoldText()
+endif
+if g:LatexBox_fold_automatic == 1
+ setl foldmethod=expr
+
+ "
+ " The foldexpr function returns "=" for most lines, which means it can become
+ " slow for large files. The following is a hack that is based on this reply to
+ " a discussion on the Vim Developer list:
+ " http://permalink.gmane.org/gmane.editors.vim.devel/14100
+ "
+ augroup FastFold
+ autocmd!
+ autocmd InsertEnter *.tex if !&diff | setlocal foldmethod=manual | endif
+ autocmd InsertLeave *.tex if !&diff | setlocal foldmethod=expr | endif
+ augroup end
+else
+ setl foldmethod=manual
+endif
+
+function! LatexBox_FoldOnDemand()
+ setl foldmethod=expr
+ normal! zx
+ setl foldmethod=manual
+endfunction
+
+command! LatexFold call LatexBox_FoldOnDemand()
+
+" {{{1 LatexBox_FoldLevel help functions
+
+" This function parses the tex file to find the sections that are to be folded
+" and their levels, and then predefines the patterns for optimized folding.
+function! s:FoldSectionLevels()
+ " Initialize
+ let level = 1
+ let foldsections = []
+
+ " If we use two or more of the *matter commands, we need one more foldlevel
+ let nparts = 0
+ for part in g:LatexBox_fold_parts
+ let i = 1
+ while i < line("$")
+ if getline(i) =~ '^\s*\\' . part . '\>'
+ let nparts += 1
+ break
+ endif
+ let i += 1
+ endwhile
+ if nparts > 1
+ let level = 2
+ break
+ endif
+ endfor
+
+ " Combine sections and levels, but ignore unused section commands: If we
+ " don't use the part command, then chapter should have the highest
+ " level. If we don't use the chapter command, then section should be the
+ " highest level. And so on.
+ let ignore = 1
+ for part in g:LatexBox_fold_sections
+ " For each part, check if it is used in the file. We start adding the
+ " part patterns to the fold sections array whenever we find one.
+ let partpattern = '^\s*\(\\\|% Fake\)' . part . '\>'
+ if ignore
+ let i = 1
+ while i < line("$")
+ if getline(i) =~# partpattern
+ call insert(foldsections, [partpattern, level])
+ let level += 1
+ let ignore = 0
+ break
+ endif
+ let i += 1
+ endwhile
+ else
+ call insert(foldsections, [partpattern, level])
+ let level += 1
+ endif
+ endfor
+
+ return foldsections
+endfunction
+
+" {{{1 LatexBox_FoldLevel
+
+" Parse file to dynamically set the sectioning fold levels
+let b:LatexBox_FoldSections = s:FoldSectionLevels()
+
+" Optimize by predefine common patterns
+let s:notbslash = '\%(\\\@<!\%(\\\\\)*\)\@<='
+let s:notcomment = '\%(\%(\\\@<!\%(\\\\\)*\)\@<=%.*\)\@<!'
+let s:envbeginpattern = s:notcomment . s:notbslash . '\\begin\s*{.\{-}}'
+let s:envendpattern = s:notcomment . s:notbslash . '\\end\s*{.\{-}}'
+let s:foldparts = '^\s*\\\%(' . join(g:LatexBox_fold_parts, '\|') . '\)'
+let s:folded = '\(% Fake\|\\\(document\|begin\|end\|paragraph\|'
+ \ . 'front\|main\|back\|app\|sub\|section\|chapter\|part\)\)'
+
+function! LatexBox_FoldLevel(lnum)
+ " Check for normal lines first (optimization)
+ let line = getline(a:lnum)
+ if line !~ s:folded
+ return "="
+ endif
+
+ " Fold preamble
+ if g:LatexBox_fold_preamble == 1
+ if line =~# s:notcomment . s:notbslash . '\s*\\documentclass'
+ return ">1"
+ elseif line =~# s:notcomment . s:notbslash . '\s*\\begin\s*{\s*document\s*}'
+ return "0"
+ endif
+ endif
+
+ " Fold parts (\frontmatter, \mainmatter, \backmatter, and \appendix)
+ if line =~# s:foldparts
+ return ">1"
+ endif
+
+ " Fold chapters and sections
+ for [part, level] in b:LatexBox_FoldSections
+ if line =~# part
+ return ">" . level
+ endif
+ endfor
+
+ " Never fold \end{document}
+ if line =~# '^\s*\\end{document}'
+ return 0
+ endif
+
+ " Fold environments
+ if line =~# s:envbeginpattern && line =~# s:envendpattern
+ " If the begin and end pattern are on the same line , do not fold
+ return "="
+ else
+ if line =~# s:envbeginpattern
+ if g:LatexBox_fold_envs == 1
+ return "a1"
+ else
+ let env = matchstr(line,'\\begin\*\?{\zs\w*\*\?\ze}')
+ if index(g:LatexBox_fold_envs_force, env) >= 0
+ return "a1"
+ else
+ return "="
+ endif
+ endif
+ elseif line =~# s:envendpattern
+ if g:LatexBox_fold_envs == 1
+ return "s1"
+ else
+ let env = matchstr(line,'\\end\*\?{\zs\w*\*\?\ze}')
+ if index(g:LatexBox_fold_envs_force, env) >= 0
+ return "s1"
+ else
+ return "="
+ endif
+ endif
+ endif
+ endif
+
+ " Return foldlevel of previous line
+ return "="
+endfunction
+
+" {{{1 LatexBox_FoldText help functions
+function! s:LabelEnv()
+ let i = v:foldend
+ while i >= v:foldstart
+ if getline(i) =~ '^\s*\\label'
+ return matchstr(getline(i), '^\s*\\label{\zs.*\ze}')
+ end
+ let i -= 1
+ endwhile
+ return ""
+endfunction
+
+function! s:CaptionEnv()
+ let i = v:foldend
+ while i >= v:foldstart
+ if getline(i) =~ '^\s*\\caption'
+ return matchstr(getline(i), '^\s*\\caption\(\[.*\]\)\?{\zs.\+')
+ end
+ let i -= 1
+ endwhile
+ return ""
+endfunction
+
+function! s:CaptionTable()
+ let i = v:foldstart
+ while i <= v:foldend
+ if getline(i) =~ '^\s*\\caption'
+ return matchstr(getline(i), '^\s*\\caption\(\[.*\]\)\?{\zs.\+')
+ end
+ let i += 1
+ endwhile
+ return ""
+endfunction
+
+function! s:CaptionFrame(line)
+ " Test simple variants first
+ let caption1 = matchstr(a:line,'\\begin\*\?{.*}{\zs.\+\ze}')
+ let caption2 = matchstr(a:line,'\\begin\*\?{.*}{\zs.\+')
+
+ if len(caption1) > 0
+ return caption1
+ elseif len(caption2) > 0
+ return caption2
+ else
+ let i = v:foldstart
+ while i <= v:foldend
+ if getline(i) =~ '^\s*\\frametitle'
+ return matchstr(getline(i),
+ \ '^\s*\\frametitle\(\[.*\]\)\?{\zs.\+')
+ end
+ let i += 1
+ endwhile
+
+ return ""
+ endif
+endfunction
+
+function! LatexBox_FoldText_title()
+ let line = getline(v:foldstart)
+ let title = 'Not defined'
+
+ " Preamble
+ if line =~ '\s*\\documentclass'
+ return "Preamble"
+ endif
+
+ " Parts, sections and fakesections
+ let sections = '\(\(sub\)*\(section\|paragraph\)\|part\|chapter\)'
+ let secpat1 = '^\s*\\' . sections . '\*\?\s*{'
+ let secpat2 = '^\s*\\' . sections . '\*\?\s*\['
+ if line =~ '\\frontmatter'
+ let title = "Frontmatter"
+ elseif line =~ '\\mainmatter'
+ let title = "Mainmatter"
+ elseif line =~ '\\backmatter'
+ let title = "Backmatter"
+ elseif line =~ '\\appendix'
+ let title = "Appendix"
+ elseif line =~ secpat1 . '.*}'
+ let title = matchstr(line, secpat1 . '\zs.\{-}\ze}')
+ elseif line =~ secpat1
+ let title = matchstr(line, secpat1 . '\zs.*')
+ elseif line =~ secpat2 . '.*\]'
+ let title = matchstr(line, secpat2 . '\zs.\{-}\ze\]')
+ elseif line =~ secpat2
+ let title = matchstr(line, secpat2 . '\zs.*')
+ elseif line =~ 'Fake' . sections . ':'
+ let title = matchstr(line,'Fake' . sections . ':\s*\zs.*')
+ elseif line =~ 'Fake' . sections
+ let title = matchstr(line, 'Fake' . sections)
+ endif
+
+ " Environments
+ if line =~ '\\begin'
+ " Capture environment name
+ let env = matchstr(line,'\\begin\*\?{\zs\w*\*\?\ze}')
+
+ " Set caption based on type of environment
+ if env == 'frame'
+ let label = ''
+ let caption = s:CaptionFrame(line)
+ elseif env == 'table'
+ let label = s:LabelEnv()
+ let caption = s:CaptionTable()
+ else
+ let label = s:LabelEnv()
+ let caption = s:CaptionEnv()
+ endif
+
+ " If no caption found, check for a caption comment
+ if caption == ''
+ let caption = matchstr(line,'\\begin\*\?{.*}\s*%\s*\zs.*')
+ endif
+
+ " Create title based on caption and label
+ if caption . label == ''
+ let title = env
+ elseif label == ''
+ let title = printf('%-12s%s', env . ':',
+ \ substitute(caption, '}\s*$', '',''))
+ elseif caption == ''
+ let title = printf('%-12s%56s', env, '(' . label . ')')
+ else
+ let title = printf('%-12s%-30s %21s', env . ':',
+ \ strpart(substitute(caption, '}\s*$', '',''),0,34),
+ \ '(' . label . ')')
+ endif
+ endif
+
+ return title
+endfunction
+
+" {{{1 LatexBox_FoldText
+function! LatexBox_FoldText()
+ let nlines = v:foldend - v:foldstart + 1
+ let title = strpart(LatexBox_FoldText_title(), 0, 68)
+ let level = ''
+
+ " Fold level
+ let level = strpart(repeat('-', v:foldlevel-1) . '*',0,3)
+ if v:foldlevel > 3
+ let level = strpart(level, 1) . v:foldlevel
+ endif
+ let level = printf('%-3s', level)
+
+ return printf('%-3s %-68s #%5d', level, title, nlines)
+endfunction
+
+" {{{1 Footer
+" vim:fdm=marker:ff=unix:ts=4:sw=4
+
+endif
diff --git a/ftplugin/latex-box/latexmk.vim b/ftplugin/latex-box/latexmk.vim
new file mode 100644
index 00000000..15db3686
--- /dev/null
+++ b/ftplugin/latex-box/latexmk.vim
@@ -0,0 +1,558 @@
+if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'latex') == -1
+
+" LaTeX Box latexmk functions
+
+" Options and variables {{{
+
+if !exists('g:LatexBox_latexmk_options')
+ let g:LatexBox_latexmk_options = ''
+endif
+if !exists('g:LatexBox_latexmk_env')
+ let g:LatexBox_latexmk_env = ''
+endif
+if !exists('g:LatexBox_latexmk_async')
+ let g:LatexBox_latexmk_async = 0
+endif
+if !exists('g:LatexBox_latexmk_preview_continuously')
+ let g:LatexBox_latexmk_preview_continuously = 0
+endif
+if !exists('g:LatexBox_output_type')
+ let g:LatexBox_output_type = 'pdf'
+endif
+if !exists('g:LatexBox_autojump')
+ let g:LatexBox_autojump = 0
+endif
+if ! exists('g:LatexBox_quickfix')
+ let g:LatexBox_quickfix = 1
+endif
+if ! exists('g:LatexBox_personal_latexmkrc')
+ let g:LatexBox_personal_latexmkrc = 0
+endif
+
+" }}}
+
+" Process ID management (used for asynchronous and continuous mode) {{{
+
+" A dictionary of latexmk PID's (basename: pid)
+if !exists('g:latexmk_running_pids')
+ let g:latexmk_running_pids = {}
+endif
+
+" Set PID {{{
+function! s:LatexmkSetPID(basename, pid)
+ let g:latexmk_running_pids[a:basename] = a:pid
+endfunction
+" }}}
+
+" kill_latexmk_process {{{
+function! s:kill_latexmk_process(pid)
+ if has('win32')
+ silent execute '!taskkill /PID ' . a:pid . ' /T /F'
+ else
+ if g:LatexBox_latexmk_async
+ " vim-server mode
+ let pids = []
+ let tmpfile = tempname()
+ silent execute '!ps x -o pgid,pid > ' . tmpfile
+ for line in readfile(tmpfile)
+ let new_pid = matchstr(line, '^\s*' . a:pid . '\s\+\zs\d\+\ze')
+ if !empty(new_pid)
+ call add(pids, new_pid)
+ endif
+ endfor
+ call delete(tmpfile)
+ if !empty(pids)
+ silent execute '!kill ' . join(pids)
+ endif
+ else
+ " single background process
+ silent execute '!kill ' . a:pid
+ endif
+ endif
+ if !has('gui_running')
+ redraw!
+ endif
+endfunction
+" }}}
+
+" kill_all_latexmk_processes {{{
+function! s:kill_all_latexmk_processes()
+ for pid in values(g:latexmk_running_pids)
+ call s:kill_latexmk_process(pid)
+ endfor
+endfunction
+" }}}
+
+" }}}
+
+" Setup for vim-server {{{
+function! s:SIDWrap(func)
+ if !exists('s:SID')
+ let s:SID = matchstr(expand('<sfile>'), '\zs<SNR>\d\+_\ze.*$')
+ endif
+ return s:SID . a:func
+endfunction
+
+function! s:LatexmkCallback(basename, status)
+ " Only remove the pid if not in continuous mode
+ if !g:LatexBox_latexmk_preview_continuously
+ call remove(g:latexmk_running_pids, a:basename)
+ endif
+ call LatexBox_LatexErrors(a:status, a:basename)
+endfunction
+
+function! s:setup_vim_server()
+ if !exists('g:vim_program')
+
+ " attempt autodetection of vim executable
+ let g:vim_program = ''
+ if has('win32')
+ " Just drop through to the default for windows
+ else
+ if match(&shell, '\(bash\|zsh\)$') >= 0
+ let ppid = '$PPID'
+ else
+ let ppid = '$$'
+ endif
+
+ let tmpfile = tempname()
+ silent execute '!ps -o command= -p ' . ppid . ' > ' . tmpfile
+ for line in readfile(tmpfile)
+ let line = matchstr(line, '^\S\+\>')
+ if !empty(line) && executable(line)
+ let g:vim_program = line . ' -g'
+ break
+ endif
+ endfor
+ call delete(tmpfile)
+ endif
+
+ if empty(g:vim_program)
+ if has('gui_macvim')
+ let g:vim_program
+ \ = '/Applications/MacVim.app/Contents/MacOS/Vim -g'
+ else
+ let g:vim_program = v:progname
+ endif
+ endif
+ endif
+endfunction
+" }}}
+
+" Latexmk {{{
+
+function! LatexBox_Latexmk(force)
+ " Define often used names
+ let basepath = LatexBox_GetBuildBasename(1)
+ let basename = fnamemodify(basepath, ':t')
+ let texroot = shellescape(LatexBox_GetTexRoot())
+ let mainfile = fnameescape(fnamemodify(LatexBox_GetMainTexFile(), ':t'))
+
+ " Check if latexmk is installed
+ if !executable('latexmk')
+ echomsg "Error: LaTeX-Box relies on latexmk for compilation, but it" .
+ \ " is not installed!"
+ return
+ endif
+
+ " Check if already running
+ if has_key(g:latexmk_running_pids, basepath)
+ echomsg "latexmk is already running for `" . basename . "'"
+ return
+ endif
+
+ " Set wrap width in log file
+ let max_print_line = 2000
+ if has('win32')
+ let env = 'set max_print_line=' . max_print_line . ' & '
+ elseif match(&shell, '/tcsh$') >= 0
+ let env = 'setenv max_print_line ' . max_print_line . '; '
+ else
+ if fnamemodify(&shell, ':t') ==# 'fish'
+ let env = 'set max_print_line ' . max_print_line . '; and '
+ else
+ let env = 'max_print_line=' . max_print_line
+ endif
+ endif
+
+ " Set environment options
+ let env .= ' ' . g:LatexBox_latexmk_env . ' '
+
+ " Set latexmk command with options
+ if has('win32')
+ " Make sure to switch drive as well as directory
+ let cmd = 'cd /D ' . texroot . ' && '
+ else
+ if fnamemodify(&shell, ':t') ==# 'fish'
+ let cmd = 'cd ' . texroot . '; and '
+ else
+ let cmd = 'cd ' . texroot . ' && '
+ endif
+ endif
+ let cmd .= env . ' latexmk'
+ if ! g:LatexBox_personal_latexmkrc
+ let cmd .= ' -' . g:LatexBox_output_type
+ endif
+ let cmd .= ' -quiet '
+ let cmd .= g:LatexBox_latexmk_options
+ if a:force
+ let cmd .= ' -g'
+ endif
+ if g:LatexBox_latexmk_preview_continuously
+ let cmd .= ' -pvc'
+ endif
+ let cmd .= ' -e ' . shellescape('$pdflatex =~ s/ / -file-line-error /')
+ let cmd .= ' -e ' . shellescape('$latex =~ s/ / -file-line-error /')
+ if g:LatexBox_latexmk_preview_continuously
+ let cmd .= ' -e ' . shellescape('$success_cmd = $ENV{SUCCESSCMD}')
+ let cmd .= ' -e ' . shellescape('$failure_cmd = $ENV{FAILURECMD}')
+ endif
+ let cmd .= ' ' . mainfile
+
+ " Redirect output to null
+ if has('win32')
+ let cmd .= ' >nul'
+ else
+ if fnamemodify(&shell, ':t') ==# 'fish'
+ let cmd .= ' >/dev/null ^/dev/null'
+ else
+ let cmd .= ' &>/dev/null'
+ endif
+ endif
+
+ if g:LatexBox_latexmk_async
+ " Check if VIM server exists
+ if empty(v:servername)
+ echoerr "cannot run latexmk in background without a VIM server"
+ echoerr "set g:LatexBox_latexmk_async to 0 to change compiling mode"
+ return
+ endif
+
+ " Start vim server if necessary
+ call s:setup_vim_server()
+
+ let setpidfunc = s:SIDWrap('LatexmkSetPID')
+ let callbackfunc = s:SIDWrap('LatexmkCallback')
+ if has('win32')
+ let vim_program = substitute(g:vim_program,
+ \ 'gvim\.exe$', 'vim.exe', '')
+
+ " Define callback to set the pid
+ let callsetpid = setpidfunc . '(''' . basepath . ''', %CMDPID%)'
+ let vimsetpid = vim_program . ' --servername ' . v:servername
+ \ . ' --remote-expr ' . shellescape(callsetpid)
+
+ " Define callback after latexmk is finished
+ let callback = callbackfunc . '(''' . basepath . ''', %LATEXERR%)'
+ let vimcmd = vim_program . ' --servername ' . v:servername
+ \ . ' --remote-expr ' . shellescape(callback)
+ let scallback = callbackfunc . '(''' . basepath . ''', 0)'
+ let svimcmd = vim_program . ' --servername ' . v:servername
+ \ . ' --remote-expr ' . shellescape(scallback)
+ let fcallback = callbackfunc . '(''' . basepath . ''', 1)'
+ let fvimcmd = vim_program . ' --servername ' . v:servername
+ \ . ' --remote-expr ' . shellescape(fcallback)
+
+ let asyncbat = tempname() . '.bat'
+ if g:LatexBox_latexmk_preview_continuously
+ call writefile(['setlocal',
+ \ 'set T=%TEMP%\sthUnique.tmp',
+ \ 'wmic process where (Name="WMIC.exe" AND CommandLine LIKE "%%%TIME%%%") '
+ \ . 'get ParentProcessId /value | find "ParentProcessId" >%T%',
+ \ 'set /P A=<%T%',
+ \ 'set CMDPID=%A:~16% & del %T%',
+ \ vimsetpid,
+ \ 'set SUCCESSCMD='.svimcmd,
+ \ 'set FAILURECMD='.fvimcmd,
+ \ cmd,
+ \ 'endlocal'], asyncbat)
+ else
+ call writefile(['setlocal',
+ \ 'set T=%TEMP%\sthUnique.tmp',
+ \ 'wmic process where (Name="WMIC.exe" AND CommandLine LIKE "%%%TIME%%%") '
+ \ . 'get ParentProcessId /value | find "ParentProcessId" >%T%',
+ \ 'set /P A=<%T%',
+ \ 'set CMDPID=%A:~16% & del %T%',
+ \ vimsetpid,
+ \ cmd,
+ \ 'set LATEXERR=%ERRORLEVEL%',
+ \ vimcmd,
+ \ 'endlocal'], asyncbat)
+ endif
+
+ " Define command
+ let cmd = '!start /b ' . asyncbat . ' & del ' . asyncbat
+ else
+ " Define callback to set the pid
+ let callsetpid = shellescape(setpidfunc).'"(\"'.basepath.'\",$$)"'
+ let vimsetpid = g:vim_program . ' --servername ' . v:servername
+ \ . ' --remote-expr ' . callsetpid
+
+ " Define callback after latexmk is finished
+ let callback = shellescape(callbackfunc).'"(\"'.basepath.'\",$?)"'
+ let vimcmd = g:vim_program . ' --servername ' . v:servername
+ \ . ' --remote-expr ' . callback
+ let scallback = shellescape(callbackfunc).'"(\"'.basepath.'\",0)"'
+ let svimcmd = g:vim_program . ' --servername ' . v:servername
+ \ . ' --remote-expr ' . scallback
+ let fcallback = shellescape(callbackfunc).'"(\"'.basepath.'\",1)"'
+ let fvimcmd = g:vim_program . ' --servername ' . v:servername
+ \ . ' --remote-expr ' . fcallback
+
+ " Define command
+ " Note: Here we escape '%' because it may be given as a user option
+ " through g:LatexBox_latexmk_options, for instance with
+ " g:Latex..._options = "-pdflatex='pdflatex -synctex=1 \%O \%S'"
+ if g:LatexBox_latexmk_preview_continuously
+ let cmd = vimsetpid . ' ; '
+ \ . 'export SUCCESSCMD=' . shellescape(svimcmd) . ' '
+ \ . ' FAILURECMD=' . shellescape(fvimcmd) . ' ; '
+ \ . escape(cmd, '%')
+ else
+ let cmd = vimsetpid . ' ; ' . escape(cmd, '%') . ' ; ' . vimcmd
+ endif
+ let cmd = '! (' . cmd . ') >/dev/null &'
+ endif
+
+ if g:LatexBox_latexmk_preview_continuously
+ echo 'Compiling to ' . g:LatexBox_output_type
+ \ . ' with continuous preview.'
+ else
+ echo 'Compiling to ' . g:LatexBox_output_type . ' ...'
+ endif
+ silent execute cmd
+ else
+ if g:LatexBox_latexmk_preview_continuously
+ if has('win32')
+ let cmd = '!start /b cmd /s /c "' . cmd . '"'
+ else
+ let cmd = '!' . cmd . ' &'
+ endif
+ echo 'Compiling to ' . g:LatexBox_output_type . ' ...'
+ silent execute cmd
+
+ " Save PID in order to be able to kill the process when wanted.
+ if has('win32')
+ let tmpfile = tempname()
+ let pidcmd = 'cmd /c "wmic process where '
+ \ . '(CommandLine LIKE "latexmk\%'.mainfile.'\%") '
+ \ . 'get ProcessId /value | find "ProcessId" '
+ \ . '>'.tmpfile.' "'
+ silent execute '! ' . pidcmd
+ let pids = readfile(tmpfile)
+ let pid = strpart(pids[0], 10)
+ let g:latexmk_running_pids[basepath] = pid
+ else
+ let pid = substitute(system('pgrep -f "perl.*'
+ \ . mainfile . '" | head -n 1'),'\D','','')
+ let g:latexmk_running_pids[basepath] = pid
+ endif
+ else
+ " Execute command and check for errors
+ echo 'Compiling to ' . g:LatexBox_output_type . ' ... (async off!)'
+ call system(cmd)
+ call LatexBox_LatexErrors(v:shell_error)
+ endif
+ endif
+
+ " Redraw screen if necessary
+ if !has("gui_running")
+ redraw!
+ endif
+endfunction
+" }}}
+
+" LatexmkClean {{{
+function! LatexBox_LatexmkClean(cleanall)
+ " Check if latexmk is installed
+ if !executable('latexmk')
+ echomsg "Error: LaTeX-Box relies on latexmk for compilation, but it" .
+ \ " is not installed!"
+ return
+ endif
+
+ let basename = LatexBox_GetBuildBasename(1)
+
+ if has_key(g:latexmk_running_pids, basename)
+ echomsg "don't clean when latexmk is running"
+ return
+ endif
+
+ if has('win32')
+ let cmd = 'cd /D ' . shellescape(LatexBox_GetTexRoot()) . ' & '
+ else
+ let cmd = 'cd ' . shellescape(LatexBox_GetTexRoot()) . ';'
+ endif
+ if a:cleanall
+ let cmd .= 'latexmk -C '
+ else
+ let cmd .= 'latexmk -c '
+ endif
+ let cmd .= shellescape(LatexBox_GetMainTexFile())
+ if has('win32')
+ let cmd .= ' >nul'
+ else
+ let cmd .= ' >&/dev/null'
+ endif
+
+ call system(cmd)
+ if !has('gui_running')
+ redraw!
+ endif
+
+ echomsg "latexmk clean finished"
+endfunction
+" }}}
+
+" LatexErrors {{{
+function! LatexBox_LatexErrors(status, ...)
+ if a:0 >= 1
+ let log = a:1 . '.log'
+ else
+ let log = LatexBox_GetLogFile()
+ endif
+
+ cclose
+
+ " set cwd to expand error file correctly
+ let l:cwd = fnamemodify(getcwd(), ':p')
+ execute 'lcd ' . fnameescape(LatexBox_GetTexRoot())
+ try
+ if g:LatexBox_autojump
+ execute 'cfile ' . fnameescape(log)
+ else
+ execute 'cgetfile ' . fnameescape(log)
+ endif
+ finally
+ " restore cwd
+ execute 'lcd ' . fnameescape(l:cwd)
+ endtry
+
+ " Always open window if started by LatexErrors command
+ if a:status < 0
+ botright copen
+ else
+ " Only open window when an error/warning is detected
+ if g:LatexBox_quickfix >= 3
+ \ ? s:log_contains_error(log)
+ \ : g:LatexBox_quickfix > 0
+ belowright cw
+ if g:LatexBox_quickfix == 2 || g:LatexBox_quickfix == 4
+ wincmd p
+ endif
+ endif
+ redraw
+
+ " Write status message to screen
+ if a:status > 0 || len(getqflist())>1
+ if s:log_contains_error(log)
+ let l:status_msg = ' ... failed!'
+ else
+ let l:status_msg = ' ... there were warnings!'
+ endif
+ else
+ let l:status_msg = ' ... success!'
+ endif
+ echomsg 'Compiling to ' . g:LatexBox_output_type . l:status_msg
+ endif
+endfunction
+
+" Redefine uniq() for compatibility with older Vim versions (< 7.4.218)
+function! s:uniq(list)
+ if exists('*uniq')
+ return uniq(a:list)
+ elseif len(a:list) <= 1
+ return a:list
+ endif
+
+ let last_element = get(a:list,0)
+ let uniq_list = [last_element]
+
+ for i in range(1, len(a:list)-1)
+ let next_element = get(a:list, i)
+ if last_element == next_element
+ continue
+ endif
+ let last_element = next_element
+ call add(uniq_list, next_element)
+ endfor
+ return uniq_list
+endfunction
+
+function! s:log_contains_error(file)
+ let lines = readfile(a:file)
+ let lines = filter(lines, 'v:val =~ ''^.*:\d\+: ''')
+ let lines = s:uniq(map(lines, 'matchstr(v:val, ''^.*\ze:\d\+:'')'))
+ let lines = filter(lines, 'filereadable(fnameescape(v:val))')
+ return len(lines) > 0
+endfunction
+" }}}
+
+" LatexmkStatus {{{
+function! LatexBox_LatexmkStatus(detailed)
+ if a:detailed
+ if empty(g:latexmk_running_pids)
+ echo "latexmk is not running"
+ else
+ let plist = ""
+ for [basename, pid] in items(g:latexmk_running_pids)
+ if !empty(plist)
+ let plist .= '; '
+ endif
+ let plist .= fnamemodify(basename, ':t') . ':' . pid
+ endfor
+ echo "latexmk is running (" . plist . ")"
+ endif
+ else
+ let basename = LatexBox_GetBuildBasename(1)
+ if has_key(g:latexmk_running_pids, basename)
+ echo "latexmk is running"
+ else
+ echo "latexmk is not running"
+ endif
+ endif
+endfunction
+" }}}
+
+" LatexmkStop {{{
+function! LatexBox_LatexmkStop(silent)
+ if empty(g:latexmk_running_pids)
+ if !a:silent
+ let basepath = LatexBox_GetBuildBasename(1)
+ let basename = fnamemodify(basepath, ':t')
+ echoerr "latexmk is not running for `" . basename . "'"
+ endif
+ else
+ let basepath = LatexBox_GetBuildBasename(1)
+ let basename = fnamemodify(basepath, ':t')
+ if has_key(g:latexmk_running_pids, basepath)
+ call s:kill_latexmk_process(g:latexmk_running_pids[basepath])
+ call remove(g:latexmk_running_pids, basepath)
+ if !a:silent
+ echomsg "latexmk stopped for `" . basename . "'"
+ endif
+ elseif !a:silent
+ echoerr "latexmk is not running for `" . basename . "'"
+ endif
+ endif
+endfunction
+" }}}
+
+" Commands {{{
+
+command! -bang Latexmk call LatexBox_Latexmk(<q-bang> == "!")
+command! -bang LatexmkClean call LatexBox_LatexmkClean(<q-bang> == "!")
+command! -bang LatexmkStatus call LatexBox_LatexmkStatus(<q-bang> == "!")
+command! LatexmkStop call LatexBox_LatexmkStop(0)
+command! LatexErrors call LatexBox_LatexErrors(-1)
+
+if g:LatexBox_latexmk_async || g:LatexBox_latexmk_preview_continuously
+ autocmd BufUnload <buffer> call LatexBox_LatexmkStop(1)
+ autocmd VimLeave * call <SID>kill_all_latexmk_processes()
+endif
+
+" }}}
+
+" vim:fdm=marker:ff=unix:noet:ts=4:sw=4
+
+endif
diff --git a/ftplugin/latex-box/mappings.vim b/ftplugin/latex-box/mappings.vim
new file mode 100644
index 00000000..7141635e
--- /dev/null
+++ b/ftplugin/latex-box/mappings.vim
@@ -0,0 +1,110 @@
+if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'latex') == -1
+
+" LaTeX Box mappings
+
+if exists("g:LatexBox_no_mappings")
+ finish
+endif
+
+" latexmk {{{
+noremap <buffer> <LocalLeader>ll :Latexmk<CR>
+noremap <buffer> <LocalLeader>lL :Latexmk!<CR>
+noremap <buffer> <LocalLeader>lc :LatexmkClean<CR>
+noremap <buffer> <LocalLeader>lC :LatexmkClean!<CR>
+noremap <buffer> <LocalLeader>lg :LatexmkStatus<CR>
+noremap <buffer> <LocalLeader>lG :LatexmkStatus!<CR>
+noremap <buffer> <LocalLeader>lk :LatexmkStop<CR>
+noremap <buffer> <LocalLeader>le :LatexErrors<CR>
+" }}}
+
+" View {{{
+noremap <buffer> <LocalLeader>lv :LatexView<CR>
+" }}}
+
+" TOC {{{
+noremap <silent> <buffer> <LocalLeader>lt :LatexTOC<CR>
+" }}}
+
+" List of labels {{{
+noremap <silent> <buffer> <LocalLeader>lj :LatexLabels<CR>
+" }}}
+
+" Folding {{{
+if g:LatexBox_Folding == 1
+ noremap <buffer> <LocalLeader>lf :LatexFold<CR>
+endif
+" }}}
+
+" Jump to match {{{
+if !exists('g:LatexBox_loaded_matchparen')
+ nmap <buffer> % <Plug>LatexBox_JumpToMatch
+ vmap <buffer> % <Plug>LatexBox_JumpToMatch
+ omap <buffer> % <Plug>LatexBox_JumpToMatch
+endif
+" }}}
+
+" Define text objects {{{
+vmap <buffer> ie <Plug>LatexBox_SelectCurrentEnvInner
+vmap <buffer> ae <Plug>LatexBox_SelectCurrentEnvOuter
+onoremap <buffer> ie :normal vie<CR>
+onoremap <buffer> ae :normal vae<CR>
+vmap <buffer> i$ <Plug>LatexBox_SelectInlineMathInner
+vmap <buffer> a$ <Plug>LatexBox_SelectInlineMathOuter
+onoremap <buffer> i$ :normal vi$<CR>
+onoremap <buffer> a$ :normal va$<CR>
+" }}}
+
+" Jump between sections {{{
+function! s:LatexBoxNextSection(type, backwards, visual)
+ " Restore visual mode if desired
+ if a:visual
+ normal! gv
+ endif
+
+ " For the [] and ][ commands we move up or down before the search
+ if a:type == 1
+ if a:backwards
+ normal! k
+ else
+ normal! j
+ endif
+ endif
+
+ " Define search pattern and do the search while preserving "/
+ let save_search = @/
+ let flags = 'W'
+ if a:backwards
+ let flags = 'b' . flags
+ endif
+ let notcomment = '\%(\%(\\\@<!\%(\\\\\)*\)\@<=%.*\)\@<!'
+ let pattern = notcomment . '\v\s*\\(' . join([
+ \ '(sub)*section',
+ \ 'chapter',
+ \ 'part',
+ \ 'appendix',
+ \ '(front|back|main)matter'], '|') . ')>'
+ call search(pattern, flags)
+ let @/ = save_search
+
+ " For the [] and ][ commands we move down or up after the search
+ if a:type == 1
+ if a:backwards
+ normal! j
+ else
+ normal! k
+ endif
+ endif
+endfunction
+noremap <buffer> <silent> ]] :call <SID>LatexBoxNextSection(0,0,0)<CR>
+noremap <buffer> <silent> ][ :call <SID>LatexBoxNextSection(1,0,0)<CR>
+noremap <buffer> <silent> [] :call <SID>LatexBoxNextSection(1,1,0)<CR>
+noremap <buffer> <silent> [[ :call <SID>LatexBoxNextSection(0,1,0)<CR>
+vnoremap <buffer> <silent> ]] :<c-u>call <SID>LatexBoxNextSection(0,0,1)<CR>
+vnoremap <buffer> <silent> ][ :<c-u>call <SID>LatexBoxNextSection(1,0,1)<CR>
+vnoremap <buffer> <silent> [] :<c-u>call <SID>LatexBoxNextSection(1,1,1)<CR>
+vnoremap <buffer> <silent> [[ :<c-u>call <SID>LatexBoxNextSection(0,1,1)<CR>
+" }}}
+
+" vim:fdm=marker:ff=unix:noet:ts=4:sw=4
+
+endif
diff --git a/ftplugin/latex-box/motion.vim b/ftplugin/latex-box/motion.vim
new file mode 100644
index 00000000..2053149c
--- /dev/null
+++ b/ftplugin/latex-box/motion.vim
@@ -0,0 +1,548 @@
+if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'latex') == -1
+
+" LaTeX Box motion functions
+
+" Motion options {{{
+" Opening and closing patterns
+if !exists('g:LatexBox_open_pats')
+ let g:LatexBox_open_pats = [ '\\{','{','\\(','(','\\\[','\[',
+ \ '\\begin\s*{.\{-}}', '\\left\s*\%([^\\]\|\\.\|\\\a*\)']
+ let g:LatexBox_close_pats = [ '\\}','}','\\)',')','\\\]','\]',
+ \ '\\end\s*{.\{-}}', '\\right\s*\%([^\\]\|\\.\|\\\a*\)']
+endif
+" }}}
+
+" HasSyntax {{{
+" s:HasSyntax(syntaxName, [line], [col])
+function! s:HasSyntax(syntaxName, ...)
+ let line = a:0 >= 1 ? a:1 : line('.')
+ let col = a:0 >= 2 ? a:2 : col('.')
+ return index(map(synstack(line, col),
+ \ 'synIDattr(v:val, "name") == "' . a:syntaxName . '"'),
+ \ 1) >= 0
+endfunction
+" }}}
+
+" Search and Skip Comments {{{
+" s:SearchAndSkipComments(pattern, [flags], [stopline])
+function! s:SearchAndSkipComments(pat, ...)
+ let flags = a:0 >= 1 ? a:1 : ''
+ let stopline = a:0 >= 2 ? a:2 : 0
+ let saved_pos = getpos('.')
+
+ " search once
+ let ret = search(a:pat, flags, stopline)
+
+ if ret
+ " do not match at current position if inside comment
+ let flags = substitute(flags, 'c', '', 'g')
+
+ " keep searching while in comment
+ while LatexBox_InComment()
+ let ret = search(a:pat, flags, stopline)
+ if !ret
+ break
+ endif
+ endwhile
+ endif
+
+ if !ret
+ " if no match found, restore position
+ call setpos('.', saved_pos)
+ endif
+
+ return ret
+endfunction
+" }}}
+
+" Finding Matching Pair {{{
+function! s:FindMatchingPair(mode)
+
+ if a:mode =~ 'h\|i'
+ 2match none
+ elseif a:mode == 'v'
+ normal! gv
+ endif
+
+ if LatexBox_InComment() | return | endif
+
+ " open/close pairs (dollars signs are treated apart)
+ let dollar_pat = '\$'
+ let notbslash = '\%(\\\@<!\%(\\\\\)*\)\@<='
+ let notcomment = '\%(\%(\\\@<!\%(\\\\\)*\)\@<=%.*\)\@<!'
+ let anymatch = '\('
+ \ . join(g:LatexBox_open_pats + g:LatexBox_close_pats, '\|')
+ \ . '\|' . dollar_pat . '\)'
+
+ let lnum = line('.')
+ let cnum = searchpos('\A', 'cbnW', lnum)[1]
+ " if the previous char is a backslash
+ if strpart(getline(lnum), cnum-2, 1) == '\'
+ let cnum = cnum-1
+ endif
+ let delim = matchstr(getline(lnum), '\C^'. anymatch , cnum - 1)
+
+ if empty(delim) || strlen(delim)+cnum-1< col('.')
+ if a:mode =~ 'n\|v\|o'
+ " if not found, search forward
+ let cnum = match(getline(lnum), '\C'. anymatch , col('.') - 1) + 1
+ if cnum == 0 | return | endif
+ call cursor(lnum, cnum)
+ let delim = matchstr(getline(lnum), '\C^'. anymatch , cnum - 1)
+ elseif a:mode =~ 'i'
+ " if not found, move one char bacward and search
+ let cnum = searchpos('\A', 'bnW', lnum)[1]
+ " if the previous char is a backslash
+ if strpart(getline(lnum), cnum-2, 1) == '\'
+ let cnum = cnum-1
+ endif
+ let delim = matchstr(getline(lnum), '\C^'. anymatch , cnum - 1)
+ if empty(delim) || strlen(delim)+cnum< col('.') | return | endif
+ elseif a:mode =~ 'h'
+ return
+ endif
+ endif
+
+ if delim =~ '^\$'
+
+ " match $-pairs
+ " check if next character is in inline math
+ let [lnum0, cnum0] = searchpos('.', 'nW')
+ if lnum0 && s:HasSyntax('texMathZoneX', lnum0, cnum0)
+ let [lnum2, cnum2] = searchpos(notcomment . notbslash. dollar_pat, 'nW', line('w$')*(a:mode =~ 'h\|i') , 200)
+ else
+ let [lnum2, cnum2] = searchpos('\%(\%'. lnum . 'l\%' . cnum . 'c\)\@!'. notcomment . notbslash . dollar_pat, 'bnW', line('w0')*(a:mode =~ 'h\|i') , 200)
+ endif
+
+ if a:mode =~ 'h\|i'
+ execute '2match MatchParen /\%(\%' . lnum . 'l\%' . cnum . 'c\$' . '\|\%' . lnum2 . 'l\%' . cnum2 . 'c\$\)/'
+ elseif a:mode =~ 'n\|v\|o'
+ call cursor(lnum2,cnum2)
+ endif
+
+ else
+ " match other pairs
+ for i in range(len(g:LatexBox_open_pats))
+ let open_pat = notbslash . g:LatexBox_open_pats[i]
+ let close_pat = notbslash . g:LatexBox_close_pats[i]
+
+ if delim =~# '^' . open_pat
+ " if on opening pattern, search for closing pattern
+ let [lnum2, cnum2] = searchpairpos('\C' . open_pat, '', '\C'
+ \ . close_pat, 'nW', 'LatexBox_InComment()',
+ \ line('w$')*(a:mode =~ 'h\|i') , 200)
+ if a:mode =~ 'h\|i'
+ execute '2match MatchParen /\%(\%' . lnum . 'l\%' . cnum
+ \ . 'c' . g:LatexBox_open_pats[i] . '\|\%'
+ \ . lnum2 . 'l\%' . cnum2 . 'c'
+ \ . g:LatexBox_close_pats[i] . '\)/'
+ elseif a:mode =~ 'n\|v\|o'
+ call cursor(lnum2,cnum2)
+ if strlen(close_pat)>1 && a:mode =~ 'o'
+ call cursor(lnum2, matchend(getline('.'), '\C'
+ \ . close_pat, col('.')-1))
+ endif
+ endif
+ break
+ elseif delim =~# '^' . close_pat
+ " if on closing pattern, search for opening pattern
+ let [lnum2, cnum2] = searchpairpos('\C' . open_pat, '',
+ \ '\C\%(\%'. lnum . 'l\%' . cnum . 'c\)\@!'
+ \ . close_pat, 'bnW', 'LatexBox_InComment()',
+ \ line('w0')*(a:mode =~ 'h\|i') , 200)
+ if a:mode =~ 'h\|i'
+ execute '2match MatchParen /\%(\%' . lnum2 . 'l\%' . cnum2
+ \ . 'c' . g:LatexBox_open_pats[i] . '\|\%'
+ \ . lnum . 'l\%' . cnum . 'c'
+ \ . g:LatexBox_close_pats[i] . '\)/'
+ elseif a:mode =~ 'n\|v\|o'
+ call cursor(lnum2,cnum2)
+ endif
+ break
+ endif
+ endfor
+
+ endif
+endfunction
+
+" Allow to disable functionality if desired
+if !exists('g:LatexBox_loaded_matchparen')
+ " Disable matchparen autocommands
+ augroup LatexBox_HighlightPairs
+ autocmd BufEnter * if !exists("g:loaded_matchparen") || !g:loaded_matchparen | runtime plugin/matchparen.vim | endif
+ autocmd BufEnter *.tex 3match none | unlet! g:loaded_matchparen | au! matchparen
+ autocmd! CursorMoved *.tex call s:FindMatchingPair('h')
+ autocmd! CursorMovedI *.tex call s:FindMatchingPair('i')
+ augroup END
+endif
+
+" Use LatexBox'es FindMatchingPair as '%' (enable jump between e.g. $'s)
+nnoremap <silent> <Plug>LatexBox_JumpToMatch :call <SID>FindMatchingPair('n')<CR>
+vnoremap <silent> <Plug>LatexBox_JumpToMatch :call <SID>FindMatchingPair('v')<CR>
+onoremap <silent> <Plug>LatexBox_JumpToMatch v:call <SID>FindMatchingPair('o')<CR>
+
+" }}}
+
+" select inline math {{{
+" s:SelectInlineMath(seltype)
+" where seltype is either 'inner' or 'outer'
+function! s:SelectInlineMath(seltype)
+
+ let dollar_pat = '\\\@<!\$'
+
+ if s:HasSyntax('texMathZoneX')
+ call s:SearchAndSkipComments(dollar_pat, 'cbW')
+ elseif getline('.')[col('.') - 1] == '$'
+ call s:SearchAndSkipComments(dollar_pat, 'bW')
+ else
+ return
+ endif
+
+ if a:seltype == 'inner'
+ normal! l
+ endif
+
+ if visualmode() ==# 'V'
+ normal! V
+ else
+ normal! v
+ endif
+
+ call s:SearchAndSkipComments(dollar_pat, 'W')
+
+ if a:seltype == 'inner'
+ normal! h
+ endif
+endfunction
+
+vnoremap <silent> <Plug>LatexBox_SelectInlineMathInner
+ \ :<C-U>call <SID>SelectInlineMath('inner')<CR>
+vnoremap <silent> <Plug>LatexBox_SelectInlineMathOuter
+ \ :<C-U>call <SID>SelectInlineMath('outer')<CR>
+" }}}
+
+" select current environment {{{
+function! s:SelectCurrentEnv(seltype)
+ let [env, lnum, cnum, lnum2, cnum2] = LatexBox_GetCurrentEnvironment(1)
+ call cursor(lnum, cnum)
+ if a:seltype == 'inner'
+ if env =~ '^\'
+ call search('\\.\_\s*\S', 'eW')
+ else
+ call search('}\(\_\s*\[\_[^]]*\]\)\?\_\s*\S', 'eW')
+ endif
+ endif
+ if visualmode() ==# 'V'
+ normal! V
+ else
+ normal! v
+ endif
+ call cursor(lnum2, cnum2)
+ if a:seltype == 'inner'
+ call search('\S\_\s*', 'bW')
+ else
+ if env =~ '^\'
+ normal! l
+ else
+ call search('}', 'eW')
+ endif
+ endif
+endfunction
+vnoremap <silent> <Plug>LatexBox_SelectCurrentEnvInner :<C-U>call <SID>SelectCurrentEnv('inner')<CR>
+vnoremap <silent> <Plug>LatexBox_SelectCurrentEnvOuter :<C-U>call <SID>SelectCurrentEnv('outer')<CR>
+" }}}
+
+" Jump to the next braces {{{
+"
+function! LatexBox_JumpToNextBraces(backward)
+ let flags = ''
+ if a:backward
+ normal h
+ let flags .= 'b'
+ else
+ let flags .= 'c'
+ endif
+ if search('[][}{]', flags) > 0
+ normal l
+ endif
+ let prev = strpart(getline('.'), col('.') - 2, 1)
+ let next = strpart(getline('.'), col('.') - 1, 1)
+ if next =~ '[]}]' && prev !~ '[][{}]'
+ return "\<Right>"
+ else
+ return ''
+ endif
+endfunction
+" }}}
+
+" Table of Contents {{{
+
+" Special UTF-8 conversion
+function! s:ConvertBack(line)
+ let line = a:line
+ if exists('g:LatexBox_plaintext_toc')
+ "
+ " Substitute stuff like '\IeC{\"u}' to plain 'u'
+ "
+ let line = substitute(line, '\\IeC\s*{\\.\(.\)}', '\1', 'g')
+ else
+ "
+ " Substitute stuff like '\IeC{\"u}' to corresponding unicode symbols
+ "
+ for [pat, symbol] in s:ConvBackPats
+ let line = substitute(line, pat, symbol, 'g')
+ endfor
+ endif
+ return line
+endfunction
+
+function! s:ReadTOC(auxfile, texfile, ...)
+ let texfile = a:texfile
+ let prefix = fnamemodify(a:auxfile, ':p:h')
+
+ if a:0 != 2
+ let toc = []
+ let fileindices = { texfile : [] }
+ else
+ let toc = a:1
+ let fileindices = a:2
+ let fileindices[ texfile ] = []
+ endif
+
+ for line in readfile(a:auxfile)
+ let included = matchstr(line, '^\\@input{\zs[^}]*\ze}')
+ if included != ''
+ " append the input TOX to `toc` and `fileindices`
+ let newaux = prefix . '/' . included
+ let newtex = fnamemodify(newaux, ':r') . '.tex'
+ call s:ReadTOC(newaux, newtex, toc, fileindices)
+ continue
+ endif
+
+ " Parse statements like:
+ " \@writefile{toc}{\contentsline {section}{\numberline {secnum}Section Title}{pagenumber}}
+ " \@writefile{toc}{\contentsline {section}{\tocsection {}{1}{Section Title}}{pagenumber}}
+ " \@writefile{toc}{\contentsline {section}{\numberline {secnum}Section Title}{pagenumber}{otherstuff}}
+
+ let line = matchstr(line,
+ \ '\\@writefile{toc}{\\contentsline\s*\zs.*\ze}\s*$')
+ if empty(line)
+ continue
+ endif
+
+ let tree = LatexBox_TexToTree(s:ConvertBack(line))
+
+ if len(tree) < 3
+ " unknown entry type: just skip it
+ continue
+ endif
+
+ " parse level
+ let level = tree[0][0]
+ " parse page
+ if !empty(tree[2])
+ let page = tree[2][0]
+ else
+ let page = ''
+ endif
+ " parse section number
+ let secnum = ''
+ let tree = tree[1]
+ if len(tree) > 3 && empty(tree[1])
+ call remove(tree, 1)
+ endif
+ if len(tree) > 1 && type(tree[0]) == type("") && tree[0] =~ '^\\\(\(chapter\)\?numberline\|tocsection\)'
+ let secnum = LatexBox_TreeToTex(tree[1])
+ let secnum = substitute(secnum, '\\\S\+\s', '', 'g')
+ let secnum = substitute(secnum, '\\\S\+{\(.\{-}\)}', '\1', 'g')
+ let secnum = substitute(secnum, '^{\+\|}\+$', '', 'g')
+ call remove(tree, 1)
+ endif
+ " parse section title
+ let text = LatexBox_TreeToTex(tree)
+ let text = substitute(text, '^{\+\|}\+$', '', 'g')
+ let text = substitute(text, '\m^\\\(no\)\?\(chapter\)\?numberline\s*', '', '')
+ let text = substitute(text, '\*', '', 'g')
+
+ " add TOC entry
+ call add(fileindices[texfile], len(toc))
+ call add(toc, {'file': texfile,
+ \ 'level': level,
+ \ 'number': secnum,
+ \ 'text': text,
+ \ 'page': page})
+ endfor
+
+ return [toc, fileindices]
+
+endfunction
+
+function! LatexBox_TOC(...)
+
+ " Check if window already exists
+ let winnr = bufwinnr(bufnr('LaTeX TOC'))
+ " Two types of splits, horizontal and vertical
+ let l:hori = "new"
+ let l:vert = "vnew"
+
+ " Set General Vars and initialize size
+ let l:type = g:LatexBox_split_type
+ let l:size = 10
+
+ " Size detection
+ if l:type == l:hori
+ let l:size = g:LatexBox_split_length
+ elseif l:type == l:vert
+ let l:size = g:LatexBox_split_width
+ endif
+
+ if winnr >= 0
+ if a:0 == 0
+ silent execute winnr . 'wincmd w'
+ else
+ " Supplying an argument to this function causes toggling instead
+ " of jumping to the TOC window
+ if g:LatexBox_split_resize
+ silent exe "set columns-=" . l:size
+ endif
+ silent execute 'bwipeout' . bufnr('LaTeX TOC')
+ endif
+ return
+ endif
+ " Read TOC
+ let [toc, fileindices] = s:ReadTOC(LatexBox_GetAuxFile(),
+ \ LatexBox_GetMainTexFile())
+ let calling_buf = bufnr('%')
+
+ " Find closest section in current buffer
+ let closest_index = s:FindClosestSection(toc,fileindices)
+
+ " Create TOC window and set local settings
+ if g:LatexBox_split_resize
+ silent exe "set columns+=" . l:size
+ endif
+ silent exe g:LatexBox_split_side l:size . l:type . ' LaTeX\ TOC'
+
+ let b:toc = toc
+ let b:toc_numbers = 1
+ let b:calling_win = bufwinnr(calling_buf)
+ setlocal filetype=latextoc
+
+ " Add TOC entries and jump to the closest section
+ for entry in toc
+ call append('$', entry['number'] . "\t" . entry['text'])
+ endfor
+ if !g:LatexBox_toc_hidehelp
+ call append('$', "")
+ call append('$', "<Esc>/q: close")
+ call append('$', "<Space>: jump")
+ call append('$', "<Enter>: jump and close")
+ call append('$', "s: hide numbering")
+ endif
+ 0delete _
+
+ execute 'normal! ' . (closest_index + 1) . 'G'
+
+ " Lock buffer
+ setlocal nomodifiable
+endfunction
+
+" Binary search for the closest section
+" return the index of the TOC entry
+function! s:FindClosestSection(toc, fileindices)
+ let file = expand('%:p')
+ if !has_key(a:fileindices, file)
+ return 0
+ endif
+
+ let imax = len(a:fileindices[file])
+ if imax > 0
+ let imin = 0
+ while imin < imax - 1
+ let i = (imax + imin) / 2
+ let tocindex = a:fileindices[file][i]
+ let entry = a:toc[tocindex]
+ let titlestr = entry['text']
+ let titlestr = escape(titlestr, '\')
+ let titlestr = substitute(titlestr, ' ', '\\_\\s\\+', 'g')
+ let [lnum, cnum] = searchpos('\\' . entry['level'] . '\_\s*{' . titlestr . '}', 'nW')
+ if lnum
+ let imax = i
+ else
+ let imin = i
+ endif
+ endwhile
+ return a:fileindices[file][imin]
+ else
+ return 0
+ endif
+endfunction
+
+let s:ConvBackPats = map([
+ \ ['\\''A}' , 'Á'],
+ \ ['\\`A}' , 'À'],
+ \ ['\\^A}' , 'À'],
+ \ ['\\¨A}' , 'Ä'],
+ \ ['\\"A}' , 'Ä'],
+ \ ['\\''a}' , 'á'],
+ \ ['\\`a}' , 'à'],
+ \ ['\\^a}' , 'à'],
+ \ ['\\¨a}' , 'ä'],
+ \ ['\\"a}' , 'ä'],
+ \ ['\\''E}' , 'É'],
+ \ ['\\`E}' , 'È'],
+ \ ['\\^E}' , 'Ê'],
+ \ ['\\¨E}' , 'Ë'],
+ \ ['\\"E}' , 'Ë'],
+ \ ['\\''e}' , 'é'],
+ \ ['\\`e}' , 'è'],
+ \ ['\\^e}' , 'ê'],
+ \ ['\\¨e}' , 'ë'],
+ \ ['\\"e}' , 'ë'],
+ \ ['\\''I}' , 'Í'],
+ \ ['\\`I}' , 'Î'],
+ \ ['\\^I}' , 'Ì'],
+ \ ['\\¨I}' , 'Ï'],
+ \ ['\\"I}' , 'Ï'],
+ \ ['\\''i}' , 'í'],
+ \ ['\\`i}' , 'î'],
+ \ ['\\^i}' , 'ì'],
+ \ ['\\¨i}' , 'ï'],
+ \ ['\\"i}' , 'ï'],
+ \ ['\\''{\?\\i }' , 'í'],
+ \ ['\\''O}' , 'Ó'],
+ \ ['\\`O}' , 'Ò'],
+ \ ['\\^O}' , 'Ô'],
+ \ ['\\¨O}' , 'Ö'],
+ \ ['\\"O}' , 'Ö'],
+ \ ['\\''o}' , 'ó'],
+ \ ['\\`o}' , 'ò'],
+ \ ['\\^o}' , 'ô'],
+ \ ['\\¨o}' , 'ö'],
+ \ ['\\"o}' , 'ö'],
+ \ ['\\''U}' , 'Ú'],
+ \ ['\\`U}' , 'Ù'],
+ \ ['\\^U}' , 'Û'],
+ \ ['\\¨U}' , 'Ü'],
+ \ ['\\"U}' , 'Ü'],
+ \ ['\\''u}' , 'ú'],
+ \ ['\\`u}' , 'ù'],
+ \ ['\\^u}' , 'û'],
+ \ ['\\¨u}' , 'ü'],
+ \ ['\\"u}' , 'ü'],
+ \ ['\\`N}' , 'Ǹ'],
+ \ ['\\\~N}' , 'Ñ'],
+ \ ['\\''n}' , 'ń'],
+ \ ['\\`n}' , 'ǹ'],
+ \ ['\\\~n}' , 'ñ'],
+ \], '[''\C\(\\IeC\s*{\)\?'' . v:val[0], v:val[1]]')
+" }}}
+
+" TOC Command {{{
+command! LatexTOC call LatexBox_TOC()
+command! LatexTOCToggle call LatexBox_TOC(1)
+" }}}
+
+" vim:fdm=marker:ff=unix:noet:ts=4:sw=4
+
+endif
diff --git a/ftplugin/latextoc.vim b/ftplugin/latextoc.vim
new file mode 100644
index 00000000..bfb8658e
--- /dev/null
+++ b/ftplugin/latextoc.vim
@@ -0,0 +1,206 @@
+if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'latex') == -1
+
+" {{{1 Settings
+setlocal buftype=nofile
+setlocal bufhidden=wipe
+setlocal nobuflisted
+setlocal noswapfile
+setlocal nowrap
+setlocal nospell
+setlocal cursorline
+setlocal nonumber
+setlocal nolist
+setlocal tabstop=8
+setlocal cole=0
+setlocal cocu=nvic
+if g:LatexBox_fold_toc
+ setlocal foldmethod=expr
+ setlocal foldexpr=TOCFoldLevel(v:lnum)
+ setlocal foldtext=TOCFoldText()
+endif
+" }}}1
+
+" {{{1 Functions
+" {{{2 TOCClose
+function! s:TOCClose()
+ if g:LatexBox_split_resize
+ silent exe "set columns-=" . g:LatexBox_split_width
+ endif
+ bwipeout
+endfunction
+
+" {{{2 TOCToggleNumbers
+function! s:TOCToggleNumbers()
+ if b:toc_numbers
+ setlocal conceallevel=3
+ let b:toc_numbers = 0
+ else
+ setlocal conceallevel=0
+ let b:toc_numbers = 1
+ endif
+endfunction
+
+" {{{2 EscapeTitle
+function! s:EscapeTitle(titlestr)
+ let titlestr = substitute(a:titlestr, '\\[a-zA-Z@]*\>\s*{\?', '.*', 'g')
+ let titlestr = substitute(titlestr, '}', '', 'g')
+ let titlestr = substitute(titlestr, '\%(\.\*\s*\)\{2,}', '.*', 'g')
+ return titlestr
+endfunction
+
+" {{{2 TOCActivate
+function! s:TOCActivate(close)
+ let n = getpos('.')[1] - 1
+
+ if n >= len(b:toc)
+ return
+ endif
+
+ let entry = b:toc[n]
+
+ let titlestr = s:EscapeTitle(entry['text'])
+
+ " Search for duplicates
+ "
+ let i=0
+ let entry_hash = entry['level'].titlestr
+ let duplicates = 0
+ while i<n
+ let i_entry = b:toc[n]
+ let i_hash = b:toc[i]['level'].s:EscapeTitle(b:toc[i]['text'])
+ if i_hash == entry_hash
+ let duplicates += 1
+ endif
+ let i += 1
+ endwhile
+ let toc_bnr = bufnr('%')
+ let toc_wnr = winnr()
+
+ execute b:calling_win . 'wincmd w'
+
+ let root = fnamemodify(entry['file'], ':h') . '/'
+ let files = [entry['file']]
+ for line in filter(readfile(entry['file']), 'v:val =~ ''\\input{''')
+ let file = matchstr(line, '{\zs.\{-}\ze\(\.tex\)\?}') . '.tex'
+ if file[0] != '/'
+ let file = root . file
+ endif
+ call add(files, file)
+ endfor
+
+ " Find section in buffer (or inputted files)
+ if entry['level'] == 'label'
+ let re = '\(\\label\_\s*{\|label\s*=\s*\)' . titlestr . '\>'
+ else
+ let re = '\\' . entry['level'] . '\_\s*{' . titlestr . '}'
+ endif
+ call s:TOCFindMatch(re, duplicates, files)
+
+ if a:close
+ if g:LatexBox_split_resize
+ silent exe "set columns-=" . g:LatexBox_split_width
+ endif
+ execute 'bwipeout ' . toc_bnr
+ else
+ execute toc_wnr . 'wincmd w'
+ endif
+endfunction
+
+" {{{2 TOCFindMatch
+function! s:TOCFindMatch(strsearch,duplicates,files)
+ if len(a:files) == 0
+ echoerr "Could not find: " . a:strsearch
+ return
+ endif
+
+ call s:TOCOpenBuf(a:files[0])
+ let dups = a:duplicates
+
+ " Skip duplicates
+ while dups > 0
+ if search(a:strsearch, 'w')
+ let dups -= 1
+ else
+ break
+ endif
+ endwhile
+
+ if search(a:strsearch, 'w')
+ normal! zv
+ return
+ endif
+
+ call s:TOCFindMatch(a:strsearch,dups,a:files[1:])
+endfunction
+
+" {{{2 TOCFoldLevel
+function! TOCFoldLevel(lnum)
+ let line = getline(a:lnum)
+ let match_s1 = line =~# '^\w\+\s'
+ let match_s2 = line =~# '^\w\+\.\w\+\s'
+ let match_s3 = line =~# '^\w\+\.\w\+\.\w\+\s'
+
+ if g:LatexBox_fold_toc_levels >= 3
+ if match_s3
+ return ">3"
+ endif
+ endif
+
+ if g:LatexBox_fold_toc_levels >= 2
+ if match_s2
+ return ">2"
+ endif
+ endif
+
+ if match_s1
+ return ">1"
+ endif
+
+ " Don't fold options
+ if line =~# '^\s*$'
+ return 0
+ endif
+
+ " Return previous fold level
+ return "="
+endfunction
+
+" {{{2 TOCFoldText
+function! TOCFoldText()
+ let parts = matchlist(getline(v:foldstart), '^\(.*\)\t\(.*\)$')
+ return printf('%-8s%-72s', parts[1], parts[2])
+endfunction
+
+" {{{2 TOCOpenBuf
+function! s:TOCOpenBuf(file)
+
+ let bnr = bufnr(a:file)
+ if bnr == -1
+ execute 'badd ' . a:file
+ let bnr = bufnr(a:file)
+ endif
+ execute 'buffer! ' . bnr
+ normal! gg
+
+endfunction
+
+" }}}1
+
+" {{{1 Mappings
+nnoremap <buffer> <silent> s :call <SID>TOCToggleNumbers()<CR>
+nnoremap <buffer> <silent> q :call <SID>TOCClose()<CR>
+nnoremap <buffer> <silent> <Esc> :call <SID>TOCClose()<CR>
+nnoremap <buffer> <silent> <Space> :call <SID>TOCActivate(0)<CR>
+nnoremap <buffer> <silent> <CR> :call <SID>TOCActivate(1)<CR>
+nnoremap <buffer> <silent> <leftrelease> :call <SID>TOCActivate(0)<cr>
+nnoremap <buffer> <silent> <2-leftmouse> :call <SID>TOCActivate(1)<cr>
+nnoremap <buffer> <silent> G G4k
+nnoremap <buffer> <silent> <Esc>OA k
+nnoremap <buffer> <silent> <Esc>OB j
+nnoremap <buffer> <silent> <Esc>OC l
+nnoremap <buffer> <silent> <Esc>OD h
+" }}}1
+
+" vim:fdm=marker:ff=unix:et:ts=4:sw=4
+
+endif
diff --git a/ftplugin/tex_LatexBox.vim b/ftplugin/tex_LatexBox.vim
new file mode 100644
index 00000000..6c8899a6
--- /dev/null
+++ b/ftplugin/tex_LatexBox.vim
@@ -0,0 +1,37 @@
+if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'latex') == -1
+
+" LaTeX Box plugin for Vim
+" Maintainer: David Munger
+" Email: mungerd@gmail.com
+" Version: 0.9.6
+
+if exists('*fnameescape')
+ function! s:FNameEscape(s)
+ return fnameescape(a:s)
+ endfunction
+else
+ function! s:FNameEscape(s)
+ return a:s
+ endfunction
+endif
+
+if !exists('b:LatexBox_loaded')
+
+ let prefix = expand('<sfile>:p:h') . '/latex-box/'
+
+ execute 'source ' . s:FNameEscape(prefix . 'common.vim')
+ execute 'source ' . s:FNameEscape(prefix . 'complete.vim')
+ execute 'source ' . s:FNameEscape(prefix . 'motion.vim')
+ execute 'source ' . s:FNameEscape(prefix . 'latexmk.vim')
+ execute 'source ' . s:FNameEscape(prefix . 'folding.vim')
+ " added by AH to add main.tex file finder
+ execute 'source ' . s:FNameEscape(prefix . 'findmain.vim')
+ execute 'source ' . s:FNameEscape(prefix . 'mappings.vim')
+
+ let b:LatexBox_loaded = 1
+
+endif
+
+" vim:fdm=marker:ff=unix:noet:ts=4:sw=4
+
+endif
diff --git a/ftplugin/vue.vim b/ftplugin/vue.vim
index 14ad26a0..cc10c561 100644
--- a/ftplugin/vue.vim
+++ b/ftplugin/vue.vim
@@ -13,6 +13,13 @@ runtime! ftplugin/html.vim
setlocal suffixesadd+=.vue
+if !exists('g:no_plugin_maps') && !exists('g:no_vue_maps')
+ nnoremap <silent> <buffer> [[ :call search('^<\(template\<Bar>script\<Bar>style\)', 'bW')<CR>
+ nnoremap <silent> <buffer> ]] :call search('^<\(template\<Bar>script\<Bar>style\)', 'W')<CR>
+ nnoremap <silent> <buffer> [] :call search('^</\(template\<Bar>script\<Bar>style\)', 'bW')<CR>
+ nnoremap <silent> <buffer> ][ :call search('^</\(template\<Bar>script\<Bar>style\)', 'W')<CR>
+endif
+
if exists('g:loaded_ale')
let g:ale_linters = get(g:, 'ale_linters', {})
let g:ale_linters.vue = get(g:ale_linters, 'vue', ['eslint'])