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