3 " Maintainer: Neil Carter <n.carter@swansea.ac.uk>
5 " Last Change: 2011 Apr 01
7 " This is version 2.0, a complete rewrite.
9 " For further documentation, see http://psy.swansea.ac.uk/staff/carter/vim/
12 if exists("b:did_indent")
17 setlocal indentexpr=GetPascalIndent(v:lnum)
19 setlocal indentkeys+==end;,==const,==type,==var,==begin,==repeat,==until,==for
20 setlocal indentkeys+==program,==function,==procedure,==object,==private
21 setlocal indentkeys+==record,==if,==else,==case
23 if exists("*GetPascalIndent")
28 function! s:GetPrevNonCommentLineNum( line_num )
30 " Skip lines starting with a comment
31 let SKIP_LINES = '^\s*\(\((\*\)\|\(\*\ \)\|\(\*)\)\|{\|}\)'
33 let nline = a:line_num
35 let nline = prevnonblank(nline-1)
36 if getline(nline) !~? SKIP_LINES
45 function! s:PurifyCode( line_num )
46 " Strip any trailing comments and whitespace
52 function! GetPascalIndent( line_num )
54 " Line 0 always goes at column 0
59 let this_codeline = getline( a:line_num )
64 " Middle of a three-part comment
65 if this_codeline =~ '^\s*\*'
66 return indent( a:line_num - 1)
72 " Last line of the program
73 if this_codeline =~ '^\s*end\.'
77 " Compiler directives, allowing "(*" and "{"
78 "if this_codeline =~ '^\s*\({\|(\*\)$\(IFDEF\|IFNDEF\|ELSE\|ENDIF\)'
79 if this_codeline =~ '^\s*\({\|(\*\)\$'
84 if this_codeline =~ '^\s*\(program\|procedure\|function\|type\)\>'
88 " Subroutine separators, lines ending with "const" or "var"
89 if this_codeline =~ '^\s*\((\*\ _\+\ \*)\|\(const\|var\)\)$'
94 " OTHERWISE, WE NEED TO LOOK FURTHER BACK...
96 let prev_codeline_num = s:GetPrevNonCommentLineNum( a:line_num )
97 let prev_codeline = getline( prev_codeline_num )
98 let indnt = indent( prev_codeline_num )
103 " If the PREVIOUS LINE ended in these items, always indent
104 if prev_codeline =~ '\<\(type\|const\|var\)$'
105 return indnt + &shiftwidth
108 if prev_codeline =~ '\<repeat$'
109 if this_codeline !~ '^\s*until\>'
110 return indnt + &shiftwidth
116 if prev_codeline =~ '\<\(begin\|record\)$'
117 if this_codeline !~ '^\s*end\>'
118 return indnt + &shiftwidth
124 " If the PREVIOUS LINE ended with these items, indent if not
125 " followed by "begin"
126 if prev_codeline =~ '\<\(\|else\|then\|do\)$' || prev_codeline =~ ':$'
127 if this_codeline !~ '^\s*begin\>'
128 return indnt + &shiftwidth
130 " If it does start with "begin" then keep the same indent
131 "return indnt + &shiftwidth
136 " Inside a parameter list (i.e. a "(" without a ")"). ???? Considers
137 " only the line before the current one. TODO: Get it working for
138 " parameter lists longer than two lines.
139 if prev_codeline =~ '([^)]\+$'
140 return indnt + &shiftwidth
146 " Lines starting with "else", but not following line ending with
148 if this_codeline =~ '^\s*else\>' && prev_codeline !~ '\<end$'
149 return indnt - &shiftwidth
152 " Lines after a single-statement branch/loop.
153 " Two lines before ended in "then", "else", or "do"
154 " Previous line didn't end in "begin"
155 let prev2_codeline_num = s:GetPrevNonCommentLineNum( prev_codeline_num )
156 let prev2_codeline = getline( prev2_codeline_num )
157 if prev2_codeline =~ '\<\(then\|else\|do\)$' && prev_codeline !~ '\<begin$'
158 " If the next code line after a single statement branch/loop
159 " starts with "end", "except" or "finally", we need an
160 " additional unindentation.
161 if this_codeline =~ '^\s*\(end;\|except\|finally\|\)$'
162 " Note that we don't return from here.
163 return indnt - &shiftwidth - &shiftwidth
165 return indnt - &shiftwidth
168 " Lines starting with "until" or "end". This rule must be overridden
169 " by the one for "end" after a single-statement branch/loop. In
170 " other words that rule should come before this one.
171 if this_codeline =~ '^\s*\(end\|until\)\>'
172 return indnt - &shiftwidth
176 " MISCELLANEOUS THINGS TO CATCH
178 " Most "begin"s will have been handled by now. Any remaining
179 " "begin"s on their own line should go in column 1.
180 if this_codeline =~ '^\s*begin$'
185 " ____________________________________________________________________
186 " Object/Borland Pascal/Delphi Extensions
188 " Note that extended-pascal is handled here, unless it is simpler to
189 " handle them in the standard-pascal section above.
194 " section headers at start of line.
195 if this_codeline =~ '^\s*\(interface\|implementation\|uses\|unit\)\>'
202 " If the PREVIOUS LINE ended in these items, always indent.
203 if prev_codeline =~ '^\s*\(unit\|uses\|try\|except\|finally\|private\|protected\|public\|published\)$'
204 return indnt + &shiftwidth
207 " ???? Indent "procedure" and "functions" if they appear within an
208 " class/object definition. But that means overriding standard-pascal
209 " rule where these words always go in column 1.
214 if this_codeline =~ '^\s*\(except\|finally\)$'
215 return indnt - &shiftwidth
218 if this_codeline =~ '^\s*\(private\|protected\|public\|published\)$'
219 return indnt - &shiftwidth
223 " ____________________________________________________________________
225 " If nothing changed, return same indent.