summaryrefslogblamecommitdiffstats
path: root/ftplugin/latex-box/common.vim
blob: c5451027d1a947becf5403b61dcc843884616cf8 (plain) (tree)
1
2
3
4
5
6




                                                                      
                                              











                                                         

                                                             

                                    



                                           
 


                           

                           








                                                           






                                                                               
                                         



                                                              
                                         

     

                         
                         

                        




                     










                                                  



                                       
                     
                                   
                                               










































                                                                                             
                                                                                


                                    







                                                                                

                                                                


                                      
                                            






                                                    

                         







                                                                   









                                                                           




































































                                                                                       









                                                                            
             
                                        

     

                                     




                                                                       
                                                                               
                       
                                                      
            





                                                             






                              
                                                        






























































































































                                                                                               
" 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_GetTexBasename(with_dir)
	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_GetTexBasename(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_GetTexBasename(0) . '.aux'
	endif

	" 3. use the base name of main tex file
	return LatexBox_GetTexBasename(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_GetTexBasename(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_GetTexBasename(0) . '.log'
	endif

	" 3. use the base name of main tex file
	return LatexBox_GetTexBasename(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_GetTexBasename(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_GetTexBasename(0)
					\ . '.' . g:LatexBox_output_type
	endif

	" 3. use the base name of main tex file
	return LatexBox_GetTexBasename(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