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