summaryrefslogtreecommitdiffstats
path: root/indent/tex.vim
blob: 31abcd575e0a202f6d3506624aca0f8eed5e056e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
if exists('g:polyglot_disabled') && index(g:polyglot_disabled, 'latex') != -1
  finish
endif

" LaTeX indent file (part of LaTeX Box)
" Maintainer: David Munger (mungerd@gmail.com)

if exists("g:LatexBox_custom_indent") && ! g:LatexBox_custom_indent
	finish
endif
if exists("b:did_indent")
	finish
endif

let b:did_indent = 1

setlocal indentexpr=LatexBox_TexIndent()
setlocal indentkeys=0=\\end,0=\\end{enumerate},0=\\end{itemize},0=\\end{description},0=\\right,0=\\item,0=\\),0=\\],0},o,O,0\\

let s:list_envs = ['itemize', 'enumerate', 'description']
" indent on \left( and on \(, but not on (
" indent on \left[ and on \[, but not on [
" indent on \left\{ and on {, but not on \{
let s:open_pat = '\\\@<!\%(\\begin\|\\left\a\@!\|\\(\|\\\[\|{\)'
let s:close_pat = '\\\@<!\%(\\end\|\\right\a\@!\|\\)\|\\\]\|}\)'
let s:list_open_pat = '\\\@<!\\begin{\%(' . join(s:list_envs, '\|') . '\)}'
let s:list_close_pat	= '\\\@<!\\end{\%(' . join(s:list_envs, '\|') . '\)}'

function! s:CountMatches(str, pat)
	return len(substitute(substitute(a:str, a:pat, "\n", 'g'), "[^\n]", '', 'g'))
endfunction


" TexIndent {{{
function! LatexBox_TexIndent()

	let lnum_curr = v:lnum
	let lnum_prev = prevnonblank(lnum_curr - 1)

	if lnum_prev == 0
		return 0
	endif

	let line_curr = getline(lnum_curr)
	let line_prev = getline(lnum_prev)

	" remove \\
	let line_curr = substitute(line_curr, '\\\\', '', 'g')
	let line_prev = substitute(line_prev, '\\\\', '', 'g')

	" strip comments
	let line_curr = substitute(line_curr, '\\\@<!%.*$', '', 'g')
	let line_prev = substitute(line_prev, '\\\@<!%.*$', '', 'g')

	" find unmatched opening patterns on previous line
	let n = s:CountMatches(line_prev, s:open_pat)-s:CountMatches(line_prev, s:close_pat)
	let n += s:CountMatches(line_prev, s:list_open_pat)-s:CountMatches(line_prev, s:list_close_pat)

	" reduce indentation if current line starts with a closing pattern
	if line_curr =~ '^\s*\%(' . s:close_pat . '\)'
		let n -= 1
	endif

	" compensate indentation if previous line starts with a closing pattern
	if line_prev =~ '^\s*\%(' . s:close_pat . '\)'
		let n += 1
	endif

	" reduce indentation if current line starts with a closing list
	if line_curr =~ '^\s*\%(' . s:list_close_pat . '\)'
		let n -= 1
	endif

	" compensate indentation if previous line starts with a closing list
	if line_prev =~ '^\s*\%(' . s:list_close_pat . '\)'
		let n += 1
	endif

	" reduce indentation if previous line is \begin{document}
	if line_prev =~ '\\begin\s*{document}'
		let n -= 1
	endif

	" less shift for lines starting with \item
	let item_here =  line_curr =~ '^\s*\\item'
	let item_above = line_prev =~ '^\s*\\item'
	if !item_here && item_above
		let n += 1
	elseif item_here && !item_above
		let n -= 1
	endif

	return indent(lnum_prev) + n * &sw
endfunction
" }}}

" Restore cursor position, window position, and last search after running a
" command.
function! Latexbox_CallIndent()
  " Save the current cursor position.
  let cursor = getpos('.')

  " Save the current window position.
  normal! H
  let window = getpos('.')
  call setpos('.', cursor)

  " Get first non-whitespace character of current line.
  let line_start_char = matchstr(getline('.'), '\S')

  " Get initial tab position.
  let initial_tab = stridx(getline('.'), line_start_char)

  " Execute the command.
  execute 'normal! =='

  " Get tab position difference.
  let difference = stridx(getline('.'), line_start_char) - initial_tab

  " Set new cursor Y position based on calculated difference.
  let cursor[2] = cursor[2] + difference

  " Restore the previous window position.
  call setpos('.', window)
  normal! zt

  " Restore the previous cursor position.
  call setpos('.', cursor)
endfunction

" autocmd to call indent after completion
" 7.3.598
if v:version > 703 || (v:version == 703 && has('patch598'))
	augroup LatexBox_Completion
		autocmd!
		autocmd CompleteDone <buffer> call Latexbox_CallIndent()
	augroup END
endif

" vim:fdm=marker:ff=unix:noet:ts=4:sw=4