xref: /vim-8.2.3635/runtime/indent/pascal.vim (revision 0e4d877e)
1" Vim indent file
2" Language:    Pascal
3" Maintainer:  Neil Carter <[email protected]>
4" Created:     2004 Jul 13
5" Last Change: 2005 Jun 07
6" TODO: Reduce indentation on line after a statement that flowed across
7" two lines (e.g. parameter list closed on second line). Also, increase
8" indent of a becomes-statement that flows onto second line.
9
10" Only load this indent file when no other was loaded.
11if exists("b:did_indent")
12   finish
13endif
14let b:did_indent = 1
15
16setlocal indentexpr=GetPascalIndent(v:lnum)
17" Appending an & to an option sets it to its default value.
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
23if exists("*GetPascalIndent")
24	finish
25endif
26
27
28function s:GetPrevLineNum( line_num )
29
30	" Skip over comments and conditional directives
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"	call input( "nline = ".nline )
42
43	return nline
44
45endfunction
46
47
48function! GetPascalIndent( line_num )
49	if a:line_num == 0
50		return 0
51	endif
52
53	" If in the middle of a three-part comment
54	if getline( a:line_num ) =~ '^\s*\*\ '
55		return indent( a:line_num )
56	endif
57
58	" We have to subtract one to start on the line before the current
59	" one. Otherwise, prevnonblank() returns the current line!
60	let prev_line_num = s:GetPrevLineNum( a:line_num )
61	let prev_line = getline( prev_line_num )
62	let indnt = indent( prev_line_num )
63
64	let this_line = getline( a:line_num )
65
66	" At the start of a block, we have to indent the newly-created line
67	" based on the previous line.
68	" =~ means matches a regular expression
69	" a question mark after =~ means ignore case (# means match case)
70	" const, type, var should always appear at the start of a line, but
71	" begin can appear anywhere in the line.
72	" if one of the following keywords appear in the previous line with
73	" nothing before it but optional whitespace, and nothing after it.
74	" Has to be end of line at end to show this is not a routine
75	" parameter list. Otherwise, you'd end up with cascading vars.
76
77	" These words appear alone on a line (apart from whitespace).
78	if prev_line =~ '^\s*\(const\|var\|begin\|repeat\|private\)$'
79		" Place an & before an option to obtain its value.
80		let indnt = indnt + &shiftwidth
81	endif
82
83	" Words preceded by optional whitespace and followed by anything.
84	if prev_line =~ '^\s*\(for\|if\|else\|case\)'
85		" Place an & before an option to obtain its value.
86		let indnt = indnt + &shiftwidth
87		" if this is a multistatement block then we need to align the
88		" begin with the previous line.
89		if this_line =~ '^\s*begin'
90			let indnt = indnt - &shiftwidth
91		endif
92	endif
93	" These words may have text before them on the line (hence the .*).
94	if prev_line =~ '^.*\s*\<\(object\|record\)\>$'
95		let indnt = indnt + &shiftwidth
96	endif
97	" If we have opened a bracket and the contents spills over one line,
98	" then indent one level beyond the bracket's first line. RE = an
99	" opening bracket followed by any amount of anything other than a
100	" closing bracket and then the end-of-line. If we didn't include the
101	" end of line, this RE would match even closed brackets, since it
102	" would match everything up to the closing bracket.
103	" This test isn't clever enough to handle brackets inside strings or
104	" comments.
105	if prev_line =~ '([^*][^)]*$'
106		let indnt = indnt + &shiftwidth
107	endif
108
109	" If we just closed a bracket that started on a previous line, then
110	" unindent.
111	if prev_line =~ '^[^(]*[^*])'
112		let indnt = indnt - &shiftwidth
113	endif
114
115	" At the end of a block, we have to unindent both the current line
116	" (the 'end;' for instance) and the newly-created line.
117	if this_line =~ '^\s*\(end;\|until\|else\)'
118		let indnt = indnt - &shiftwidth
119	endif
120
121	" Keywords that always appear at the start of a line.
122	" Problem is that function and procedure keywords should be indented
123	" if within a class declaration.
124	if this_line =~ '^\s*\<type\|uses\|$IFDEF\|$ENDIF\|procedure\|function\>'
125		let indnt = 0
126	endif
127	if prev_line =~ '^\s*\<type\|uses\>'
128		let indnt = &shiftwidth
129	endif
130
131	" Put conditional compile directives on first column.
132	if this_line =~ '^\s*{\$'
133		let indnt = 0
134	endif
135
136	return indnt
137endfunction
138
139" TODO: end; should align with the previous (begin/record/object/else).
140" "else begin" is the only case where begin does not appear at the start
141" of the line.
142
143" TODO: Don't align with {$IFDEF}
144
145"Example from vb.vim
146" regular expression match, case insensitive
147"if previous_line =~?
148" start of line, zero or more whitespace
149"'^\s*
150" start of word
151"\<
152"
153"\(
154"	begin\|
155"	\%(
156"		\%(
157"			private\|public\|friend
158"		\)
159"		\s\+
160"	\)
161"	zero or more of the previous atom
162"	\=
163"	\%(
164"		function\|sub\|property
165"	\)
166"	\|select\|case\|default\|if
167"\>
168"	.\{-}\<then\>\s*$\|else\|elseif\|do\|for\|while\|enum\|with
169"\)
170" end of word
171"\>'
172"	let ind = ind + &sw
173"endif
174