blob: 68d13fb116117ae2256dd3d35ff4b99684dad05d [file] [log] [blame]
Bram Moolenaareb3dc872018-05-13 22:34:24 +02001" Vim indent file
2" Language: LaTeX
3" Maintainer: Yichao Zhou <broken.zhou AT gmail.com>
4" Created: Sat, 16 Feb 2002 16:50:19 +0100
5" Version: 1.0.0
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
Bram Moolenaareb3dc872018-05-13 22:34:24 +02009" Last Update: {{{
Bram Moolenaar61d35bd2012-03-28 20:51:51 +020010" 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 Moolenaareb3dc872018-05-13 22:34:24 +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 Moolenaareb3dc872018-05-13 22:34:24 +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 Moolenaareb3dc872018-05-13 22:34:24 +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 Moolenaareb3dc872018-05-13 22:34:24 +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 Moolenaareb3dc872018-05-13 22:34:24 +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 Moolenaareb3dc872018-05-13 22:34:24 +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 Moolenaareb3dc872018-05-13 22:34:24 +020044" 2012/03/12 by Yichao Zhou <broken.zhou AT gmail.com>
Bram Moolenaar61d35bd2012-03-28 20:51:51 +020045" (*) Modify indentkeys.
Bram Moolenaareb3dc872018-05-13 22:34:24 +020046" 2012/03/18 by Yichao Zhou <broken.zhou AT gmail.com>
Bram Moolenaar61d35bd2012-03-28 20:51:51 +020047" (*) Add &cpo
Bram Moolenaareb3dc872018-05-13 22:34:24 +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 Moolenaareb3dc872018-05-13 22:34:24 +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 Moolenaareb3dc872018-05-13 22:34:24 +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 Moolenaareb3dc872018-05-13 22:34:24 +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.
65" 2018/02/07 by Yichao Zhou <broken.zhou AT gmail.com>
66" (*) Make indentation more smart in the normal mode
Bram Moolenaar388a5d42020-05-26 21:20:45 +020067" 2020/04/26 by Yichao Zhou <broken.zhou AT gmail.com>
68" (*) Fix a bug related to \[ & \]. Thanks Manuel Boni for
69" reporting.
dkearns0382f052023-08-29 05:32:59 +100070" 2023/08/28 by Vim Project
71" (*) Set b:undo_indent.
Bram Moolenaar61d35bd2012-03-28 20:51:51 +020072" }}}
Bram Moolenaareb3dc872018-05-13 22:34:24 +020073
74" Document: {{{
75"
Bram Moolenaar388a5d42020-05-26 21:20:45 +020076" For proper latex experience, please put
77" let g:tex_flavor = "latex"
78" into your vimrc.
Bram Moolenaareb3dc872018-05-13 22:34:24 +020079"
80" * g:tex_indent_brace
81"
82" If this variable is unset or non-zero, it will use smartindent-like style
83" for "{}" and "[]". Now this only works if the open brace is the last
84" character of that line.
85"
86" % Example 1
87" \usetikzlibrary{
88" external
89" }
90"
91" % Example 2
92" \tikzexternalize[
93" prefix=tikz]
94"
95" * g:tex_indent_items
96"
97" If this variable is set, item-environments are indented like Emacs does
98" it, i.e., continuation lines are indented with a shiftwidth.
99"
100" set unset
101" ------------------------------------------------------
102" \begin{itemize} \begin{itemize}
103" \item blablabla \item blablabla
104" bla bla bla bla bla bla
105" \item blablabla \item blablabla
106" bla bla bla bla bla bla
107" \end{itemize} \end{itemize}
108"
109"
110" * g:tex_items
111"
112" A list of tokens to be considered as commands for the beginning of an item
113" command. The tokens should be separated with '\|'. The initial '\' should
114" be escaped. The default is '\\bibitem\|\\item'.
115"
116" * g:tex_itemize_env
117"
118" A list of environment names, separated with '\|', where the items (item
119" commands matching g:tex_items) may appear. The default is
120" 'itemize\|description\|enumerate\|thebibliography'.
121"
122" * g:tex_noindent_env
123"
124" A list of environment names. separated with '\|', where no indentation is
125" required. The default is 'document\|verbatim'.
126" }}}
127
128" Only define the function once
Bram Moolenaarf1568ec2011-12-14 21:17:39 +0100129if exists("b:did_indent")
130 finish
131endif
Bram Moolenaar61d35bd2012-03-28 20:51:51 +0200132
133let s:cpo_save = &cpo
134set cpo&vim
Bram Moolenaareb3dc872018-05-13 22:34:24 +0200135
136" Define global variable {{{
137
Bram Moolenaarf1568ec2011-12-14 21:17:39 +0100138let b:did_indent = 1
139
Bram Moolenaarf1568ec2011-12-14 21:17:39 +0100140if !exists("g:tex_indent_items")
141 let g:tex_indent_items = 1
142endif
143if !exists("g:tex_indent_brace")
144 let g:tex_indent_brace = 1
145endif
Bram Moolenaar328da0d2016-03-04 22:22:32 +0100146if !exists("g:tex_max_scan_line")
147 let g:tex_max_scan_line = 60
Bram Moolenaarf1568ec2011-12-14 21:17:39 +0100148endif
149if g:tex_indent_items
150 if !exists("g:tex_itemize_env")
151 let g:tex_itemize_env = 'itemize\|description\|enumerate\|thebibliography'
152 endif
153 if !exists('g:tex_items')
Bram Moolenaareb3dc872018-05-13 22:34:24 +0200154 let g:tex_items = '\\bibitem\|\\item'
Bram Moolenaarf1568ec2011-12-14 21:17:39 +0100155 endif
156else
157 let g:tex_items = ''
158endif
159
Bram Moolenaar61d35bd2012-03-28 20:51:51 +0200160if !exists("g:tex_noindent_env")
161 let g:tex_noindent_env = 'document\|verbatim\|lstlisting'
162endif "}}}
Bram Moolenaareb3dc872018-05-13 22:34:24 +0200163
164" VIM Setting " {{{
Bram Moolenaarf1568ec2011-12-14 21:17:39 +0100165setlocal autoindent
166setlocal nosmartindent
167setlocal indentexpr=GetTeXIndent()
Bram Moolenaar61d35bd2012-03-28 20:51:51 +0200168setlocal indentkeys&
169exec 'setlocal indentkeys+=[,(,{,),},],\&' . substitute(g:tex_items, '^\|\(\\|\)', ',=', 'g')
170let g:tex_items = '^\s*' . substitute(g:tex_items, '^\(\^\\s\*\)*', '', '')
dkearns0382f052023-08-29 05:32:59 +1000171let b:undo_indent = "setlocal autoindent< indentexpr< indentkeys< smartindent<"
Bram Moolenaar7db25fe2018-05-13 00:02:36 +0200172" }}}
Bram Moolenaareb3dc872018-05-13 22:34:24 +0200173
174function! GetTeXIndent() " {{{
Bram Moolenaarf1568ec2011-12-14 21:17:39 +0100175 " Find a non-blank line above the current line.
176 let lnum = prevnonblank(v:lnum - 1)
Bram Moolenaar328da0d2016-03-04 22:22:32 +0100177 let cnum = v:lnum
Bram Moolenaarf1568ec2011-12-14 21:17:39 +0100178
179 " Comment line is not what we need.
180 while lnum != 0 && getline(lnum) =~ '^\s*%'
181 let lnum = prevnonblank(lnum - 1)
182 endwhile
183
184 " At the start of the file use zero indent.
185 if lnum == 0
Bram Moolenaareb3dc872018-05-13 22:34:24 +0200186 return 0
Bram Moolenaarf1568ec2011-12-14 21:17:39 +0100187 endif
188
Bram Moolenaar328da0d2016-03-04 22:22:32 +0100189 let line = substitute(getline(lnum), '\s*%.*', '','g') " last line
190 let cline = substitute(getline(v:lnum), '\s*%.*', '', 'g') " current line
Bram Moolenaarf1568ec2011-12-14 21:17:39 +0100191
Bram Moolenaar388a5d42020-05-26 21:20:45 +0200192 let ccol = 1
193 while cline[ccol] =~ '\s'
194 let ccol += 1
195 endwhile
196
Bram Moolenaar61d35bd2012-03-28 20:51:51 +0200197 " We are in verbatim, so do what our user what.
Bram Moolenaar388a5d42020-05-26 21:20:45 +0200198 if synIDattr(synID(v:lnum, ccol, 1), "name") == "texZone"
Bram Moolenaar61d35bd2012-03-28 20:51:51 +0200199 if empty(cline)
200 return indent(lnum)
201 else
202 return indent(v:lnum)
Bram Moolenaar388a5d42020-05-26 21:20:45 +0200203 endif
Bram Moolenaar61d35bd2012-03-28 20:51:51 +0200204 endif
Bram Moolenaareb3dc872018-05-13 22:34:24 +0200205
Bram Moolenaarf1568ec2011-12-14 21:17:39 +0100206 if lnum == 0
Bram Moolenaareb3dc872018-05-13 22:34:24 +0200207 return 0
Bram Moolenaarf1568ec2011-12-14 21:17:39 +0100208 endif
209
210 let ind = indent(lnum)
Bram Moolenaar328da0d2016-03-04 22:22:32 +0100211 let stay = 1
Bram Moolenaarf1568ec2011-12-14 21:17:39 +0100212
213 " New code for comment: retain the indent of current line
214 if cline =~ '^\s*%'
215 return indent(v:lnum)
216 endif
217
Bram Moolenaareb3dc872018-05-13 22:34:24 +0200218 " Add a 'shiftwidth' after beginning of environments.
219 " Don't add it for \begin{document} and \begin{verbatim}
220 " if line =~ '^\s*\\begin{\(.*\)}' && line !~ 'verbatim'
221 " LH modification : \begin does not always start a line
222 " ZYC modification : \end after \begin won't cause wrong indent anymore
223 if line =~ '\\begin{.*}'
224 if line !~ g:tex_noindent_env
225 let ind = ind + shiftwidth()
226 let stay = 0
227 endif
Bram Moolenaarf1568ec2011-12-14 21:17:39 +0100228
229 if g:tex_indent_items
230 " Add another sw for item-environments
231 if line =~ g:tex_itemize_env
Bram Moolenaar3ec574f2017-06-13 18:12:01 +0200232 let ind = ind + shiftwidth()
Bram Moolenaar328da0d2016-03-04 22:22:32 +0100233 let stay = 0
Bram Moolenaarf1568ec2011-12-14 21:17:39 +0100234 endif
235 endif
236 endif
237
Bram Moolenaar328da0d2016-03-04 22:22:32 +0100238 if cline =~ '\\end{.*}'
239 let retn = s:GetEndIndentation(v:lnum)
240 if retn != -1
241 return retn
242 endif
243 end
Bram Moolenaarf1568ec2011-12-14 21:17:39 +0100244 " Subtract a 'shiftwidth' when an environment ends
Bram Moolenaar328da0d2016-03-04 22:22:32 +0100245 if cline =~ '\\end{.*}'
246 \ && cline !~ g:tex_noindent_env
247 \ && cline !~ '\\begin{.*}.*\\end{.*}'
Bram Moolenaarf1568ec2011-12-14 21:17:39 +0100248 if g:tex_indent_items
249 " Remove another sw for item-environments
250 if cline =~ g:tex_itemize_env
Bram Moolenaar3ec574f2017-06-13 18:12:01 +0200251 let ind = ind - shiftwidth()
Bram Moolenaar328da0d2016-03-04 22:22:32 +0100252 let stay = 0
Bram Moolenaarf1568ec2011-12-14 21:17:39 +0100253 endif
254 endif
255
Bram Moolenaar3ec574f2017-06-13 18:12:01 +0200256 let ind = ind - shiftwidth()
Bram Moolenaar328da0d2016-03-04 22:22:32 +0100257 let stay = 0
Bram Moolenaarf1568ec2011-12-14 21:17:39 +0100258 endif
259
260 if g:tex_indent_brace
Bram Moolenaareb3dc872018-05-13 22:34:24 +0200261 if line =~ '[[{]$'
Bram Moolenaar3ec574f2017-06-13 18:12:01 +0200262 let ind += shiftwidth()
Bram Moolenaar328da0d2016-03-04 22:22:32 +0100263 let stay = 0
264 endif
265
Bram Moolenaar388a5d42020-05-26 21:20:45 +0200266 if cline =~ '^\s*\\\?[\]}]' && s:CheckPairedIsLastCharacter(v:lnum, ccol)
Bram Moolenaar3ec574f2017-06-13 18:12:01 +0200267 let ind -= shiftwidth()
Bram Moolenaar328da0d2016-03-04 22:22:32 +0100268 let stay = 0
269 endif
270
Bram Moolenaareb3dc872018-05-13 22:34:24 +0200271 if line !~ '^\s*\\\?[\]}]'
Bram Moolenaar388a5d42020-05-26 21:20:45 +0200272 for i in range(1, strlen(line)-1)
Bram Moolenaareb3dc872018-05-13 22:34:24 +0200273 let char = line[i]
274 if char == ']' || char == '}'
275 if s:CheckPairedIsLastCharacter(lnum, i)
276 let ind -= shiftwidth()
277 let stay = 0
278 endif
Bram Moolenaar328da0d2016-03-04 22:22:32 +0100279 endif
Bram Moolenaareb3dc872018-05-13 22:34:24 +0200280 endfor
281 endif
Bram Moolenaar61d35bd2012-03-28 20:51:51 +0200282 endif
Bram Moolenaarf1568ec2011-12-14 21:17:39 +0100283
284 " Special treatment for 'item'
285 " ----------------------------
286
287 if g:tex_indent_items
Bram Moolenaarf1568ec2011-12-14 21:17:39 +0100288 " '\item' or '\bibitem' itself:
289 if cline =~ g:tex_items
Bram Moolenaar3ec574f2017-06-13 18:12:01 +0200290 let ind = ind - shiftwidth()
Bram Moolenaar328da0d2016-03-04 22:22:32 +0100291 let stay = 0
Bram Moolenaarf1568ec2011-12-14 21:17:39 +0100292 endif
Bram Moolenaar6c391a72021-09-09 21:55:11 +0200293 " lines following to '\item' are indented once again:
Bram Moolenaarf1568ec2011-12-14 21:17:39 +0100294 if line =~ g:tex_items
Bram Moolenaar3ec574f2017-06-13 18:12:01 +0200295 let ind = ind + shiftwidth()
Bram Moolenaar328da0d2016-03-04 22:22:32 +0100296 let stay = 0
Bram Moolenaarf1568ec2011-12-14 21:17:39 +0100297 endif
Bram Moolenaarf1568ec2011-12-14 21:17:39 +0100298 endif
299
Bram Moolenaareb3dc872018-05-13 22:34:24 +0200300 if stay && mode() == 'i'
301 " If there is no obvious indentation hint, and indentation is triggered
302 " in insert mode, we trust our user.
Bram Moolenaar328da0d2016-03-04 22:22:32 +0100303 if empty(cline)
304 return ind
305 else
306 return max([indent(v:lnum), s:GetLastBeginIndentation(v:lnum)])
307 endif
308 else
309 return ind
310 endif
311endfunction "}}}
Bram Moolenaareb3dc872018-05-13 22:34:24 +0200312
313function! s:GetLastBeginIndentation(lnum) " {{{
Bram Moolenaar328da0d2016-03-04 22:22:32 +0100314 let matchend = 1
315 for lnum in range(a:lnum-1, max([a:lnum - g:tex_max_scan_line, 1]), -1)
316 let line = getline(lnum)
317 if line =~ '\\end{.*}'
318 let matchend += 1
319 endif
320 if line =~ '\\begin{.*}'
321 let matchend -= 1
322 endif
323 if matchend == 0
Bram Moolenaar7db25fe2018-05-13 00:02:36 +0200324 if line =~ g:tex_noindent_env
325 return indent(lnum)
326 endif
Bram Moolenaareb3dc872018-05-13 22:34:24 +0200327 if line =~ g:tex_itemize_env
328 return indent(lnum) + 2 * shiftwidth()
329 endif
Bram Moolenaar3ec574f2017-06-13 18:12:01 +0200330 return indent(lnum) + shiftwidth()
Bram Moolenaar328da0d2016-03-04 22:22:32 +0100331 endif
332 endfor
333 return -1
334endfunction
335
Bram Moolenaareb3dc872018-05-13 22:34:24 +0200336function! s:GetEndIndentation(lnum) " {{{
Bram Moolenaar328da0d2016-03-04 22:22:32 +0100337 if getline(a:lnum) =~ '\\begin{.*}.*\\end{.*}'
338 return -1
339 endif
340
341 let min_indent = 100
342 let matchend = 1
343 for lnum in range(a:lnum-1, max([a:lnum-g:tex_max_scan_line, 1]), -1)
344 let line = getline(lnum)
345 if line =~ '\\end{.*}'
346 let matchend += 1
347 endif
348 if line =~ '\\begin{.*}'
349 let matchend -= 1
350 endif
351 if matchend == 0
352 return indent(lnum)
353 endif
354 if !empty(line)
355 let min_indent = min([min_indent, indent(lnum)])
356 endif
357 endfor
Bram Moolenaar3ec574f2017-06-13 18:12:01 +0200358 return min_indent - shiftwidth()
Bram Moolenaar328da0d2016-03-04 22:22:32 +0100359endfunction
360
361" Most of the code is from matchparen.vim
362function! s:CheckPairedIsLastCharacter(lnum, col) "{{{
Bram Moolenaar328da0d2016-03-04 22:22:32 +0100363 let c_lnum = a:lnum
364 let c_col = a:col+1
365
Bram Moolenaareb3dc872018-05-13 22:34:24 +0200366 let line = getline(c_lnum)
367 if line[c_col-1] == '\'
368 let c_col = c_col + 1
369 endif
370 let c = line[c_col-1]
Bram Moolenaar328da0d2016-03-04 22:22:32 +0100371
Bram Moolenaar328da0d2016-03-04 22:22:32 +0100372 let plist = split(&matchpairs, '.\zs[:,]')
373 let i = index(plist, c)
374 if i < 0
375 return 0
376 endif
377
378 " Figure out the arguments for searchpairpos().
379 if i % 2 == 0
380 let s_flags = 'nW'
381 let c2 = plist[i + 1]
382 else
383 let s_flags = 'nbW'
384 let c2 = c
385 let c = plist[i - 1]
386 endif
387 if c == '['
388 let c = '\['
389 let c2 = '\]'
390 endif
391
392 " Find the match. When it was just before the cursor move it there for a
393 " moment.
394 let save_cursor = winsaveview()
395 call cursor(c_lnum, c_col)
396
397 " When not in a string or comment ignore matches inside them.
398 " We match "escape" for special items, such as lispEscapeSpecial.
399 let s_skip ='synIDattr(synID(line("."), col("."), 0), "name") ' .
400 \ '=~? "string\\|character\\|singlequote\\|escape\\|comment"'
401 execute 'if' s_skip '| let s_skip = 0 | endif'
402
403 let stopline = max([0, c_lnum - g:tex_max_scan_line])
404
405 " Limit the search time to 300 msec to avoid a hang on very long lines.
406 " This fails when a timeout is not supported.
407 try
408 let [m_lnum, m_col] = searchpairpos(c, '', c2, s_flags, s_skip, stopline, 100)
409 catch /E118/
410 endtry
411
412 call winrestview(save_cursor)
413
414 if m_lnum > 0
415 let line = getline(m_lnum)
416 return strlen(line) == m_col
417 endif
418
419 return 0
Bram Moolenaareb3dc872018-05-13 22:34:24 +0200420endfunction "}}}
421
Bram Moolenaarb6b046b2011-12-30 13:11:27 +0100422let &cpo = s:cpo_save
423unlet s:cpo_save
424
Bram Moolenaarf1568ec2011-12-14 21:17:39 +0100425" vim: set sw=4 textwidth=80: