blob: 582d033b236b2ad32b08c3fd8edde2e3b414d9c1 [file] [log] [blame]
Bram Moolenaar9964e462007-05-05 17:54:07 +00001"------------------------------------------------------------------------------
2" Description: Vim Ada indent file
3" Language: Ada (2005)
Bram Moolenaar5c736222010-01-06 20:54:52 +01004" $Id: ada.vim 887 2008-07-08 14:29:01Z krischik $
Bram Moolenaar9964e462007-05-05 17:54:07 +00005" Copyright: Copyright (C) 2006 Martin Krischik
Bram Moolenaarc236c162008-07-13 17:41:49 +00006" Maintainer: Martin Krischik <krischik@users.sourceforge.net>
Bram Moolenaar9964e462007-05-05 17:54:07 +00007" Neil Bird <neil@fnxweb.com>
Bram Moolenaarc236c162008-07-13 17:41:49 +00008" Ned Okie <nokie@radford.edu>
Bram Moolenaar5c736222010-01-06 20:54:52 +01009" $Author: krischik $
10" $Date: 2008-07-08 16:29:01 +0200 (Di, 08 Jul 2008) $
Bram Moolenaarc236c162008-07-13 17:41:49 +000011" Version: 4.6
Bram Moolenaar5c736222010-01-06 20:54:52 +010012" $Revision: 887 $
Bram Moolenaarc236c162008-07-13 17:41:49 +000013" $HeadURL: https://gnuada.svn.sourceforge.net/svnroot/gnuada/trunk/tools/vim/indent/ada.vim $
Bram Moolenaar9964e462007-05-05 17:54:07 +000014" History: 24.05.2006 MK Unified Headers
15" 16.07.2006 MK Ada-Mode as vim-ball
16" 15.10.2006 MK Bram's suggestion for runtime integration
17" 05.11.2006 MK Bram suggested to save on spaces
Bram Moolenaarc236c162008-07-13 17:41:49 +000018" 19.09.2007 NO g: missing before ada#Comment
Bram Moolenaarcbaff5e2022-04-08 17:45:08 +010019" 2022 April: b:undo_indent added by Doug Kearns
Bram Moolenaar9964e462007-05-05 17:54:07 +000020" Help Page: ft-vim-indent
21"------------------------------------------------------------------------------
Bram Moolenaar071d4272004-06-13 20:20:40 +000022" ToDo:
23" Verify handling of multi-line exprs. and recovery upon the final ';'.
24" Correctly find comments given '"' and "" ==> " syntax.
25" Combine the two large block-indent functions into one?
Bram Moolenaar9964e462007-05-05 17:54:07 +000026"------------------------------------------------------------------------------
Bram Moolenaar071d4272004-06-13 20:20:40 +000027
28" Only load this indent file when no other was loaded.
Bram Moolenaar9964e462007-05-05 17:54:07 +000029if exists("b:did_indent") || version < 700
Bram Moolenaar071d4272004-06-13 20:20:40 +000030 finish
31endif
Bram Moolenaar9964e462007-05-05 17:54:07 +000032
Bram Moolenaarc236c162008-07-13 17:41:49 +000033let b:did_indent = 45
Bram Moolenaar071d4272004-06-13 20:20:40 +000034
35setlocal indentexpr=GetAdaIndent()
36setlocal indentkeys-=0{,0}
37setlocal indentkeys+=0=~then,0=~end,0=~elsif,0=~when,0=~exception,0=~begin,0=~is,0=~record
38
Bram Moolenaarcbaff5e2022-04-08 17:45:08 +010039let b:undo_indent = "setl inde< indk<"
40
Bram Moolenaar071d4272004-06-13 20:20:40 +000041" Only define the functions once.
42if exists("*GetAdaIndent")
43 finish
44endif
Bram Moolenaar80716072012-05-01 21:14:34 +020045let s:keepcpo= &cpo
46set cpo&vim
Bram Moolenaar071d4272004-06-13 20:20:40 +000047
Bram Moolenaar9964e462007-05-05 17:54:07 +000048if exists("g:ada_with_gnat_project_files")
49 let s:AdaBlockStart = '^\s*\(if\>\|while\>\|else\>\|elsif\>\|loop\>\|for\>.*\<\(loop\|use\)\>\|declare\>\|begin\>\|type\>.*\<is\>[^;]*$\|\(type\>.*\)\=\<record\>\|procedure\>\|function\>\|accept\>\|do\>\|task\>\|package\>\|project\>\|then\>\|when\>\|is\>\)'
50else
51 let s:AdaBlockStart = '^\s*\(if\>\|while\>\|else\>\|elsif\>\|loop\>\|for\>.*\<\(loop\|use\)\>\|declare\>\|begin\>\|type\>.*\<is\>[^;]*$\|\(type\>.*\)\=\<record\>\|procedure\>\|function\>\|accept\>\|do\>\|task\>\|package\>\|then\>\|when\>\|is\>\)'
52endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000053
Bram Moolenaar9964e462007-05-05 17:54:07 +000054" Section: s:MainBlockIndent {{{1
55"
Bram Moolenaar293ee4d2004-12-09 21:34:53 +000056" Try to find indent of the block we're in
Bram Moolenaar071d4272004-06-13 20:20:40 +000057" prev_indent = the previous line's indent
58" prev_lnum = previous line (to start looking on)
59" blockstart = expr. that indicates a possible start of this block
60" stop_at = if non-null, if a matching line is found, gives up!
61" No recursive previous block analysis: simply look for a valid line
62" with a lesser or equal indent than we currently (on prev_lnum) have.
63" This shouldn't work as well as it appears to with lines that are currently
64" nowhere near the correct indent (e.g., start of line)!
65" Seems to work OK as it 'starts' with the indent of the /previous/ line.
Bram Moolenaar9964e462007-05-05 17:54:07 +000066function s:MainBlockIndent (prev_indent, prev_lnum, blockstart, stop_at)
Bram Moolenaar071d4272004-06-13 20:20:40 +000067 let lnum = a:prev_lnum
Bram Moolenaarc236c162008-07-13 17:41:49 +000068 let line = substitute( getline(lnum), g:ada#Comment, '', '' )
Bram Moolenaar071d4272004-06-13 20:20:40 +000069 while lnum > 1
70 if a:stop_at != '' && line =~ '^\s*' . a:stop_at && indent(lnum) < a:prev_indent
Bram Moolenaarc9b4b052006-04-30 18:54:39 +000071 return a:prev_indent
Bram Moolenaar071d4272004-06-13 20:20:40 +000072 elseif line =~ '^\s*' . a:blockstart
Bram Moolenaarc9b4b052006-04-30 18:54:39 +000073 let ind = indent(lnum)
74 if ind < a:prev_indent
75 return ind
76 endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000077 endif
78
79 let lnum = prevnonblank(lnum - 1)
80 " Get previous non-blank/non-comment-only line
81 while 1
Bram Moolenaarc236c162008-07-13 17:41:49 +000082 let line = substitute( getline(lnum), g:ada#Comment, '', '' )
Bram Moolenaarc9b4b052006-04-30 18:54:39 +000083 if line !~ '^\s*$' && line !~ '^\s*#'
84 break
85 endif
86 let lnum = prevnonblank(lnum - 1)
87 if lnum <= 0
88 return a:prev_indent
89 endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000090 endwhile
91 endwhile
92 " Fallback - just move back one
Bram Moolenaar3ec574f2017-06-13 18:12:01 +020093 return a:prev_indent - shiftwidth()
Bram Moolenaar9964e462007-05-05 17:54:07 +000094endfunction MainBlockIndent
Bram Moolenaar071d4272004-06-13 20:20:40 +000095
Bram Moolenaar9964e462007-05-05 17:54:07 +000096" Section: s:EndBlockIndent {{{1
97"
Bram Moolenaar071d4272004-06-13 20:20:40 +000098" Try to find indent of the block we're in (and about to complete),
99" including handling of nested blocks. Works on the 'end' of a block.
100" prev_indent = the previous line's indent
101" prev_lnum = previous line (to start looking on)
102" blockstart = expr. that indicates a possible start of this block
103" blockend = expr. that indicates a possible end of this block
104function s:EndBlockIndent( prev_indent, prev_lnum, blockstart, blockend )
105 let lnum = a:prev_lnum
106 let line = getline(lnum)
107 let ends = 0
108 while lnum > 1
109 if getline(lnum) =~ '^\s*' . a:blockstart
110 let ind = indent(lnum)
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000111 if ends <= 0
112 if ind < a:prev_indent
Bram Moolenaar071d4272004-06-13 20:20:40 +0000113 return ind
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000114 endif
115 else
116 let ends = ends - 1
Bram Moolenaar071d4272004-06-13 20:20:40 +0000117 endif
118 elseif getline(lnum) =~ '^\s*' . a:blockend
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000119 let ends = ends + 1
Bram Moolenaar071d4272004-06-13 20:20:40 +0000120 endif
121
122 let lnum = prevnonblank(lnum - 1)
123 " Get previous non-blank/non-comment-only line
124 while 1
125 let line = getline(lnum)
Bram Moolenaarc236c162008-07-13 17:41:49 +0000126 let line = substitute( line, g:ada#Comment, '', '' )
Bram Moolenaar071d4272004-06-13 20:20:40 +0000127 if line !~ '^\s*$'
128 break
129 endif
130 let lnum = prevnonblank(lnum - 1)
131 if lnum <= 0
132 return a:prev_indent
133 endif
134 endwhile
135 endwhile
136 " Fallback - just move back one
Bram Moolenaar3ec574f2017-06-13 18:12:01 +0200137 return a:prev_indent - shiftwidth()
Bram Moolenaar9964e462007-05-05 17:54:07 +0000138endfunction EndBlockIndent
Bram Moolenaar071d4272004-06-13 20:20:40 +0000139
Bram Moolenaar9964e462007-05-05 17:54:07 +0000140" Section: s:StatementIndent {{{1
141"
Bram Moolenaar293ee4d2004-12-09 21:34:53 +0000142" Return indent of previous statement-start
Bram Moolenaar071d4272004-06-13 20:20:40 +0000143" (after we've indented due to multi-line statements).
144" This time, we start searching on the line *before* the one given (which is
145" the end of a statement - we want the previous beginning).
146function s:StatementIndent( current_indent, prev_lnum )
147 let lnum = a:prev_lnum
148 while lnum > 0
149 let prev_lnum = lnum
150 let lnum = prevnonblank(lnum - 1)
151 " Get previous non-blank/non-comment-only line
152 while 1
Bram Moolenaarc236c162008-07-13 17:41:49 +0000153 let line = substitute( getline(lnum), g:ada#Comment, '', '' )
Bram Moolenaar91e15e12014-09-19 22:38:48 +0200154
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000155 if line !~ '^\s*$' && line !~ '^\s*#'
156 break
157 endif
158 let lnum = prevnonblank(lnum - 1)
159 if lnum <= 0
160 return a:current_indent
161 endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000162 endwhile
163 " Leave indent alone if our ';' line is part of a ';'-delineated
164 " aggregate (e.g., procedure args.) or first line after a block start.
165 if line =~ s:AdaBlockStart || line =~ '(\s*$'
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000166 return a:current_indent
Bram Moolenaar071d4272004-06-13 20:20:40 +0000167 endif
168 if line !~ '[.=(]\s*$'
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000169 let ind = indent(prev_lnum)
170 if ind < a:current_indent
171 return ind
172 endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000173 endif
174 endwhile
175 " Fallback - just use current one
176 return a:current_indent
Bram Moolenaar9964e462007-05-05 17:54:07 +0000177endfunction StatementIndent
Bram Moolenaar071d4272004-06-13 20:20:40 +0000178
179
Bram Moolenaar9964e462007-05-05 17:54:07 +0000180" Section: GetAdaIndent {{{1
181"
Bram Moolenaar071d4272004-06-13 20:20:40 +0000182" Find correct indent of a new line based upon what went before
Bram Moolenaar9964e462007-05-05 17:54:07 +0000183"
Bram Moolenaar071d4272004-06-13 20:20:40 +0000184function GetAdaIndent()
185 " Find a non-blank line above the current line.
186 let lnum = prevnonblank(v:lnum - 1)
187 let ind = indent(lnum)
188 let package_line = 0
189
190 " Get previous non-blank/non-comment-only/non-cpp line
191 while 1
Bram Moolenaar9964e462007-05-05 17:54:07 +0000192 let line = substitute( getline(lnum), g:ada#Comment, '', '' )
Bram Moolenaar071d4272004-06-13 20:20:40 +0000193 if line !~ '^\s*$' && line !~ '^\s*#'
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000194 break
Bram Moolenaar071d4272004-06-13 20:20:40 +0000195 endif
196 let lnum = prevnonblank(lnum - 1)
197 if lnum <= 0
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000198 return ind
Bram Moolenaar071d4272004-06-13 20:20:40 +0000199 endif
200 endwhile
201
202 " Get default indent (from prev. line)
203 let ind = indent(lnum)
Bram Moolenaar293ee4d2004-12-09 21:34:53 +0000204 let initind = ind
Bram Moolenaar071d4272004-06-13 20:20:40 +0000205
206 " Now check what's on the previous line
207 if line =~ s:AdaBlockStart || line =~ '(\s*$'
208 " Check for false matches to AdaBlockStart
209 let false_match = 0
210 if line =~ '^\s*\(procedure\|function\|package\)\>.*\<is\s*new\>'
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000211 " Generic instantiation
212 let false_match = 1
Bram Moolenaar071d4272004-06-13 20:20:40 +0000213 elseif line =~ ')\s*;\s*$' || line =~ '^\([^(]*([^)]*)\)*[^(]*;\s*$'
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000214 " forward declaration
215 let false_match = 1
Bram Moolenaar071d4272004-06-13 20:20:40 +0000216 endif
217 " Move indent in
218 if ! false_match
Bram Moolenaar3ec574f2017-06-13 18:12:01 +0200219 let ind = ind + shiftwidth()
Bram Moolenaar071d4272004-06-13 20:20:40 +0000220 endif
221 elseif line =~ '^\s*\(case\|exception\)\>'
222 " Move indent in twice (next 'when' will move back)
Bram Moolenaar3ec574f2017-06-13 18:12:01 +0200223 let ind = ind + 2 * shiftwidth()
Bram Moolenaar071d4272004-06-13 20:20:40 +0000224 elseif line =~ '^\s*end\s*record\>'
Bram Moolenaar6c391a72021-09-09 21:55:11 +0200225 " Move indent back to tallying 'type' preceding the 'record'.
Bram Moolenaar071d4272004-06-13 20:20:40 +0000226 " Allow indent to be equal to 'end record's.
Bram Moolenaar3ec574f2017-06-13 18:12:01 +0200227 let ind = s:MainBlockIndent( ind+shiftwidth(), lnum, 'type\>', '' )
Bram Moolenaar071d4272004-06-13 20:20:40 +0000228 elseif line =~ '\(^\s*new\>.*\)\@<!)\s*[;,]\s*$'
229 " Revert to indent of line that started this parenthesis pair
230 exe lnum
231 exe 'normal! $F)%'
232 if getline('.') =~ '^\s*('
Bram Moolenaarc236c162008-07-13 17:41:49 +0000233 " Dire layout - use previous indent (could check for g:ada#Comment here)
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000234 let ind = indent( prevnonblank( line('.')-1 ) )
Bram Moolenaar071d4272004-06-13 20:20:40 +0000235 else
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000236 let ind = indent('.')
Bram Moolenaar071d4272004-06-13 20:20:40 +0000237 endif
238 exe v:lnum
239 elseif line =~ '[.=(]\s*$'
240 " A statement continuation - move in one
Bram Moolenaar3ec574f2017-06-13 18:12:01 +0200241 let ind = ind + shiftwidth()
Bram Moolenaar071d4272004-06-13 20:20:40 +0000242 elseif line =~ '^\s*new\>'
243 " Multiple line generic instantiation ('package blah is\nnew thingy')
Bram Moolenaar3ec574f2017-06-13 18:12:01 +0200244 let ind = s:StatementIndent( ind - shiftwidth(), lnum )
Bram Moolenaar071d4272004-06-13 20:20:40 +0000245 elseif line =~ ';\s*$'
Bram Moolenaar293ee4d2004-12-09 21:34:53 +0000246 " Statement end (but not 'end' ) - try to find current statement-start indent
Bram Moolenaar071d4272004-06-13 20:20:40 +0000247 let ind = s:StatementIndent( ind, lnum )
248 endif
249
250 " Check for potential argument list on next line
251 let continuation = (line =~ '[A-Za-z0-9_]\s*$')
252
253
254 " Check current line; search for simplistic matching start-of-block
255 let line = getline(v:lnum)
256 if line =~ '^\s*#'
257 " Start of line for ada-pp
258 let ind = 0
259 elseif continuation && line =~ '^\s*('
Bram Moolenaar293ee4d2004-12-09 21:34:53 +0000260 " Don't do this if we've already indented due to the previous line
261 if ind == initind
Bram Moolenaar3ec574f2017-06-13 18:12:01 +0200262 let ind = ind + shiftwidth()
Bram Moolenaar293ee4d2004-12-09 21:34:53 +0000263 endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000264 elseif line =~ '^\s*\(begin\|is\)\>'
265 let ind = s:MainBlockIndent( ind, lnum, '\(procedure\|function\|declare\|package\|task\)\>', 'begin\>' )
266 elseif line =~ '^\s*record\>'
Bram Moolenaar3ec574f2017-06-13 18:12:01 +0200267 let ind = s:MainBlockIndent( ind, lnum, 'type\>\|for\>.*\<use\>', '' ) + shiftwidth()
Bram Moolenaar071d4272004-06-13 20:20:40 +0000268 elseif line =~ '^\s*\(else\|elsif\)\>'
269 let ind = s:MainBlockIndent( ind, lnum, 'if\>', '' )
270 elseif line =~ '^\s*when\>'
271 " Align 'when' one /in/ from matching block start
Bram Moolenaar3ec574f2017-06-13 18:12:01 +0200272 let ind = s:MainBlockIndent( ind, lnum, '\(case\|exception\)\>', '' ) + shiftwidth()
Bram Moolenaar071d4272004-06-13 20:20:40 +0000273 elseif line =~ '^\s*end\>\s*\<if\>'
274 " End of if statements
275 let ind = s:EndBlockIndent( ind, lnum, 'if\>', 'end\>\s*\<if\>' )
276 elseif line =~ '^\s*end\>\s*\<loop\>'
277 " End of loops
278 let ind = s:EndBlockIndent( ind, lnum, '\(\(while\|for\)\>.*\)\?\<loop\>', 'end\>\s*\<loop\>' )
279 elseif line =~ '^\s*end\>\s*\<record\>'
280 " End of records
281 let ind = s:EndBlockIndent( ind, lnum, '\(type\>.*\)\=\<record\>', 'end\>\s*\<record\>' )
282 elseif line =~ '^\s*end\>\s*\<procedure\>'
283 " End of procedures
284 let ind = s:EndBlockIndent( ind, lnum, 'procedure\>.*\<is\>', 'end\>\s*\<procedure\>' )
285 elseif line =~ '^\s*end\>\s*\<case\>'
286 " End of case statement
287 let ind = s:EndBlockIndent( ind, lnum, 'case\>.*\<is\>', 'end\>\s*\<case\>' )
288 elseif line =~ '^\s*end\>'
289 " General case for end
Bram Moolenaar293ee4d2004-12-09 21:34:53 +0000290 let ind = s:MainBlockIndent( ind, lnum, '\(if\|while\|for\|loop\|accept\|begin\|record\|case\|exception\|package\)\>', '' )
Bram Moolenaar071d4272004-06-13 20:20:40 +0000291 elseif line =~ '^\s*exception\>'
292 let ind = s:MainBlockIndent( ind, lnum, 'begin\>', '' )
293 elseif line =~ '^\s*then\>'
294 let ind = s:MainBlockIndent( ind, lnum, 'if\>', '' )
295 endif
296
297 return ind
Bram Moolenaar9964e462007-05-05 17:54:07 +0000298endfunction GetAdaIndent
Bram Moolenaar071d4272004-06-13 20:20:40 +0000299
Bram Moolenaar9a7224b2012-04-30 15:56:52 +0200300let &cpo = s:keepcpo
301unlet s:keepcpo
302
Bram Moolenaar9964e462007-05-05 17:54:07 +0000303finish " 1}}}
304
305"------------------------------------------------------------------------------
306" Copyright (C) 2006 Martin Krischik
307"
308" Vim is Charityware - see ":help license" or uganda.txt for licence details.
309"------------------------------------------------------------------------------
310" vim: textwidth=78 wrap tabstop=8 shiftwidth=3 softtabstop=3 noexpandtab
311" vim: foldmethod=marker