fork for IVI
[profile/ivi/vim.git] / runtime / indent / pascal.vim
1 " Vim indent file
2 " Language:    Pascal
3 " Maintainer:  Neil Carter <n.carter@swansea.ac.uk>
4 " Created:     2004 Jul 13
5 " Last Change: 2011 Apr 01
6 "
7 " This is version 2.0, a complete rewrite.
8 "
9 " For further documentation, see http://psy.swansea.ac.uk/staff/carter/vim/
10
11
12 if exists("b:did_indent")
13         finish
14 endif
15 let b:did_indent = 1
16
17 setlocal indentexpr=GetPascalIndent(v:lnum)
18 setlocal indentkeys&
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
22
23 if exists("*GetPascalIndent")
24         finish
25 endif
26
27
28 function! s:GetPrevNonCommentLineNum( line_num )
29
30         " Skip lines starting with a comment
31         let SKIP_LINES = '^\s*\(\((\*\)\|\(\*\ \)\|\(\*)\)\|{\|}\)'
32
33         let nline = a:line_num
34         while nline > 0
35                 let nline = prevnonblank(nline-1)
36                 if getline(nline) !~? SKIP_LINES
37                         break
38                 endif
39         endwhile
40
41         return nline
42 endfunction
43
44
45 function! s:PurifyCode( line_num )
46         " Strip any trailing comments and whitespace
47         let pureline = 'TODO'
48         return pureline
49 endfunction
50
51
52 function! GetPascalIndent( line_num )
53
54         " Line 0 always goes at column 0
55         if a:line_num == 0
56                 return 0
57         endif
58
59         let this_codeline = getline( a:line_num )
60
61
62         " SAME INDENT
63
64         " Middle of a three-part comment
65         if this_codeline =~ '^\s*\*'
66                 return indent( a:line_num - 1)
67         endif
68
69
70         " COLUMN 1 ALWAYS
71
72         " Last line of the program
73         if this_codeline =~ '^\s*end\.'
74                 return 0
75         endif
76
77         " Compiler directives, allowing "(*" and "{"
78         "if this_codeline =~ '^\s*\({\|(\*\)$\(IFDEF\|IFNDEF\|ELSE\|ENDIF\)'
79         if this_codeline =~ '^\s*\({\|(\*\)\$'
80                 return 0
81         endif
82
83         " section headers
84         if this_codeline =~ '^\s*\(program\|procedure\|function\|type\)\>'
85                 return 0
86         endif
87
88         " Subroutine separators, lines ending with "const" or "var"
89         if this_codeline =~ '^\s*\((\*\ _\+\ \*)\|\(const\|var\)\)$'
90                 return 0
91         endif
92
93
94         " OTHERWISE, WE NEED TO LOOK FURTHER BACK...
95
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 )
99
100
101         " INCREASE INDENT
102
103         " If the PREVIOUS LINE ended in these items, always indent
104         if prev_codeline =~ '\<\(type\|const\|var\)$'
105                 return indnt + &shiftwidth
106         endif
107
108         if prev_codeline =~ '\<repeat$'
109                 if this_codeline !~ '^\s*until\>'
110                         return indnt + &shiftwidth
111                 else
112                         return indnt
113                 endif
114         endif
115
116         if prev_codeline =~ '\<\(begin\|record\)$'
117                 if this_codeline !~ '^\s*end\>'
118                         return indnt + &shiftwidth
119                 else
120                         return indnt
121                 endif
122         endif
123
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
129                 else
130                         " If it does start with "begin" then keep the same indent
131                         "return indnt + &shiftwidth
132                         return indnt
133                 endif
134         endif
135
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
141         endif
142
143
144         " DECREASE INDENT
145
146         " Lines starting with "else", but not following line ending with
147         " "end".
148         if this_codeline =~ '^\s*else\>' && prev_codeline !~ '\<end$'
149                 return indnt - &shiftwidth
150         endif
151
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
164                 endif
165                 return indnt - &shiftwidth
166         endif
167
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
173         endif
174
175
176         " MISCELLANEOUS THINGS TO CATCH
177
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$'
181                 return 0
182         endif
183
184
185 " ____________________________________________________________________
186 " Object/Borland Pascal/Delphi Extensions
187 "
188 " Note that extended-pascal is handled here, unless it is simpler to
189 " handle them in the standard-pascal section above.
190
191
192         " COLUMN 1 ALWAYS
193
194         " section headers at start of line.
195         if this_codeline =~ '^\s*\(interface\|implementation\|uses\|unit\)\>'
196                 return 0
197         endif
198
199
200         " INDENT ONCE
201
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
205         endif
206
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.
210
211
212         " UNINDENT ONCE
213
214         if this_codeline =~ '^\s*\(except\|finally\)$'
215                 return indnt - &shiftwidth
216         endif
217
218         if this_codeline =~ '^\s*\(private\|protected\|public\|published\)$'
219                 return indnt - &shiftwidth
220         endif
221
222
223 " ____________________________________________________________________
224
225         " If nothing changed, return same indent.
226         return indnt
227 endfunction
228