blob: eafb8dd56830edc96c0886802fa41a7c6f1c2e8e [file] [log] [blame]
Bram Moolenaar071d4272004-06-13 20:20:40 +00001" Vim indent file
Bram Moolenaard47d5222018-12-09 20:43:55 +01002" Language: Tcl
Bram Moolenaard47d5222018-12-09 20:43:55 +01003" Latest Update: Chris Heithoff <chrisheithoff@gmail.com>
Bram Moolenaar30e9b3c2019-09-07 16:24:12 +02004" Previous Maintainer: Nikolai Weibull <now@bitwi.se>
5" Latest Revision: 2018-12-05
Bram Moolenaar071d4272004-06-13 20:20:40 +00006
Bram Moolenaar071d4272004-06-13 20:20:40 +00007if exists("b:did_indent")
8 finish
9endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000010let b:did_indent = 1
11
12setlocal indentexpr=GetTclIndent()
Bram Moolenaar42eeac32005-06-29 22:40:58 +000013setlocal indentkeys=0{,0},!^F,o,O,0]
Bram Moolenaar2c7a7632007-05-10 18:19:11 +000014setlocal nosmartindent
Bram Moolenaar071d4272004-06-13 20:20:40 +000015
Bram Moolenaar071d4272004-06-13 20:20:40 +000016if exists("*GetTclIndent")
17 finish
18endif
19
Bram Moolenaar42eeac32005-06-29 22:40:58 +000020function s:prevnonblanknoncomment(lnum)
Bram Moolenaar071d4272004-06-13 20:20:40 +000021 let lnum = prevnonblank(a:lnum)
22 while lnum > 0
23 let line = getline(lnum)
24 if line !~ '^\s*\(#\|$\)'
25 break
26 endif
27 let lnum = prevnonblank(lnum - 1)
28 endwhile
29 return lnum
30endfunction
31
Bram Moolenaard47d5222018-12-09 20:43:55 +010032function s:ends_with_backslash(lnum)
33 let line = getline(a:lnum)
34 if line =~ '\\\s*$'
35 return 1
36 else
37 return 0
38 endif
39endfunction
40
Bram Moolenaar42eeac32005-06-29 22:40:58 +000041function s:count_braces(lnum, count_open)
42 let n_open = 0
43 let n_close = 0
44 let line = getline(a:lnum)
Bram Moolenaar0dc065e2005-07-04 22:49:24 +000045 let pattern = '[{}]'
Bram Moolenaar42eeac32005-06-29 22:40:58 +000046 let i = match(line, pattern)
47 while i != -1
Bram Moolenaar0dc065e2005-07-04 22:49:24 +000048 if synIDattr(synID(a:lnum, i + 1, 0), 'name') !~ 'tcl\%(Comment\|String\)'
Bram Moolenaar42eeac32005-06-29 22:40:58 +000049 if line[i] == '{'
Bram Moolenaar2c7a7632007-05-10 18:19:11 +000050 let n_open += 1
Bram Moolenaar42eeac32005-06-29 22:40:58 +000051 elseif line[i] == '}'
Bram Moolenaar2c7a7632007-05-10 18:19:11 +000052 if n_open > 0
53 let n_open -= 1
54 else
55 let n_close += 1
56 endif
Bram Moolenaar42eeac32005-06-29 22:40:58 +000057 endif
58 endif
59 let i = match(line, pattern, i + 1)
60 endwhile
61 return a:count_open ? n_open : n_close
62endfunction
Bram Moolenaar071d4272004-06-13 20:20:40 +000063
Bram Moolenaar42eeac32005-06-29 22:40:58 +000064function GetTclIndent()
Bram Moolenaar0dc065e2005-07-04 22:49:24 +000065 let line = getline(v:lnum)
Bram Moolenaar0dc065e2005-07-04 22:49:24 +000066
Bram Moolenaard47d5222018-12-09 20:43:55 +010067 " Get the line number of the previous non-blank or non-comment line.
Bram Moolenaar42eeac32005-06-29 22:40:58 +000068 let pnum = s:prevnonblanknoncomment(v:lnum - 1)
69 if pnum == 0
Bram Moolenaar071d4272004-06-13 20:20:40 +000070 return 0
71 endif
72
Bram Moolenaard47d5222018-12-09 20:43:55 +010073 " ..and the previous line before the previous line.
74 let pnum2 = s:prevnonblanknoncomment(pnum-1)
Bram Moolenaar0dc065e2005-07-04 22:49:24 +000075
Bram Moolenaard47d5222018-12-09 20:43:55 +010076 " Default indentation is to preserve the previous indentation.
77 let ind = indent(pnum)
78
79 " ...but if previous line introduces an open brace, then increase current line's indentation
80 if s:count_braces(pnum, 1) > 0
81 let ind += shiftwidth()
82 else
83 " Look for backslash line continuation on the previous two lines.
84 let slash1 = s:ends_with_backslash(pnum)
85 let slash2 = s:ends_with_backslash(pnum2)
86 if slash1 && !slash2
87 " If the previous line begins a line continuation.
88 let ind += shiftwidth()
89 elseif !slash1 && slash2
90 " If two lines ago was the end of a line continuation group of lines.
91 let ind -= shiftwidth()
92 endif
Bram Moolenaar42eeac32005-06-29 22:40:58 +000093 endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000094
Bram Moolenaard47d5222018-12-09 20:43:55 +010095 " If the current line begins with a closed brace, then decrease the indentation by one.
96 if line =~ '^\s*}'
97 let ind -= shiftwidth()
98 endif
99
Bram Moolenaar0dc065e2005-07-04 22:49:24 +0000100 return ind
Bram Moolenaar071d4272004-06-13 20:20:40 +0000101endfunction