1" Vim indent file 2" Language: Pascal 3" Maintainer: Neil Carter <n.carter@swansea.ac.uk> 4" Created: 2004 Jul 13 5" Last Change: 2005 Jul 05 6 7 8if exists("b:did_indent") 9 finish 10endif 11let b:did_indent = 1 12 13setlocal indentexpr=GetPascalIndent(v:lnum) 14setlocal indentkeys& 15setlocal indentkeys+==end;,==const,==type,==var,==begin,==repeat,==until,==for 16setlocal indentkeys+==program,==function,==procedure,==object,==private 17setlocal indentkeys+==record,==if,==else,==case 18 19if exists("*GetPascalIndent") 20 finish 21endif 22 23 24function! s:GetPrevNonCommentLineNum( line_num ) 25 26 " Skip lines starting with a comment 27 let SKIP_LINES = '^\s*\(\((\*\)\|\(\*\ \)\|\(\*)\)\|{\|}\)' 28 29 let nline = a:line_num 30 while nline > 0 31 let nline = prevnonblank(nline-1) 32 if getline(nline) !~? SKIP_LINES 33 break 34 endif 35 endwhile 36 37 return nline 38endfunction 39 40 41function! GetPascalIndent( line_num ) 42 " Line 0 always goes at column 0 43 if a:line_num == 0 44 return 0 45 endif 46 47 let this_codeline = getline( a:line_num ) 48 49 " If in the middle of a three-part comment 50 if this_codeline =~ '^\s*\*' 51 return indent( a:line_num ) 52 endif 53 54 let prev_codeline_num = s:GetPrevNonCommentLineNum( a:line_num ) 55 let prev_codeline = getline( prev_codeline_num ) 56 let indnt = indent( prev_codeline_num ) 57 58 " Compiler directives should always go in column zero. 59 if this_codeline =~ '^\s*{\(\$IFDEF\|\$ELSE\|\$ENDIF\)' 60 return 0 61 endif 62 63 " These items have nothing before or after (not even a comment), and 64 " go on column 0. Make sure that the ^\s* is followed by \( to make 65 " ORs work properly, and not include the start of line (this must 66 " always appear). 67 " The bracketed expression with the underline is a routine 68 " separator. This is one case where we do indent comment lines. 69 if this_codeline =~ '^\s*\((\*\ _\+\ \*)\|\<\(const\|var\)\>\)$' 70 return 0 71 endif 72 73 " These items may have text after them, and go on column 0 (in most 74 " cases). The problem is that "function" and "procedure" keywords 75 " should be indented if within a class declaration. 76 if this_codeline =~ '^\s*\<\(program\|type\|uses\|procedure\|function\)\>' 77 return 0 78 endif 79 80 " BEGIN 81 " If the begin does not come after "if", "for", or "else", then it 82 " goes in column 0 83 if this_codeline =~ '^\s*begin\>' && prev_codeline !~ '^\s*\<\(if\|for\|else\)\>' 84 return 0 85 endif 86 87 " These keywords are indented once only. 88 if this_codeline =~ '^\s*\<\(private\)\>' 89 return &shiftwidth 90 endif 91 92 " If the PREVIOUS LINE contained these items, the current line is 93 " always indented once. 94 if prev_codeline =~ '^\s*\<\(type\|uses\)\>' 95 return &shiftwidth 96 endif 97 98 " These keywords are indented once only. Possibly surrounded by 99 " other chars. 100 if this_codeline =~ '^.\+\<\(object\|record\)\>' 101 return &shiftwidth 102 endif 103 104 " If the previous line was indenting... 105 if prev_codeline =~ '^\s*\<\(for\|if\|case\|else\|end\ else\)\>' 106 " then indent. 107 let indnt = indnt + &shiftwidth 108 " BUT... if this is the start of a multistatement block then we 109 " need to align the begin with the previous line. 110 if this_codeline =~ '^\s*begin\>' 111 return indnt - &shiftwidth 112 endif 113 114 " We also need to keep the indentation level constant if the 115 " whole if-then statement was on one line. 116 if prev_codeline =~ '\<then\>.\+' 117 let indnt = indnt - &shiftwidth 118 endif 119 endif 120 121 " PREVIOUS-LINE BEGIN 122 " If the previous line was an indenting keyword then indent once... 123 if prev_codeline =~ '^\s*\<\(const\|var\|begin\|repeat\|private\)\>' 124 " But only if this is another var in a list. 125 if this_codeline !~ '^\s*var\>' 126 return indnt + &shiftwidth 127 endif 128 endif 129 130 " PREVIOUS-LINE BEGIN 131 " Indent code after a case statement begin 132 if prev_codeline =~ '\:\ begin\>' 133 return indnt + &shiftwidth 134 endif 135 136 " These words may have text before them on the line (hence the .*) 137 " but are followed by nothing. Always indent once only. 138 if prev_codeline =~ '^\(.*\|\s*\)\<\(object\|record\)\>$' 139 return indnt + &shiftwidth 140 endif 141 142 " If we just closed a bracket that started on a previous line, then 143 " unindent. But don't return yet -- we need to check for further 144 " unindentation (for end/until/else) 145 if prev_codeline =~ '^[^(]*[^*])' 146 let indnt = indnt - &shiftwidth 147 endif 148 149 " At the end of a block, we have to unindent both the current line 150 " (the "end" for instance) and the newly-created line. 151 if this_codeline =~ '^\s*\<\(end\|until\|else\)\>' 152 return indnt - &shiftwidth 153 endif 154 155 " If we have opened a bracket and it continues over one line, 156 " then indent once. 157 " 158 " RE = an opening bracket followed by any amount of anything other 159 " than a closing bracket and then the end-of-line. 160 " 161 " If we didn't include the end of line, this RE would match even 162 " closed brackets, since it would match everything up to the closing 163 " bracket. 164 " 165 " This test isn't clever enough to handle brackets inside strings or 166 " comments. 167 if prev_codeline =~ '([^*]\=[^)]*$' 168 return indnt + &shiftwidth 169 endif 170 171 return indnt 172endfunction 173 174