Bram Moolenaar | 0e4d877 | 2005-06-07 21:12:49 +0000 | [diff] [blame] | 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 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. |
| 11 | if exists("b:did_indent") |
| 12 | finish |
| 13 | endif |
| 14 | let b:did_indent = 1 |
| 15 | |
| 16 | setlocal indentexpr=GetPascalIndent(v:lnum) |
| 17 | " Appending an & to an option sets it to its default value. |
| 18 | setlocal indentkeys& |
| 19 | setlocal indentkeys+=~end;,=~const,=~type,=~var,=~begin,=~repeat,=~until,=~for |
| 20 | setlocal indentkeys+=~program,=~function,=~procedure,=~object,=~private |
| 21 | setlocal indentkeys+=~record,=~if,=~else,=~case |
| 22 | |
| 23 | if exists("*GetPascalIndent") |
| 24 | finish |
| 25 | endif |
| 26 | |
| 27 | |
| 28 | function 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 | |
| 45 | endfunction |
| 46 | |
| 47 | |
| 48 | function! 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 |
| 137 | endfunction |
| 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 |