codekingpro/portable-devtools
114k
1"------------------------------------------------------------------------------2" Description: Vim Ada indent file3" Language: Ada (2005)4" $Id: ada.vim 887 2008-07-08 14:29:01Z krischik $5" Copyright: Copyright (C) 2006 Martin Krischik6" Maintainer: Martin Krischik <krischik@users.sourceforge.net>7" Neil Bird <neil@fnxweb.com>8" Ned Okie <nokie@radford.edu>9" $Author: krischik $10" $Date: 2008-07-08 16:29:01 +0200 (Di, 08 Jul 2008) $11" Version: 4.612" $Revision: 887 $13" $HeadURL: https://gnuada.svn.sourceforge.net/svnroot/gnuada/trunk/tools/vim/indent/ada.vim $14" History: 24.05.2006 MK Unified Headers15" 16.07.2006 MK Ada-Mode as vim-ball16" 15.10.2006 MK Bram's suggestion for runtime integration17" 05.11.2006 MK Bram suggested to save on spaces18" 19.09.2007 NO g: missing before ada#Comment19" 2022 April: b:undo_indent added by Doug Kearns20" Help Page: ft-vim-indent21"------------------------------------------------------------------------------22" 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?26"------------------------------------------------------------------------------27 28" Only load this indent file when no other was loaded.29if exists("b:did_indent") || version < 70030 finish31endif32 33let b:did_indent = 4534 35setlocal indentexpr=GetAdaIndent()36setlocal indentkeys-=0{,0}37setlocal indentkeys+=0=~then,0=~end,0=~elsif,0=~when,0=~exception,0=~begin,0=~is,0=~record38 39let b:undo_indent = "setl inde< indk<"40 41" Only define the functions once.42if exists("*GetAdaIndent")43 finish44endif45let s:keepcpo= &cpo46set cpo&vim47 48if 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\>\)'50else51 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\>\)'52endif53 54" Section: s:MainBlockIndent {{{155"56" Try to find indent of the block we're in57" prev_indent = the previous line's indent58" prev_lnum = previous line (to start looking on)59" blockstart = expr. that indicates a possible start of this block60" stop_at = if non-null, if a matching line is found, gives up!61" No recursive previous block analysis: simply look for a valid line62" 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 currently64" 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.66function s:MainBlockIndent (prev_indent, prev_lnum, blockstart, stop_at)67 let lnum = a:prev_lnum68 let line = substitute( getline(lnum), g:ada#Comment, '', '' )69 while lnum > 170 if a:stop_at != '' && line =~ '^\s*' . a:stop_at && indent(lnum) < a:prev_indent71 return a:prev_indent72 elseif line =~ '^\s*' . a:blockstart73 let ind = indent(lnum)74 if ind < a:prev_indent75 return ind76 endif77 endif78 79 let lnum = prevnonblank(lnum - 1)80 " Get previous non-blank/non-comment-only line81 while 182 let line = substitute( getline(lnum), g:ada#Comment, '', '' )83 if line !~ '^\s*$' && line !~ '^\s*#'84 break85 endif86 let lnum = prevnonblank(lnum - 1)87 if lnum <= 088 return a:prev_indent89 endif90 endwhile91 endwhile92 " Fallback - just move back one93 return a:prev_indent - shiftwidth()94endfunction MainBlockIndent95 96" Section: s:EndBlockIndent {{{197"98" 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 indent101" prev_lnum = previous line (to start looking on)102" blockstart = expr. that indicates a possible start of this block103" blockend = expr. that indicates a possible end of this block104function s:EndBlockIndent( prev_indent, prev_lnum, blockstart, blockend )105 let lnum = a:prev_lnum106 let line = getline(lnum)107 let ends = 0108 while lnum > 1109 if getline(lnum) =~ '^\s*' . a:blockstart110 let ind = indent(lnum)111 if ends <= 0112 if ind < a:prev_indent113 return ind114 endif115 else116 let ends = ends - 1117 endif118 elseif getline(lnum) =~ '^\s*' . a:blockend119 let ends = ends + 1120 endif121 122 let lnum = prevnonblank(lnum - 1)123 " Get previous non-blank/non-comment-only line124 while 1125 let line = getline(lnum)126 let line = substitute( line, g:ada#Comment, '', '' )127 if line !~ '^\s*$'128 break129 endif130 let lnum = prevnonblank(lnum - 1)131 if lnum <= 0132 return a:prev_indent133 endif134 endwhile135 endwhile136 " Fallback - just move back one137 return a:prev_indent - shiftwidth()138endfunction EndBlockIndent139 140" Section: s:StatementIndent {{{1141"142" Return indent of previous statement-start143" (after we've indented due to multi-line statements).144" This time, we start searching on the line *before* the one given (which is145" the end of a statement - we want the previous beginning).146function s:StatementIndent( current_indent, prev_lnum )147 let lnum = a:prev_lnum148 while lnum > 0149 let prev_lnum = lnum150 let lnum = prevnonblank(lnum - 1)151 " Get previous non-blank/non-comment-only line152 while 1153 let line = substitute( getline(lnum), g:ada#Comment, '', '' )154 155 if line !~ '^\s*$' && line !~ '^\s*#'156 break157 endif158 let lnum = prevnonblank(lnum - 1)159 if lnum <= 0160 return a:current_indent161 endif162 endwhile163 " Leave indent alone if our ';' line is part of a ';'-delineated164 " aggregate (e.g., procedure args.) or first line after a block start.165 if line =~ s:AdaBlockStart || line =~ '(\s*$'166 return a:current_indent167 endif168 if line !~ '[.=(]\s*$'169 let ind = indent(prev_lnum)170 if ind < a:current_indent171 return ind172 endif173 endif174 endwhile175 " Fallback - just use current one176 return a:current_indent177endfunction StatementIndent178 179 180" Section: GetAdaIndent {{{1181"182" Find correct indent of a new line based upon what went before183"184function 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 = 0189 190 " Get previous non-blank/non-comment-only/non-cpp line191 while 1192 let line = substitute( getline(lnum), g:ada#Comment, '', '' )193 if line !~ '^\s*$' && line !~ '^\s*#'194 break195 endif196 let lnum = prevnonblank(lnum - 1)197 if lnum <= 0198 return ind199 endif200 endwhile201 202 " Get default indent (from prev. line)203 let ind = indent(lnum)204 let initind = ind205 206 " Now check what's on the previous line207 if line =~ s:AdaBlockStart || line =~ '(\s*$'208 " Check for false matches to AdaBlockStart209 let false_match = 0210 if line =~ '^\s*\(procedure\|function\|package\)\>.*\<is\s*new\>'211 " Generic instantiation212 let false_match = 1213 elseif line =~ ')\s*;\s*$' || line =~ '^\([^(]*([^)]*)\)*[^(]*;\s*$'214 " forward declaration215 let false_match = 1216 endif217 " Move indent in218 if ! false_match219 let ind = ind + shiftwidth()220 endif221 elseif line =~ '^\s*\(case\|exception\)\>'222 " Move indent in twice (next 'when' will move back)223 let ind = ind + 2 * shiftwidth()224 elseif line =~ '^\s*end\s*record\>'225 " Move indent back to tallying 'type' preceding the 'record'.226 " Allow indent to be equal to 'end record's.227 let ind = s:MainBlockIndent( ind+shiftwidth(), lnum, 'type\>', '' )228 elseif line =~ '\(^\s*new\>.*\)\@<!)\s*[;,]\s*$'229 " Revert to indent of line that started this parenthesis pair230 exe lnum231 exe 'normal! $F)%'232 if getline('.') =~ '^\s*('233 " Dire layout - use previous indent (could check for g:ada#Comment here)234 let ind = indent( prevnonblank( line('.')-1 ) )235 else236 let ind = indent('.')237 endif238 exe v:lnum239 elseif line =~ '[.=(]\s*$'240 " A statement continuation - move in one241 let ind = ind + shiftwidth()242 elseif line =~ '^\s*new\>'243 " Multiple line generic instantiation ('package blah is\nnew thingy')244 let ind = s:StatementIndent( ind - shiftwidth(), lnum )245 elseif line =~ ';\s*$'246 " Statement end (but not 'end' ) - try to find current statement-start indent247 let ind = s:StatementIndent( ind, lnum )248 endif249 250 " Check for potential argument list on next line251 let continuation = (line =~ '[A-Za-z0-9_]\s*$')252 253 254 " Check current line; search for simplistic matching start-of-block255 let line = getline(v:lnum)256 if line =~ '^\s*#'257 " Start of line for ada-pp258 let ind = 0259 elseif continuation && line =~ '^\s*('260 " Don't do this if we've already indented due to the previous line261 if ind == initind262 let ind = ind + shiftwidth()263 endif264 elseif line =~ '^\s*\(begin\|is\)\>'265 let ind = s:MainBlockIndent( ind, lnum, '\(procedure\|function\|declare\|package\|task\)\>', 'begin\>' )266 elseif line =~ '^\s*record\>'267 let ind = s:MainBlockIndent( ind, lnum, 'type\>\|for\>.*\<use\>', '' ) + shiftwidth()268 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 start272 let ind = s:MainBlockIndent( ind, lnum, '\(case\|exception\)\>', '' ) + shiftwidth()273 elseif line =~ '^\s*end\>\s*\<if\>'274 " End of if statements275 let ind = s:EndBlockIndent( ind, lnum, 'if\>', 'end\>\s*\<if\>' )276 elseif line =~ '^\s*end\>\s*\<loop\>'277 " End of loops278 let ind = s:EndBlockIndent( ind, lnum, '\(\(while\|for\)\>.*\)\?\<loop\>', 'end\>\s*\<loop\>' )279 elseif line =~ '^\s*end\>\s*\<record\>'280 " End of records281 let ind = s:EndBlockIndent( ind, lnum, '\(type\>.*\)\=\<record\>', 'end\>\s*\<record\>' )282 elseif line =~ '^\s*end\>\s*\<procedure\>'283 " End of procedures284 let ind = s:EndBlockIndent( ind, lnum, 'procedure\>.*\<is\>', 'end\>\s*\<procedure\>' )285 elseif line =~ '^\s*end\>\s*\<case\>'286 " End of case statement287 let ind = s:EndBlockIndent( ind, lnum, 'case\>.*\<is\>', 'end\>\s*\<case\>' )288 elseif line =~ '^\s*end\>'289 " General case for end290 let ind = s:MainBlockIndent( ind, lnum, '\(if\|while\|for\|loop\|accept\|begin\|record\|case\|exception\|package\)\>', '' )291 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 endif296 297 return ind298endfunction GetAdaIndent299 300let &cpo = s:keepcpo301unlet s:keepcpo302 303finish " 1}}}304 305"------------------------------------------------------------------------------306" Copyright (C) 2006 Martin Krischik307"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 noexpandtab311" vim: foldmethod=marker312 