xref: /vim-8.2.3635/runtime/indent/tcl.vim (revision 6e649224)
1" Vim indent file
2" Language:		Tcl
3" Maintainer:		Chris Heithoff <[email protected]>
4" Previous Maintainer:	Nikolai Weibull <[email protected]>
5" Last Change:		24 Sep 2021
6
7if exists("b:did_indent")
8  finish
9endif
10let b:did_indent = 1
11
12setlocal indentexpr=GetTclIndent()
13setlocal indentkeys=0{,0},!^F,o,O,0]
14setlocal nosmartindent
15
16let b:undo_indent = "setl inde< indk< si<"
17
18if exists("*GetTclIndent")
19  finish
20endif
21
22function s:prevnonblanknoncomment(lnum)
23  let lnum = prevnonblank(a:lnum)
24  while lnum > 0
25    let line = getline(lnum)
26    if line !~ '^\s*\(#\|$\)'
27      break
28    endif
29    let lnum = prevnonblank(lnum - 1)
30  endwhile
31  return lnum
32endfunction
33
34function s:ends_with_backslash(lnum)
35  let line = getline(a:lnum)
36  if line =~ '\\\s*$'
37    return 1
38  else
39    return 0
40  endif
41endfunction
42
43function s:count_braces(lnum, count_open)
44  let n_open = 0
45  let n_close = 0
46  let line = getline(a:lnum)
47  let pattern = '[{}]'
48  let i = match(line, pattern)
49  while i != -1
50    if synIDattr(synID(a:lnum, i + 1, 0), 'name') !~ 'tcl\%(Comment\|String\)'
51      if line[i] == '{'
52        let n_open += 1
53      elseif line[i] == '}'
54        if n_open > 0
55          let n_open -= 1
56        else
57          let n_close += 1
58        endif
59      endif
60    endif
61    let i = match(line, pattern, i + 1)
62  endwhile
63  return a:count_open ? n_open : n_close
64endfunction
65
66function GetTclIndent()
67  let line = getline(v:lnum)
68
69  " Get the line number of the previous non-blank or non-comment line.
70  let pnum = s:prevnonblanknoncomment(v:lnum - 1)
71  if pnum == 0
72    return 0
73  endif
74
75  " ..and the previous line before the previous line.
76  let pnum2 = s:prevnonblanknoncomment(pnum-1)
77
78  " Default indentation is to preserve the previous indentation.
79  let ind = indent(pnum)
80
81  " ...but if previous line introduces an open brace, then increase current line's indentation
82  if s:count_braces(pnum, 1) > 0
83    let ind += shiftwidth()
84  else
85    " Look for backslash line continuation on the previous two lines.
86    let slash1 = s:ends_with_backslash(pnum)
87    let slash2 = s:ends_with_backslash(pnum2)
88    if slash1 && !slash2
89      " If the previous line begins a line continuation.
90      let ind += shiftwidth()
91    elseif !slash1 && slash2
92      " If two lines ago was the end of a line continuation group of lines.
93      let ind -= shiftwidth()
94    endif
95  endif
96
97  " If the current line begins with a closed brace, then decrease the indentation by one.
98  if line =~ '^\s*}'
99    let ind -= shiftwidth()
100  endif
101
102  return ind
103endfunction
104