tcl.vim 2.5 KB

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