blob: d356ba905bc14e22759742e3d446059ebec25c36 [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.
Bram Moolenaar328da0d2016-03-04 22:22:32 +010070"
Bram Moolenaar61d35bd2012-03-28 20:51:51 +020071" }}}
Bram Moolenaareb3dc872018-05-13 22:34:24 +020072
73" Document: {{{
74"
Bram Moolenaar388a5d42020-05-26 21:20:45 +020075" For proper latex experience, please put
76" let g:tex_flavor = "latex"
77" into your vimrc.
Bram Moolenaareb3dc872018-05-13 22:34:24 +020078"
79" * g:tex_indent_brace
80"
81" If this variable is unset or non-zero, it will use smartindent-like style
82" for "{}" and "[]". Now this only works if the open brace is the last
83" character of that line.
84"
85" % Example 1
86" \usetikzlibrary{
87" external
88" }
89"
90" % Example 2
91" \tikzexternalize[
92" prefix=tikz]
93"
94" * g:tex_indent_items
95"
96" If this variable is set, item-environments are indented like Emacs does
97" it, i.e., continuation lines are indented with a shiftwidth.
98"
99" set unset
100" ------------------------------------------------------
101" \begin{itemize} \begin{itemize}
102" \item blablabla \item blablabla
103" bla bla bla bla bla bla
104" \item blablabla \item blablabla
105" bla bla bla bla bla bla
106" \end{itemize} \end{itemize}
107"
108"
109" * g:tex_items
110"
111" 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
113" be escaped. The default is '\\bibitem\|\\item'.
114"
115" * g:tex_itemize_env
116"
117" A list of environment names, separated with '\|', where the items (item
118" commands matching g:tex_items) may appear. The default is
119" 'itemize\|description\|enumerate\|thebibliography'.
120"
121" * g:tex_noindent_env
122"
123" A list of environment names. separated with '\|', where no indentation is
124" required. The default is 'document\|verbatim'.
125" }}}
126
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
Bram Moolenaareb3dc872018-05-13 22:34:24 +0200134
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 Moolenaareb3dc872018-05-13 22:34:24 +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 "}}}
Bram Moolenaareb3dc872018-05-13 22:34:24 +0200162
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\*\)*', '', '')
Bram Moolenaar7db25fe2018-05-13 00:02:36 +0200170" }}}
Bram Moolenaareb3dc872018-05-13 22:34:24 +0200171
172function! 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 Moolenaareb3dc872018-05-13 22:34:24 +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 Moolenaar388a5d42020-05-26 21:20:45 +0200190 let ccol = 1
191 while cline[ccol] =~ '\s'
192 let ccol += 1
193 endwhile
194
Bram Moolenaar61d35bd2012-03-28 20:51:51 +0200195 " We are in verbatim, so do what our user what.
Bram Moolenaar388a5d42020-05-26 21:20:45 +0200196 if synIDattr(synID(v:lnum, ccol, 1), "name") == "texZone"
Bram Moolenaar61d35bd2012-03-28 20:51:51 +0200197 if empty(cline)
198 return indent(lnum)
199 else
200 return indent(v:lnum)
Bram Moolenaar388a5d42020-05-26 21:20:45 +0200201 endif
Bram Moolenaar61d35bd2012-03-28 20:51:51 +0200202 endif
Bram Moolenaareb3dc872018-05-13 22:34:24 +0200203
Bram Moolenaarf1568ec2011-12-14 21:17:39 +0100204 if lnum == 0
Bram Moolenaareb3dc872018-05-13 22:34:24 +0200205 return 0
Bram Moolenaarf1568ec2011-12-14 21:17:39 +0100206 endif
207
208 let ind = indent(lnum)
Bram Moolenaar328da0d2016-03-04 22:22:32 +0100209 let stay = 1
Bram Moolenaarf1568ec2011-12-14 21:17:39 +0100210
211 " New code for comment: retain the indent of current line
212 if cline =~ '^\s*%'
213 return indent(v:lnum)
214 endif
215
Bram Moolenaareb3dc872018-05-13 22:34:24 +0200216 " Add a 'shiftwidth' after beginning of environments.
217 " Don't add it for \begin{document} and \begin{verbatim}
218 " if line =~ '^\s*\\begin{\(.*\)}' && line !~ 'verbatim'
219 " LH modification : \begin does not always start a line
220 " ZYC modification : \end after \begin won't cause wrong indent anymore
221 if line =~ '\\begin{.*}'
222 if line !~ g:tex_noindent_env
223 let ind = ind + shiftwidth()
224 let stay = 0
225 endif
Bram Moolenaarf1568ec2011-12-14 21:17:39 +0100226
227 if g:tex_indent_items
228 " Add another sw for item-environments
229 if line =~ g:tex_itemize_env
Bram Moolenaar3ec574f2017-06-13 18:12:01 +0200230 let ind = ind + shiftwidth()
Bram Moolenaar328da0d2016-03-04 22:22:32 +0100231 let stay = 0
Bram Moolenaarf1568ec2011-12-14 21:17:39 +0100232 endif
233 endif
234 endif
235
Bram Moolenaar328da0d2016-03-04 22:22:32 +0100236 if cline =~ '\\end{.*}'
237 let retn = s:GetEndIndentation(v:lnum)
238 if retn != -1
239 return retn
240 endif
241 end
Bram Moolenaarf1568ec2011-12-14 21:17:39 +0100242 " Subtract a 'shiftwidth' when an environment ends
Bram Moolenaar328da0d2016-03-04 22:22:32 +0100243 if cline =~ '\\end{.*}'
244 \ && cline !~ g:tex_noindent_env
245 \ && cline !~ '\\begin{.*}.*\\end{.*}'
Bram Moolenaarf1568ec2011-12-14 21:17:39 +0100246 if g:tex_indent_items
247 " Remove another sw for item-environments
248 if cline =~ g:tex_itemize_env
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 endif
253
Bram Moolenaar3ec574f2017-06-13 18:12:01 +0200254 let ind = ind - shiftwidth()
Bram Moolenaar328da0d2016-03-04 22:22:32 +0100255 let stay = 0
Bram Moolenaarf1568ec2011-12-14 21:17:39 +0100256 endif
257
258 if g:tex_indent_brace
Bram Moolenaareb3dc872018-05-13 22:34:24 +0200259 if line =~ '[[{]$'
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 Moolenaar388a5d42020-05-26 21:20:45 +0200264 if cline =~ '^\s*\\\?[\]}]' && s:CheckPairedIsLastCharacter(v:lnum, ccol)
Bram Moolenaar3ec574f2017-06-13 18:12:01 +0200265 let ind -= shiftwidth()
Bram Moolenaar328da0d2016-03-04 22:22:32 +0100266 let stay = 0
267 endif
268
Bram Moolenaareb3dc872018-05-13 22:34:24 +0200269 if line !~ '^\s*\\\?[\]}]'
Bram Moolenaar388a5d42020-05-26 21:20:45 +0200270 for i in range(1, strlen(line)-1)
Bram Moolenaareb3dc872018-05-13 22:34:24 +0200271 let char = line[i]
272 if char == ']' || char == '}'
273 if s:CheckPairedIsLastCharacter(lnum, i)
274 let ind -= shiftwidth()
275 let stay = 0
276 endif
Bram Moolenaar328da0d2016-03-04 22:22:32 +0100277 endif
Bram Moolenaareb3dc872018-05-13 22:34:24 +0200278 endfor
279 endif
Bram Moolenaar61d35bd2012-03-28 20:51:51 +0200280 endif
Bram Moolenaarf1568ec2011-12-14 21:17:39 +0100281
282 " Special treatment for 'item'
283 " ----------------------------
284
285 if g:tex_indent_items
Bram Moolenaarf1568ec2011-12-14 21:17:39 +0100286 " '\item' or '\bibitem' itself:
287 if cline =~ 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 Moolenaar6c391a72021-09-09 21:55:11 +0200291 " lines following to '\item' are indented once again:
Bram Moolenaarf1568ec2011-12-14 21:17:39 +0100292 if line =~ g:tex_items
Bram Moolenaar3ec574f2017-06-13 18:12:01 +0200293 let ind = ind + shiftwidth()
Bram Moolenaar328da0d2016-03-04 22:22:32 +0100294 let stay = 0
Bram Moolenaarf1568ec2011-12-14 21:17:39 +0100295 endif
Bram Moolenaarf1568ec2011-12-14 21:17:39 +0100296 endif
297
Bram Moolenaareb3dc872018-05-13 22:34:24 +0200298 if stay && mode() == 'i'
299 " If there is no obvious indentation hint, and indentation is triggered
300 " in insert mode, we trust our user.
Bram Moolenaar328da0d2016-03-04 22:22:32 +0100301 if empty(cline)
302 return ind
303 else
304 return max([indent(v:lnum), s:GetLastBeginIndentation(v:lnum)])
305 endif
306 else
307 return ind
308 endif
309endfunction "}}}
Bram Moolenaareb3dc872018-05-13 22:34:24 +0200310
311function! s:GetLastBeginIndentation(lnum) " {{{
Bram Moolenaar328da0d2016-03-04 22:22:32 +0100312 let matchend = 1
313 for lnum in range(a:lnum-1, max([a:lnum - g:tex_max_scan_line, 1]), -1)
314 let line = getline(lnum)
315 if line =~ '\\end{.*}'
316 let matchend += 1
317 endif
318 if line =~ '\\begin{.*}'
319 let matchend -= 1
320 endif
321 if matchend == 0
Bram Moolenaar7db25fe2018-05-13 00:02:36 +0200322 if line =~ g:tex_noindent_env
323 return indent(lnum)
324 endif
Bram Moolenaareb3dc872018-05-13 22:34:24 +0200325 if line =~ g:tex_itemize_env
326 return indent(lnum) + 2 * shiftwidth()
327 endif
Bram Moolenaar3ec574f2017-06-13 18:12:01 +0200328 return indent(lnum) + shiftwidth()
Bram Moolenaar328da0d2016-03-04 22:22:32 +0100329 endif
330 endfor
331 return -1
332endfunction
333
Bram Moolenaareb3dc872018-05-13 22:34:24 +0200334function! s:GetEndIndentation(lnum) " {{{
Bram Moolenaar328da0d2016-03-04 22:22:32 +0100335 if getline(a:lnum) =~ '\\begin{.*}.*\\end{.*}'
336 return -1
337 endif
338
339 let min_indent = 100
340 let matchend = 1
341 for lnum in range(a:lnum-1, max([a:lnum-g:tex_max_scan_line, 1]), -1)
342 let line = getline(lnum)
343 if line =~ '\\end{.*}'
344 let matchend += 1
345 endif
346 if line =~ '\\begin{.*}'
347 let matchend -= 1
348 endif
349 if matchend == 0
350 return indent(lnum)
351 endif
352 if !empty(line)
353 let min_indent = min([min_indent, indent(lnum)])
354 endif
355 endfor
Bram Moolenaar3ec574f2017-06-13 18:12:01 +0200356 return min_indent - shiftwidth()
Bram Moolenaar328da0d2016-03-04 22:22:32 +0100357endfunction
358
359" Most of the code is from matchparen.vim
360function! s:CheckPairedIsLastCharacter(lnum, col) "{{{
Bram Moolenaar328da0d2016-03-04 22:22:32 +0100361 let c_lnum = a:lnum
362 let c_col = a:col+1
363
Bram Moolenaareb3dc872018-05-13 22:34:24 +0200364 let line = getline(c_lnum)
365 if line[c_col-1] == '\'
366 let c_col = c_col + 1
367 endif
368 let c = line[c_col-1]
Bram Moolenaar328da0d2016-03-04 22:22:32 +0100369
Bram Moolenaar328da0d2016-03-04 22:22:32 +0100370 let plist = split(&matchpairs, '.\zs[:,]')
371 let i = index(plist, c)
372 if i < 0
373 return 0
374 endif
375
376 " Figure out the arguments for searchpairpos().
377 if i % 2 == 0
378 let s_flags = 'nW'
379 let c2 = plist[i + 1]
380 else
381 let s_flags = 'nbW'
382 let c2 = c
383 let c = plist[i - 1]
384 endif
385 if c == '['
386 let c = '\['
387 let c2 = '\]'
388 endif
389
390 " Find the match. When it was just before the cursor move it there for a
391 " moment.
392 let save_cursor = winsaveview()
393 call cursor(c_lnum, c_col)
394
395 " When not in a string or comment ignore matches inside them.
396 " We match "escape" for special items, such as lispEscapeSpecial.
397 let s_skip ='synIDattr(synID(line("."), col("."), 0), "name") ' .
398 \ '=~? "string\\|character\\|singlequote\\|escape\\|comment"'
399 execute 'if' s_skip '| let s_skip = 0 | endif'
400
401 let stopline = max([0, c_lnum - g:tex_max_scan_line])
402
403 " Limit the search time to 300 msec to avoid a hang on very long lines.
404 " This fails when a timeout is not supported.
405 try
406 let [m_lnum, m_col] = searchpairpos(c, '', c2, s_flags, s_skip, stopline, 100)
407 catch /E118/
408 endtry
409
410 call winrestview(save_cursor)
411
412 if m_lnum > 0
413 let line = getline(m_lnum)
414 return strlen(line) == m_col
415 endif
416
417 return 0
Bram Moolenaareb3dc872018-05-13 22:34:24 +0200418endfunction "}}}
419
Bram Moolenaarb6b046b2011-12-30 13:11:27 +0100420let &cpo = s:cpo_save
421unlet s:cpo_save
422
Bram Moolenaarf1568ec2011-12-14 21:17:39 +0100423" vim: set sw=4 textwidth=80: