blob: b67071c9e5530d5cb58850ee923b403085dd68dc [file] [log] [blame]
Bram Moolenaar0e4d8772005-06-07 21:12:49 +00001" Vim indent file
2" Language: Pascal
3" Maintainer: Neil Carter <n.carter@swansea.ac.uk>
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