blob: 03fbaa3a18857d27885313791daaf7978f85ebf7 [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 Moolenaar9964e462007-05-05 17:54:07 +000019" Help Page: ft-vim-indent
20"------------------------------------------------------------------------------
Bram Moolenaar071d4272004-06-13 20:20:40 +000021" ToDo:
22" Verify handling of multi-line exprs. and recovery upon the final ';'.
23" Correctly find comments given '"' and "" ==> " syntax.
24" Combine the two large block-indent functions into one?
Bram Moolenaar9964e462007-05-05 17:54:07 +000025"------------------------------------------------------------------------------
Bram Moolenaar071d4272004-06-13 20:20:40 +000026
27" Only load this indent file when no other was loaded.
Bram Moolenaar9964e462007-05-05 17:54:07 +000028if exists("b:did_indent") || version < 700
Bram Moolenaar071d4272004-06-13 20:20:40 +000029 finish
30endif
Bram Moolenaar9964e462007-05-05 17:54:07 +000031
Bram Moolenaarc236c162008-07-13 17:41:49 +000032let b:did_indent = 45
Bram Moolenaar071d4272004-06-13 20:20:40 +000033
34setlocal indentexpr=GetAdaIndent()
35setlocal indentkeys-=0{,0}
36setlocal indentkeys+=0=~then,0=~end,0=~elsif,0=~when,0=~exception,0=~begin,0=~is,0=~record
37
38" Only define the functions once.
39if exists("*GetAdaIndent")
40 finish
41endif
Bram Moolenaar80716072012-05-01 21:14:34 +020042let s:keepcpo= &cpo
43set cpo&vim
Bram Moolenaar071d4272004-06-13 20:20:40 +000044
Bram Moolenaar9964e462007-05-05 17:54:07 +000045if exists("g:ada_with_gnat_project_files")
46 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\>\)'
47else
48 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\>\)'
49endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000050
Bram Moolenaar9964e462007-05-05 17:54:07 +000051" Section: s:MainBlockIndent {{{1
52"
Bram Moolenaar293ee4d2004-12-09 21:34:53 +000053" Try to find indent of the block we're in
Bram Moolenaar071d4272004-06-13 20:20:40 +000054" prev_indent = the previous line's indent
55" prev_lnum = previous line (to start looking on)
56" blockstart = expr. that indicates a possible start of this block
57" stop_at = if non-null, if a matching line is found, gives up!
58" No recursive previous block analysis: simply look for a valid line
59" with a lesser or equal indent than we currently (on prev_lnum) have.
60" This shouldn't work as well as it appears to with lines that are currently
61" nowhere near the correct indent (e.g., start of line)!
62" Seems to work OK as it 'starts' with the indent of the /previous/ line.
Bram Moolenaar9964e462007-05-05 17:54:07 +000063function s:MainBlockIndent (prev_indent, prev_lnum, blockstart, stop_at)
Bram Moolenaar071d4272004-06-13 20:20:40 +000064 let lnum = a:prev_lnum
Bram Moolenaarc236c162008-07-13 17:41:49 +000065 let line = substitute( getline(lnum), g:ada#Comment, '', '' )
Bram Moolenaar071d4272004-06-13 20:20:40 +000066 while lnum > 1
67 if a:stop_at != '' && line =~ '^\s*' . a:stop_at && indent(lnum) < a:prev_indent
Bram Moolenaarc9b4b052006-04-30 18:54:39 +000068 return a:prev_indent
Bram Moolenaar071d4272004-06-13 20:20:40 +000069 elseif line =~ '^\s*' . a:blockstart
Bram Moolenaarc9b4b052006-04-30 18:54:39 +000070 let ind = indent(lnum)
71 if ind < a:prev_indent
72 return ind
73 endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000074 endif
75
76 let lnum = prevnonblank(lnum - 1)
77 " Get previous non-blank/non-comment-only line
78 while 1
Bram Moolenaarc236c162008-07-13 17:41:49 +000079 let line = substitute( getline(lnum), g:ada#Comment, '', '' )
Bram Moolenaarc9b4b052006-04-30 18:54:39 +000080 if line !~ '^\s*$' && line !~ '^\s*#'
81 break
82 endif
83 let lnum = prevnonblank(lnum - 1)
84 if lnum <= 0
85 return a:prev_indent
86 endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000087 endwhile
88 endwhile
89 " Fallback - just move back one
90 return a:prev_indent - &sw
Bram Moolenaar9964e462007-05-05 17:54:07 +000091endfunction MainBlockIndent
Bram Moolenaar071d4272004-06-13 20:20:40 +000092
Bram Moolenaar9964e462007-05-05 17:54:07 +000093" Section: s:EndBlockIndent {{{1
94"
Bram Moolenaar071d4272004-06-13 20:20:40 +000095" Try to find indent of the block we're in (and about to complete),
96" including handling of nested blocks. Works on the 'end' of a block.
97" prev_indent = the previous line's indent
98" prev_lnum = previous line (to start looking on)
99" blockstart = expr. that indicates a possible start of this block
100" blockend = expr. that indicates a possible end of this block
101function s:EndBlockIndent( prev_indent, prev_lnum, blockstart, blockend )
102 let lnum = a:prev_lnum
103 let line = getline(lnum)
104 let ends = 0
105 while lnum > 1
106 if getline(lnum) =~ '^\s*' . a:blockstart
107 let ind = indent(lnum)
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000108 if ends <= 0
109 if ind < a:prev_indent
Bram Moolenaar071d4272004-06-13 20:20:40 +0000110 return ind
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000111 endif
112 else
113 let ends = ends - 1
Bram Moolenaar071d4272004-06-13 20:20:40 +0000114 endif
115 elseif getline(lnum) =~ '^\s*' . a:blockend
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000116 let ends = ends + 1
Bram Moolenaar071d4272004-06-13 20:20:40 +0000117 endif
118
119 let lnum = prevnonblank(lnum - 1)
120 " Get previous non-blank/non-comment-only line
121 while 1
122 let line = getline(lnum)
Bram Moolenaarc236c162008-07-13 17:41:49 +0000123 let line = substitute( line, g:ada#Comment, '', '' )
Bram Moolenaar071d4272004-06-13 20:20:40 +0000124 if line !~ '^\s*$'
125 break
126 endif
127 let lnum = prevnonblank(lnum - 1)
128 if lnum <= 0
129 return a:prev_indent
130 endif
131 endwhile
132 endwhile
133 " Fallback - just move back one
134 return a:prev_indent - &sw
Bram Moolenaar9964e462007-05-05 17:54:07 +0000135endfunction EndBlockIndent
Bram Moolenaar071d4272004-06-13 20:20:40 +0000136
Bram Moolenaar9964e462007-05-05 17:54:07 +0000137" Section: s:StatementIndent {{{1
138"
Bram Moolenaar293ee4d2004-12-09 21:34:53 +0000139" Return indent of previous statement-start
Bram Moolenaar071d4272004-06-13 20:20:40 +0000140" (after we've indented due to multi-line statements).
141" This time, we start searching on the line *before* the one given (which is
142" the end of a statement - we want the previous beginning).
143function s:StatementIndent( current_indent, prev_lnum )
144 let lnum = a:prev_lnum
145 while lnum > 0
146 let prev_lnum = lnum
147 let lnum = prevnonblank(lnum - 1)
148 " Get previous non-blank/non-comment-only line
149 while 1
Bram Moolenaarc236c162008-07-13 17:41:49 +0000150 let line = substitute( getline(lnum), g:ada#Comment, '', '' )
151
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000152 if line !~ '^\s*$' && line !~ '^\s*#'
153 break
154 endif
155 let lnum = prevnonblank(lnum - 1)
156 if lnum <= 0
157 return a:current_indent
158 endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000159 endwhile
160 " Leave indent alone if our ';' line is part of a ';'-delineated
161 " aggregate (e.g., procedure args.) or first line after a block start.
162 if line =~ s:AdaBlockStart || line =~ '(\s*$'
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000163 return a:current_indent
Bram Moolenaar071d4272004-06-13 20:20:40 +0000164 endif
165 if line !~ '[.=(]\s*$'
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000166 let ind = indent(prev_lnum)
167 if ind < a:current_indent
168 return ind
169 endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000170 endif
171 endwhile
172 " Fallback - just use current one
173 return a:current_indent
Bram Moolenaar9964e462007-05-05 17:54:07 +0000174endfunction StatementIndent
Bram Moolenaar071d4272004-06-13 20:20:40 +0000175
176
Bram Moolenaar9964e462007-05-05 17:54:07 +0000177" Section: GetAdaIndent {{{1
178"
Bram Moolenaar071d4272004-06-13 20:20:40 +0000179" Find correct indent of a new line based upon what went before
Bram Moolenaar9964e462007-05-05 17:54:07 +0000180"
Bram Moolenaar071d4272004-06-13 20:20:40 +0000181function GetAdaIndent()
182 " Find a non-blank line above the current line.
183 let lnum = prevnonblank(v:lnum - 1)
184 let ind = indent(lnum)
185 let package_line = 0
186
187 " Get previous non-blank/non-comment-only/non-cpp line
188 while 1
Bram Moolenaar9964e462007-05-05 17:54:07 +0000189 let line = substitute( getline(lnum), g:ada#Comment, '', '' )
Bram Moolenaar071d4272004-06-13 20:20:40 +0000190 if line !~ '^\s*$' && line !~ '^\s*#'
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000191 break
Bram Moolenaar071d4272004-06-13 20:20:40 +0000192 endif
193 let lnum = prevnonblank(lnum - 1)
194 if lnum <= 0
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000195 return ind
Bram Moolenaar071d4272004-06-13 20:20:40 +0000196 endif
197 endwhile
198
199 " Get default indent (from prev. line)
200 let ind = indent(lnum)
Bram Moolenaar293ee4d2004-12-09 21:34:53 +0000201 let initind = ind
Bram Moolenaar071d4272004-06-13 20:20:40 +0000202
203 " Now check what's on the previous line
204 if line =~ s:AdaBlockStart || line =~ '(\s*$'
205 " Check for false matches to AdaBlockStart
206 let false_match = 0
207 if line =~ '^\s*\(procedure\|function\|package\)\>.*\<is\s*new\>'
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000208 " Generic instantiation
209 let false_match = 1
Bram Moolenaar071d4272004-06-13 20:20:40 +0000210 elseif line =~ ')\s*;\s*$' || line =~ '^\([^(]*([^)]*)\)*[^(]*;\s*$'
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000211 " forward declaration
212 let false_match = 1
Bram Moolenaar071d4272004-06-13 20:20:40 +0000213 endif
214 " Move indent in
215 if ! false_match
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000216 let ind = ind + &sw
Bram Moolenaar071d4272004-06-13 20:20:40 +0000217 endif
218 elseif line =~ '^\s*\(case\|exception\)\>'
219 " Move indent in twice (next 'when' will move back)
220 let ind = ind + 2 * &sw
221 elseif line =~ '^\s*end\s*record\>'
222 " Move indent back to tallying 'type' preceeding the 'record'.
223 " Allow indent to be equal to 'end record's.
224 let ind = s:MainBlockIndent( ind+&sw, lnum, 'type\>', '' )
225 elseif line =~ '\(^\s*new\>.*\)\@<!)\s*[;,]\s*$'
226 " Revert to indent of line that started this parenthesis pair
227 exe lnum
228 exe 'normal! $F)%'
229 if getline('.') =~ '^\s*('
Bram Moolenaarc236c162008-07-13 17:41:49 +0000230 " Dire layout - use previous indent (could check for g:ada#Comment here)
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000231 let ind = indent( prevnonblank( line('.')-1 ) )
Bram Moolenaar071d4272004-06-13 20:20:40 +0000232 else
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000233 let ind = indent('.')
Bram Moolenaar071d4272004-06-13 20:20:40 +0000234 endif
235 exe v:lnum
236 elseif line =~ '[.=(]\s*$'
237 " A statement continuation - move in one
238 let ind = ind + &sw
239 elseif line =~ '^\s*new\>'
240 " Multiple line generic instantiation ('package blah is\nnew thingy')
241 let ind = s:StatementIndent( ind - &sw, lnum )
242 elseif line =~ ';\s*$'
Bram Moolenaar293ee4d2004-12-09 21:34:53 +0000243 " Statement end (but not 'end' ) - try to find current statement-start indent
Bram Moolenaar071d4272004-06-13 20:20:40 +0000244 let ind = s:StatementIndent( ind, lnum )
245 endif
246
247 " Check for potential argument list on next line
248 let continuation = (line =~ '[A-Za-z0-9_]\s*$')
249
250
251 " Check current line; search for simplistic matching start-of-block
252 let line = getline(v:lnum)
253 if line =~ '^\s*#'
254 " Start of line for ada-pp
255 let ind = 0
256 elseif continuation && line =~ '^\s*('
Bram Moolenaar293ee4d2004-12-09 21:34:53 +0000257 " Don't do this if we've already indented due to the previous line
258 if ind == initind
Bram Moolenaarc9b4b052006-04-30 18:54:39 +0000259 let ind = ind + &sw
Bram Moolenaar293ee4d2004-12-09 21:34:53 +0000260 endif
Bram Moolenaar071d4272004-06-13 20:20:40 +0000261 elseif line =~ '^\s*\(begin\|is\)\>'
262 let ind = s:MainBlockIndent( ind, lnum, '\(procedure\|function\|declare\|package\|task\)\>', 'begin\>' )
263 elseif line =~ '^\s*record\>'
Bram Moolenaar293ee4d2004-12-09 21:34:53 +0000264 let ind = s:MainBlockIndent( ind, lnum, 'type\>\|for\>.*\<use\>', '' ) + &sw
Bram Moolenaar071d4272004-06-13 20:20:40 +0000265 elseif line =~ '^\s*\(else\|elsif\)\>'
266 let ind = s:MainBlockIndent( ind, lnum, 'if\>', '' )
267 elseif line =~ '^\s*when\>'
268 " Align 'when' one /in/ from matching block start
269 let ind = s:MainBlockIndent( ind, lnum, '\(case\|exception\)\>', '' ) + &sw
270 elseif line =~ '^\s*end\>\s*\<if\>'
271 " End of if statements
272 let ind = s:EndBlockIndent( ind, lnum, 'if\>', 'end\>\s*\<if\>' )
273 elseif line =~ '^\s*end\>\s*\<loop\>'
274 " End of loops
275 let ind = s:EndBlockIndent( ind, lnum, '\(\(while\|for\)\>.*\)\?\<loop\>', 'end\>\s*\<loop\>' )
276 elseif line =~ '^\s*end\>\s*\<record\>'
277 " End of records
278 let ind = s:EndBlockIndent( ind, lnum, '\(type\>.*\)\=\<record\>', 'end\>\s*\<record\>' )
279 elseif line =~ '^\s*end\>\s*\<procedure\>'
280 " End of procedures
281 let ind = s:EndBlockIndent( ind, lnum, 'procedure\>.*\<is\>', 'end\>\s*\<procedure\>' )
282 elseif line =~ '^\s*end\>\s*\<case\>'
283 " End of case statement
284 let ind = s:EndBlockIndent( ind, lnum, 'case\>.*\<is\>', 'end\>\s*\<case\>' )
285 elseif line =~ '^\s*end\>'
286 " General case for end
Bram Moolenaar293ee4d2004-12-09 21:34:53 +0000287 let ind = s:MainBlockIndent( ind, lnum, '\(if\|while\|for\|loop\|accept\|begin\|record\|case\|exception\|package\)\>', '' )
Bram Moolenaar071d4272004-06-13 20:20:40 +0000288 elseif line =~ '^\s*exception\>'
289 let ind = s:MainBlockIndent( ind, lnum, 'begin\>', '' )
290 elseif line =~ '^\s*then\>'
291 let ind = s:MainBlockIndent( ind, lnum, 'if\>', '' )
292 endif
293
294 return ind
Bram Moolenaar9964e462007-05-05 17:54:07 +0000295endfunction GetAdaIndent
Bram Moolenaar071d4272004-06-13 20:20:40 +0000296
Bram Moolenaar9a7224b2012-04-30 15:56:52 +0200297let &cpo = s:keepcpo
298unlet s:keepcpo
299
Bram Moolenaar9964e462007-05-05 17:54:07 +0000300finish " 1}}}
301
302"------------------------------------------------------------------------------
303" Copyright (C) 2006 Martin Krischik
304"
305" Vim is Charityware - see ":help license" or uganda.txt for licence details.
306"------------------------------------------------------------------------------
307" vim: textwidth=78 wrap tabstop=8 shiftwidth=3 softtabstop=3 noexpandtab
308" vim: foldmethod=marker