pascal.vim 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. " Vim indent file
  2. " Language: Pascal
  3. " Maintainer: Neil Carter <n.carter@swansea.ac.uk>
  4. " Created: 2004 Jul 13
  5. " Last Change: 2021 Sep 22
  6. "
  7. " For further documentation, see https://psy.swansea.ac.uk/staff/carter/vim/
  8. if exists("b:did_indent")
  9. finish
  10. endif
  11. let b:did_indent = 1
  12. setlocal indentexpr=GetPascalIndent(v:lnum)
  13. setlocal indentkeys&
  14. setlocal indentkeys+==end;,==const,==type,==var,==begin,==repeat,==until,==for
  15. setlocal indentkeys+==program,==function,==procedure,==object,==private
  16. setlocal indentkeys+==record,==if,==else,==case
  17. let b:undo_indent = 'setlocal indentexpr< indentkeys<'
  18. if exists("*GetPascalIndent")
  19. finish
  20. endif
  21. " ________________________________________________________________
  22. function! s:GetPrevNonCommentLineNum( line_num )
  23. " Skip lines starting with a comment
  24. let SKIP_LINES = '^\s*\(\((\*\)\|\(\*\ \)\|\(\*)\)\|{\|}\)'
  25. let nline = a:line_num
  26. while nline > 0
  27. let nline = prevnonblank(nline-1)
  28. if getline(nline) !~? SKIP_LINES
  29. break
  30. endif
  31. endwhile
  32. return nline
  33. endfunction
  34. " ________________________________________________________________
  35. function! s:PurifyCode( line_num )
  36. " Strip any trailing comments and whitespace
  37. let pureline = 'TODO'
  38. return pureline
  39. endfunction
  40. " ________________________________________________________________
  41. function! GetPascalIndent( line_num )
  42. " Line 0 always goes at column 0
  43. if a:line_num == 0
  44. return 0
  45. endif
  46. let this_codeline = getline( a:line_num )
  47. " SAME INDENT
  48. " Middle of a three-part comment
  49. if this_codeline =~ '^\s*\*'
  50. return indent( a:line_num - 1)
  51. endif
  52. " COLUMN 1 ALWAYS
  53. " Last line of the program
  54. if this_codeline =~ '^\s*end\.'
  55. return 0
  56. endif
  57. " Compiler directives, allowing "(*" and "{"
  58. "if this_codeline =~ '^\s*\({\|(\*\)$\(IFDEF\|IFNDEF\|ELSE\|ENDIF\)'
  59. if this_codeline =~ '^\s*\({\|(\*\)\$'
  60. return 0
  61. endif
  62. " section headers
  63. if this_codeline =~ '^\s*\(program\|procedure\|function\|type\)\>'
  64. return 0
  65. endif
  66. " Subroutine separators, lines ending with "const" or "var"
  67. if this_codeline =~ '^\s*\((\*\ _\+\ \*)\|\(const\|var\)\)$'
  68. return 0
  69. endif
  70. " OTHERWISE, WE NEED TO LOOK FURTHER BACK...
  71. let prev_codeline_num = s:GetPrevNonCommentLineNum( a:line_num )
  72. let prev_codeline = getline( prev_codeline_num )
  73. let indnt = indent( prev_codeline_num )
  74. " INCREASE INDENT
  75. " If the PREVIOUS LINE ended in these items, always indent
  76. if prev_codeline =~ '\<\(type\|const\|var\)$'
  77. return indnt + shiftwidth()
  78. endif
  79. if prev_codeline =~ '\<repeat$'
  80. if this_codeline !~ '^\s*until\>'
  81. return indnt + shiftwidth()
  82. else
  83. return indnt
  84. endif
  85. endif
  86. if prev_codeline =~ '\<\(begin\|record\)$'
  87. if this_codeline !~ '^\s*end\>'
  88. return indnt + shiftwidth()
  89. else
  90. return indnt
  91. endif
  92. endif
  93. " If the PREVIOUS LINE ended with these items, indent if not
  94. " followed by "begin"
  95. if prev_codeline =~ '\<\(\|else\|then\|do\)$' || prev_codeline =~ ':$'
  96. if this_codeline !~ '^\s*begin\>'
  97. return indnt + shiftwidth()
  98. else
  99. " If it does start with "begin" then keep the same indent
  100. "return indnt + shiftwidth()
  101. return indnt
  102. endif
  103. endif
  104. " Inside a parameter list (i.e. a "(" without a ")"). ???? Considers
  105. " only the line before the current one. TODO: Get it working for
  106. " parameter lists longer than two lines.
  107. if prev_codeline =~ '([^)]\+$'
  108. return indnt + shiftwidth()
  109. endif
  110. " DECREASE INDENT
  111. " Lines starting with "else", but not following line ending with
  112. " "end".
  113. if this_codeline =~ '^\s*else\>' && prev_codeline !~ '\<end$'
  114. return indnt - shiftwidth()
  115. endif
  116. " Lines after a single-statement branch/loop.
  117. " Two lines before ended in "then", "else", or "do"
  118. " Previous line didn't end in "begin"
  119. let prev2_codeline_num = s:GetPrevNonCommentLineNum( prev_codeline_num )
  120. let prev2_codeline = getline( prev2_codeline_num )
  121. if prev2_codeline =~ '\<\(then\|else\|do\)$' && prev_codeline !~ '\<begin$'
  122. " If the next code line after a single statement branch/loop
  123. " starts with "end", "except" or "finally", we need an
  124. " additional unindentation.
  125. if this_codeline =~ '^\s*\(end;\|except\|finally\|\)$'
  126. " Note that we don't return from here.
  127. return indnt - 2 * shiftwidth()
  128. endif
  129. return indnt - shiftwidth()
  130. endif
  131. " Lines starting with "until" or "end". This rule must be overridden
  132. " by the one for "end" after a single-statement branch/loop. In
  133. " other words that rule should come before this one.
  134. if this_codeline =~ '^\s*\(end\|until\)\>'
  135. return indnt - shiftwidth()
  136. endif
  137. " MISCELLANEOUS THINGS TO CATCH
  138. " Most "begin"s will have been handled by now. Any remaining
  139. " "begin"s on their own line should go in column 1.
  140. if this_codeline =~ '^\s*begin$'
  141. return 0
  142. endif
  143. " ________________________________________________________________
  144. " Object/Borland Pascal/Delphi Extensions
  145. "
  146. " Note that extended-pascal is handled here, unless it is simpler to
  147. " handle them in the standard-pascal section above.
  148. " COLUMN 1 ALWAYS
  149. " section headers at start of line.
  150. if this_codeline =~ '^\s*\(interface\|implementation\|uses\|unit\)\>'
  151. return 0
  152. endif
  153. " INDENT ONCE
  154. " If the PREVIOUS LINE ended in these items, always indent.
  155. if prev_codeline =~ '^\s*\(unit\|uses\|try\|except\|finally\|private\|protected\|public\|published\)$'
  156. return indnt + shiftwidth()
  157. endif
  158. " ???? Indent "procedure" and "functions" if they appear within an
  159. " class/object definition. But that means overriding standard-pascal
  160. " rule where these words always go in column 1.
  161. " UNINDENT ONCE
  162. if this_codeline =~ '^\s*\(except\|finally\)$'
  163. return indnt - shiftwidth()
  164. endif
  165. if this_codeline =~ '^\s*\(private\|protected\|public\|published\)$'
  166. return indnt - shiftwidth()
  167. endif
  168. " If nothing changed, return same indent.
  169. return indnt
  170. endfunction