1" Vim indent file 2" Language: Tcl 3" Previous Maintainer: Nikolai Weibull <[email protected]> 4" Latest Update: Chris Heithoff <[email protected]> 5" Latest Revision: 2018-12-05 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 16if exists("*GetTclIndent") 17 finish 18endif 19 20function s:prevnonblanknoncomment(lnum) 21 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 32function 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 41function s:count_braces(lnum, count_open) 42 let n_open = 0 43 let n_close = 0 44 let line = getline(a:lnum) 45 let pattern = '[{}]' 46 let i = match(line, pattern) 47 while i != -1 48 if synIDattr(synID(a:lnum, i + 1, 0), 'name') !~ 'tcl\%(Comment\|String\)' 49 if line[i] == '{' 50 let n_open += 1 51 elseif line[i] == '}' 52 if n_open > 0 53 let n_open -= 1 54 else 55 let n_close += 1 56 endif 57 endif 58 endif 59 let i = match(line, pattern, i + 1) 60 endwhile 61 return a:count_open ? n_open : n_close 62endfunction 63 64function GetTclIndent() 65 let line = getline(v:lnum) 66 67 " Get the line number of the previous non-blank or non-comment line. 68 let pnum = s:prevnonblanknoncomment(v:lnum - 1) 69 if pnum == 0 70 return 0 71 endif 72 73 " ..and the previous line before the previous line. 74 let pnum2 = s:prevnonblanknoncomment(pnum-1) 75 76 " 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 93 endif 94 95 " 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 100 return ind 101endfunction 102