blob: 1a4d8b1cb688fadac356052078f4c790d7c977d8 [file] [log] [blame]
Bram Moolenaarf1568ec2011-12-14 21:17:39 +01001" Vim indent file
2" Language: LaTeX
Bram Moolenaarb4d6c3e2017-05-27 16:45:17 +02003" Maintainer: Yichao Zhou <broken.zhou AT gmail.com>
Bram Moolenaarf1568ec2011-12-14 21:17:39 +01004" Created: Sat, 16 Feb 2002 16:50:19 +0100
Bram Moolenaarb4d6c3e2017-05-27 16:45:17 +02005" Version: 0.9.4
Bram Moolenaar328da0d2016-03-04 22:22:32 +01006" Please email me if you found something I can do. Comments, bug report and
7" feature request are welcome.
Bram Moolenaar61d35bd2012-03-28 20:51:51 +02008
9" Last Update: {{{
10" 25th Sep 2002, by LH :
Bram Moolenaarf1568ec2011-12-14 21:17:39 +010011" (*) better support for the option
12" (*) use some regex instead of several '||'.
13" Oct 9th, 2003, by JT:
14" (*) don't change indentation of lines starting with '%'
Bram Moolenaar61d35bd2012-03-28 20:51:51 +020015" 2005/06/15, Moshe Kaminsky <kaminsky AT math.huji.ac.il>
Bram Moolenaarf1568ec2011-12-14 21:17:39 +010016" (*) New variables:
17" g:tex_items, g:tex_itemize_env, g:tex_noindent_env
Bram Moolenaarb4d6c3e2017-05-27 16:45:17 +020018" 2011/3/6, by Yichao Zhou <broken.zhou AT gmail.com>
Bram Moolenaarf1568ec2011-12-14 21:17:39 +010019" (*) Don't change indentation of lines starting with '%'
20" I don't see any code with '%' and it doesn't work properly
21" so I add some code.
22" (*) New features: Add smartindent-like indent for "{}" and "[]".
23" (*) New variables: g:tex_indent_brace
Bram Moolenaarb4d6c3e2017-05-27 16:45:17 +020024" 2011/9/25, by Yichao Zhou <broken.zhou AT gmail.com>
Bram Moolenaarf1568ec2011-12-14 21:17:39 +010025" (*) Bug fix: smartindent-like indent for "[]"
26" (*) New features: Align with "&".
Bram Moolenaar61d35bd2012-03-28 20:51:51 +020027" (*) New variable: g:tex_indent_and.
Bram Moolenaarb4d6c3e2017-05-27 16:45:17 +020028" 2011/10/23 by Yichao Zhou <broken.zhou AT gmail.com>
Bram Moolenaarf1568ec2011-12-14 21:17:39 +010029" (*) Bug fix: improve the smartindent-like indent for "{}" and
30" "[]".
Bram Moolenaarb4d6c3e2017-05-27 16:45:17 +020031" 2012/02/27 by Yichao Zhou <broken.zhou AT gmail.com>
Bram Moolenaar61d35bd2012-03-28 20:51:51 +020032" (*) Bug fix: support default folding marker.
33" (*) Indent with "&" is not very handy. Make it not enable by
34" default.
Bram Moolenaarb4d6c3e2017-05-27 16:45:17 +020035" 2012/03/06 by Yichao Zhou <broken.zhou AT gmail.com>
Bram Moolenaar61d35bd2012-03-28 20:51:51 +020036" (*) Modify "&" behavior and make it default again. Now "&"
37" won't align when there are more then one "&" in the previous
38" line.
39" (*) Add indent "\left(" and "\right)"
40" (*) Trust user when in "verbatim" and "lstlisting"
Bram Moolenaarb4d6c3e2017-05-27 16:45:17 +020041" 2012/03/11 by Yichao Zhou <broken.zhou AT gmail.com>
Bram Moolenaar61d35bd2012-03-28 20:51:51 +020042" (*) Modify "&" so that only indent when current line start with
Bram Moolenaar328da0d2016-03-04 22:22:32 +010043" "&".
Bram Moolenaarb4d6c3e2017-05-27 16:45:17 +020044" 2012/03/12 by Yichao Zhou <broken.zhou AT gmail.com>
Bram Moolenaar61d35bd2012-03-28 20:51:51 +020045" (*) Modify indentkeys.
Bram Moolenaarb4d6c3e2017-05-27 16:45:17 +020046" 2012/03/18 by Yichao Zhou <broken.zhou AT gmail.com>
Bram Moolenaar61d35bd2012-03-28 20:51:51 +020047" (*) Add &cpo
Bram Moolenaarb4d6c3e2017-05-27 16:45:17 +020048" 2013/05/02 by Yichao Zhou <broken.zhou AT gmail.com>
Bram Moolenaarad3b3662013-05-17 18:14:19 +020049" (*) Fix problem about GetTeXIndent checker. Thank Albert Netymk
50" for reporting this.
Bram Moolenaarb4d6c3e2017-05-27 16:45:17 +020051" 2014/06/23 by Yichao Zhou <broken.zhou AT gmail.com>
Bram Moolenaar328da0d2016-03-04 22:22:32 +010052" (*) Remove the feature g:tex_indent_and because it is buggy.
53" (*) If there is not any obvious indentation hints, we do not
54" alert our user's current indentation.
55" (*) g:tex_indent_brace now only works if the open brace is the
56" last character of that line.
Bram Moolenaarb4d6c3e2017-05-27 16:45:17 +020057" 2014/08/03 by Yichao Zhou <broken.zhou AT gmail.com>
Bram Moolenaar328da0d2016-03-04 22:22:32 +010058" (*) Indent current line if last line has larger indentation
Bram Moolenaarb4d6c3e2017-05-27 16:45:17 +020059" 2016/11/08 by Yichao Zhou <broken.zhou AT gmail.com>
60" (*) Fix problems for \[ and \]. Thanks Bruno for reporting.
61" 2017/04/30 by Yichao Zhou <broken.zhou AT gmail.com>
62" (*) Fix a bug between g:tex_noindent_env and g:tex_indent_items
63" Now g:tex_noindent_env='document\|verbatim\|itemize' (Emacs
64" style) is supported. Thanks Miles Wheeler for reporting.
Bram Moolenaar328da0d2016-03-04 22:22:32 +010065"
Bram Moolenaar61d35bd2012-03-28 20:51:51 +020066" }}}
Bram Moolenaarf1568ec2011-12-14 21:17:39 +010067
Bram Moolenaar61d35bd2012-03-28 20:51:51 +020068" Document: {{{
Bram Moolenaarf1568ec2011-12-14 21:17:39 +010069"
70" To set the following options (ok, currently it's just one), add a line like
71" let g:tex_indent_items = 1
72" to your ~/.vimrc.
73"
74" * g:tex_indent_brace
75"
76" If this variable is unset or non-zero, it will use smartindent-like style
Bram Moolenaar328da0d2016-03-04 22:22:32 +010077" for "{}" and "[]". Now this only works if the open brace is the last
78" character of that line.
79"
80" % Example 1
81" \usetikzlibrary{
82" external
83" }
84"
85" % Example 2
86" \tikzexternalize[
87" prefix=tikz]
Bram Moolenaarb4d6c3e2017-05-27 16:45:17 +020088"
Bram Moolenaarf1568ec2011-12-14 21:17:39 +010089" * g:tex_indent_items
90"
91" If this variable is set, item-environments are indented like Emacs does
92" it, i.e., continuation lines are indented with a shiftwidth.
Bram Moolenaarb4d6c3e2017-05-27 16:45:17 +020093"
Bram Moolenaarf1568ec2011-12-14 21:17:39 +010094" NOTE: I've already set the variable below; delete the corresponding line
95" if you don't like this behaviour.
96"
97" Per default, it is unset.
Bram Moolenaarb4d6c3e2017-05-27 16:45:17 +020098"
Bram Moolenaarf1568ec2011-12-14 21:17:39 +010099" set unset
100" ----------------------------------------------------------------
Bram Moolenaarb4d6c3e2017-05-27 16:45:17 +0200101" \begin{itemize} \begin{itemize}
Bram Moolenaarf1568ec2011-12-14 21:17:39 +0100102" \item blablabla \item blablabla
Bram Moolenaarb4d6c3e2017-05-27 16:45:17 +0200103" bla bla bla bla bla bla
Bram Moolenaarf1568ec2011-12-14 21:17:39 +0100104" \item blablabla \item blablabla
Bram Moolenaarb4d6c3e2017-05-27 16:45:17 +0200105" bla bla bla bla bla bla
106" \end{itemize} \end{itemize}
Bram Moolenaarf1568ec2011-12-14 21:17:39 +0100107"
108"
109" * g:tex_items
110"
Bram Moolenaarb4d6c3e2017-05-27 16:45:17 +0200111" A list of tokens to be considered as commands for the beginning of an item
112" command. The tokens should be separated with '\|'. The initial '\' should
Bram Moolenaarf1568ec2011-12-14 21:17:39 +0100113" be escaped. The default is '\\bibitem\|\\item'.
114"
115" * g:tex_itemize_env
Bram Moolenaarb4d6c3e2017-05-27 16:45:17 +0200116"
117" A list of environment names, separated with '\|', where the items (item
118" commands matching g:tex_items) may appear. The default is
Bram Moolenaarf1568ec2011-12-14 21:17:39 +0100119" 'itemize\|description\|enumerate\|thebibliography'.
120"
121" * g:tex_noindent_env
122"
Bram Moolenaarb4d6c3e2017-05-27 16:45:17 +0200123" A list of environment names. separated with '\|', where no indentation is
Bram Moolenaarf1568ec2011-12-14 21:17:39 +0100124" required. The default is 'document\|verbatim'.
Bram Moolenaarb4d6c3e2017-05-27 16:45:17 +0200125" }}}
Bram Moolenaar61d35bd2012-03-28 20:51:51 +0200126
127" Only define the function once
Bram Moolenaarf1568ec2011-12-14 21:17:39 +0100128if exists("b:did_indent")
129 finish
130endif
Bram Moolenaar61d35bd2012-03-28 20:51:51 +0200131
132let s:cpo_save = &cpo
133set cpo&vim
134
135" Define global variable {{{
136
Bram Moolenaarf1568ec2011-12-14 21:17:39 +0100137let b:did_indent = 1
138
Bram Moolenaarf1568ec2011-12-14 21:17:39 +0100139if !exists("g:tex_indent_items")
140 let g:tex_indent_items = 1
141endif
142if !exists("g:tex_indent_brace")
143 let g:tex_indent_brace = 1
144endif
Bram Moolenaar328da0d2016-03-04 22:22:32 +0100145if !exists("g:tex_max_scan_line")
146 let g:tex_max_scan_line = 60
Bram Moolenaarf1568ec2011-12-14 21:17:39 +0100147endif
148if g:tex_indent_items
149 if !exists("g:tex_itemize_env")
150 let g:tex_itemize_env = 'itemize\|description\|enumerate\|thebibliography'
151 endif
152 if !exists('g:tex_items')
Bram Moolenaarb4d6c3e2017-05-27 16:45:17 +0200153 let g:tex_items = '\\bibitem\|\\item'
Bram Moolenaarf1568ec2011-12-14 21:17:39 +0100154 endif
155else
156 let g:tex_items = ''
157endif
158
Bram Moolenaar61d35bd2012-03-28 20:51:51 +0200159if !exists("g:tex_noindent_env")
160 let g:tex_noindent_env = 'document\|verbatim\|lstlisting'
161endif "}}}
162
163" VIM Setting " {{{
Bram Moolenaarf1568ec2011-12-14 21:17:39 +0100164setlocal autoindent
165setlocal nosmartindent
166setlocal indentexpr=GetTeXIndent()
Bram Moolenaar61d35bd2012-03-28 20:51:51 +0200167setlocal indentkeys&
168exec 'setlocal indentkeys+=[,(,{,),},],\&' . substitute(g:tex_items, '^\|\(\\|\)', ',=', 'g')
169let g:tex_items = '^\s*' . substitute(g:tex_items, '^\(\^\\s\*\)*', '', '')
170" }}}
Bram Moolenaarf1568ec2011-12-14 21:17:39 +0100171
Bram Moolenaarad3b3662013-05-17 18:14:19 +0200172function! GetTeXIndent() " {{{
Bram Moolenaarf1568ec2011-12-14 21:17:39 +0100173 " Find a non-blank line above the current line.
174 let lnum = prevnonblank(v:lnum - 1)
Bram Moolenaar328da0d2016-03-04 22:22:32 +0100175 let cnum = v:lnum
Bram Moolenaarf1568ec2011-12-14 21:17:39 +0100176
177 " Comment line is not what we need.
178 while lnum != 0 && getline(lnum) =~ '^\s*%'
179 let lnum = prevnonblank(lnum - 1)
180 endwhile
181
182 " At the start of the file use zero indent.
183 if lnum == 0
Bram Moolenaarb4d6c3e2017-05-27 16:45:17 +0200184 return 0
Bram Moolenaarf1568ec2011-12-14 21:17:39 +0100185 endif
186
Bram Moolenaar328da0d2016-03-04 22:22:32 +0100187 let line = substitute(getline(lnum), '\s*%.*', '','g') " last line
188 let cline = substitute(getline(v:lnum), '\s*%.*', '', 'g') " current line
Bram Moolenaarf1568ec2011-12-14 21:17:39 +0100189
Bram Moolenaar61d35bd2012-03-28 20:51:51 +0200190 " We are in verbatim, so do what our user what.
191 if synIDattr(synID(v:lnum, indent(v:lnum), 1), "name") == "texZone"
192 if empty(cline)
193 return indent(lnum)
194 else
195 return indent(v:lnum)
196 end
197 endif
Bram Moolenaarb4d6c3e2017-05-27 16:45:17 +0200198
Bram Moolenaarf1568ec2011-12-14 21:17:39 +0100199 if lnum == 0
Bram Moolenaarb4d6c3e2017-05-27 16:45:17 +0200200 return 0
Bram Moolenaarf1568ec2011-12-14 21:17:39 +0100201 endif
202
203 let ind = indent(lnum)
Bram Moolenaar328da0d2016-03-04 22:22:32 +0100204 let stay = 1
Bram Moolenaarf1568ec2011-12-14 21:17:39 +0100205
206 " New code for comment: retain the indent of current line
207 if cline =~ '^\s*%'
208 return indent(v:lnum)
209 endif
210
211 " Add a 'shiftwidth' after beginning of environments.
212 " Don't add it for \begin{document} and \begin{verbatim}
Bram Moolenaarb4d6c3e2017-05-27 16:45:17 +0200213 " if line =~ '^\s*\\begin{\(.*\)}' && line !~ 'verbatim'
Bram Moolenaarf1568ec2011-12-14 21:17:39 +0100214 " LH modification : \begin does not always start a line
215 " ZYC modification : \end after \begin won't cause wrong indent anymore
Bram Moolenaarb4d6c3e2017-05-27 16:45:17 +0200216 if line =~ '\\begin{.*}'
217 if line !~ g:tex_noindent_env
Bram Moolenaar3ec574f2017-06-13 18:12:01 +0200218 let ind = ind + shiftwidth()
Bram Moolenaarb4d6c3e2017-05-27 16:45:17 +0200219 let stay = 0
220 endif
Bram Moolenaarf1568ec2011-12-14 21:17:39 +0100221
222 if g:tex_indent_items
223 " Add another sw for item-environments
224 if line =~ g:tex_itemize_env
Bram Moolenaar3ec574f2017-06-13 18:12:01 +0200225 let ind = ind + shiftwidth()
Bram Moolenaar328da0d2016-03-04 22:22:32 +0100226 let stay = 0
Bram Moolenaarf1568ec2011-12-14 21:17:39 +0100227 endif
228 endif
229 endif
230
Bram Moolenaar328da0d2016-03-04 22:22:32 +0100231 if cline =~ '\\end{.*}'
232 let retn = s:GetEndIndentation(v:lnum)
233 if retn != -1
234 return retn
235 endif
236 end
Bram Moolenaarf1568ec2011-12-14 21:17:39 +0100237 " Subtract a 'shiftwidth' when an environment ends
Bram Moolenaar328da0d2016-03-04 22:22:32 +0100238 if cline =~ '\\end{.*}'
239 \ && cline !~ g:tex_noindent_env
240 \ && cline !~ '\\begin{.*}.*\\end{.*}'
Bram Moolenaarf1568ec2011-12-14 21:17:39 +0100241 if g:tex_indent_items
242 " Remove another sw for item-environments
243 if cline =~ g:tex_itemize_env
Bram Moolenaar3ec574f2017-06-13 18:12:01 +0200244 let ind = ind - shiftwidth()
Bram Moolenaar328da0d2016-03-04 22:22:32 +0100245 let stay = 0
Bram Moolenaarf1568ec2011-12-14 21:17:39 +0100246 endif
247 endif
248
Bram Moolenaar3ec574f2017-06-13 18:12:01 +0200249 let ind = ind - shiftwidth()
Bram Moolenaar328da0d2016-03-04 22:22:32 +0100250 let stay = 0
Bram Moolenaarf1568ec2011-12-14 21:17:39 +0100251 endif
252
253 if g:tex_indent_brace
Bram Moolenaarb4d6c3e2017-05-27 16:45:17 +0200254 if line =~ '[[{]$'
Bram Moolenaar3ec574f2017-06-13 18:12:01 +0200255 let ind += shiftwidth()
Bram Moolenaar328da0d2016-03-04 22:22:32 +0100256 let stay = 0
257 endif
258
Bram Moolenaarb4d6c3e2017-05-27 16:45:17 +0200259 if cline =~ '^\s*\\\?[\]}]' && s:CheckPairedIsLastCharacter(v:lnum, indent(v:lnum))
Bram Moolenaar3ec574f2017-06-13 18:12:01 +0200260 let ind -= shiftwidth()
Bram Moolenaar328da0d2016-03-04 22:22:32 +0100261 let stay = 0
262 endif
263
Bram Moolenaarb4d6c3e2017-05-27 16:45:17 +0200264 if line !~ '^\s*\\\?[\]}]'
265 for i in range(indent(lnum)+1, strlen(line)-1)
266 let char = line[i]
267 if char == ']' || char == '}'
268 if s:CheckPairedIsLastCharacter(lnum, i)
Bram Moolenaar3ec574f2017-06-13 18:12:01 +0200269 let ind -= shiftwidth()
Bram Moolenaarb4d6c3e2017-05-27 16:45:17 +0200270 let stay = 0
271 endif
Bram Moolenaar328da0d2016-03-04 22:22:32 +0100272 endif
Bram Moolenaarb4d6c3e2017-05-27 16:45:17 +0200273 endfor
274 endif
Bram Moolenaar61d35bd2012-03-28 20:51:51 +0200275 endif
Bram Moolenaarf1568ec2011-12-14 21:17:39 +0100276
277 " Special treatment for 'item'
278 " ----------------------------
279
280 if g:tex_indent_items
Bram Moolenaarf1568ec2011-12-14 21:17:39 +0100281 " '\item' or '\bibitem' itself:
282 if cline =~ g:tex_items
Bram Moolenaar3ec574f2017-06-13 18:12:01 +0200283 let ind = ind - shiftwidth()
Bram Moolenaar328da0d2016-03-04 22:22:32 +0100284 let stay = 0
Bram Moolenaarf1568ec2011-12-14 21:17:39 +0100285 endif
Bram Moolenaarf1568ec2011-12-14 21:17:39 +0100286 " lines following to '\item' are intented once again:
287 if line =~ g:tex_items
Bram Moolenaar3ec574f2017-06-13 18:12:01 +0200288 let ind = ind + shiftwidth()
Bram Moolenaar328da0d2016-03-04 22:22:32 +0100289 let stay = 0
Bram Moolenaarf1568ec2011-12-14 21:17:39 +0100290 endif
Bram Moolenaarf1568ec2011-12-14 21:17:39 +0100291 endif
292
Bram Moolenaar328da0d2016-03-04 22:22:32 +0100293 if stay
294 " If there is no obvious indentation hint, we trust our user.
295 if empty(cline)
296 return ind
297 else
298 return max([indent(v:lnum), s:GetLastBeginIndentation(v:lnum)])
299 endif
300 else
301 return ind
302 endif
303endfunction "}}}
304
305function! s:GetLastBeginIndentation(lnum) " {{{
306 let matchend = 1
307 for lnum in range(a:lnum-1, max([a:lnum - g:tex_max_scan_line, 1]), -1)
308 let line = getline(lnum)
309 if line =~ '\\end{.*}'
310 let matchend += 1
311 endif
312 if line =~ '\\begin{.*}'
313 let matchend -= 1
314 endif
315 if matchend == 0
Bram Moolenaar328da0d2016-03-04 22:22:32 +0100316 if line =~ g:tex_noindent_env
317 return indent(lnum)
318 endif
Bram Moolenaarb4d6c3e2017-05-27 16:45:17 +0200319 if line =~ g:tex_itemize_env
Bram Moolenaar3ec574f2017-06-13 18:12:01 +0200320 return indent(lnum) + 2 * shiftwidth()
Bram Moolenaarb4d6c3e2017-05-27 16:45:17 +0200321 endif
Bram Moolenaar3ec574f2017-06-13 18:12:01 +0200322 return indent(lnum) + shiftwidth()
Bram Moolenaar328da0d2016-03-04 22:22:32 +0100323 endif
324 endfor
325 return -1
326endfunction
327
328function! s:GetEndIndentation(lnum) " {{{
329 if getline(a:lnum) =~ '\\begin{.*}.*\\end{.*}'
330 return -1
331 endif
332
333 let min_indent = 100
334 let matchend = 1
335 for lnum in range(a:lnum-1, max([a:lnum-g:tex_max_scan_line, 1]), -1)
336 let line = getline(lnum)
337 if line =~ '\\end{.*}'
338 let matchend += 1
339 endif
340 if line =~ '\\begin{.*}'
341 let matchend -= 1
342 endif
343 if matchend == 0
344 return indent(lnum)
345 endif
346 if !empty(line)
347 let min_indent = min([min_indent, indent(lnum)])
348 endif
349 endfor
Bram Moolenaar3ec574f2017-06-13 18:12:01 +0200350 return min_indent - shiftwidth()
Bram Moolenaar328da0d2016-03-04 22:22:32 +0100351endfunction
352
353" Most of the code is from matchparen.vim
354function! s:CheckPairedIsLastCharacter(lnum, col) "{{{
Bram Moolenaar328da0d2016-03-04 22:22:32 +0100355 let c_lnum = a:lnum
356 let c_col = a:col+1
357
Bram Moolenaarb4d6c3e2017-05-27 16:45:17 +0200358 let line = getline(c_lnum)
359 if line[c_col-1] == '\'
360 let c_col = c_col + 1
361 endif
362 let c = line[c_col-1]
Bram Moolenaar328da0d2016-03-04 22:22:32 +0100363
Bram Moolenaar328da0d2016-03-04 22:22:32 +0100364 let plist = split(&matchpairs, '.\zs[:,]')
365 let i = index(plist, c)
366 if i < 0
367 return 0
368 endif
369
370 " Figure out the arguments for searchpairpos().
371 if i % 2 == 0
372 let s_flags = 'nW'
373 let c2 = plist[i + 1]
374 else
375 let s_flags = 'nbW'
376 let c2 = c
377 let c = plist[i - 1]
378 endif
379 if c == '['
380 let c = '\['
381 let c2 = '\]'
382 endif
383
384 " Find the match. When it was just before the cursor move it there for a
385 " moment.
386 let save_cursor = winsaveview()
387 call cursor(c_lnum, c_col)
388
389 " When not in a string or comment ignore matches inside them.
390 " We match "escape" for special items, such as lispEscapeSpecial.
391 let s_skip ='synIDattr(synID(line("."), col("."), 0), "name") ' .
392 \ '=~? "string\\|character\\|singlequote\\|escape\\|comment"'
393 execute 'if' s_skip '| let s_skip = 0 | endif'
394
395 let stopline = max([0, c_lnum - g:tex_max_scan_line])
396
397 " Limit the search time to 300 msec to avoid a hang on very long lines.
398 " This fails when a timeout is not supported.
399 try
400 let [m_lnum, m_col] = searchpairpos(c, '', c2, s_flags, s_skip, stopline, 100)
401 catch /E118/
402 endtry
403
404 call winrestview(save_cursor)
405
406 if m_lnum > 0
407 let line = getline(m_lnum)
408 return strlen(line) == m_col
409 endif
410
411 return 0
Bram Moolenaar61d35bd2012-03-28 20:51:51 +0200412endfunction "}}}
Bram Moolenaarf1568ec2011-12-14 21:17:39 +0100413
Bram Moolenaarb6b046b2011-12-30 13:11:27 +0100414let &cpo = s:cpo_save
415unlet s:cpo_save
416
Bram Moolenaarf1568ec2011-12-14 21:17:39 +0100417" vim: set sw=4 textwidth=80: