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