1" Vim Ada plugin file 2" Language: Ada 3" Maintainer: Neil Bird <[email protected]> 4" Last Change: 2003 May 11 5" Version: $Id$ 6" Look for the latest version at http://vim.sourceforge.net/ 7" 8" Perform Ada specific completion & tagging. 9" 10" 11" Provides mapping overrides for tag jumping that figure out the current 12" Ada object and tag jump to that, not the 'simple' vim word. 13" Similarly allows <Ctrl-N> matching of full-length ada entities from tags. 14" Exports 'AdaWord()' function to return full name of Ada entity under the 15" cursor( or at given line/column), stripping whitespace/newlines as necessary. 16 17 18" Only do this when not done yet for this buffer 19if exists("b:did_ftplugin") 20 finish 21endif 22 23" Don't load another plugin for this buffer 24let b:did_ftplugin = 1 25 26" Temporarily set cpoptions to ensure the script loads OK 27let s:cpoptions = &cpoptions 28set cpo-=C 29 30 31" Ada comments 32setlocal comments+=O:-- 33 34 35" Make local tag mappings for this buffer (if not already set) 36if mapcheck('<C-]>','n') == '' 37 nnoremap <unique> <buffer> <C-]> :call JumpToTag_ada('')<cr> 38endif 39if mapcheck('g<C-]>','n') == '' 40 nnoremap <unique> <buffer> g<C-]> :call JumpToTag_ada('','stj')<cr> 41endif 42 43if mapcheck('<C-N>','i') == '' 44 inoremap <unique> <buffer> <C-N> <C-R>=<SID>AdaCompletion("\<lt>C-N>")<cr> 45endif 46if mapcheck('<C-P>','i') == '' 47 inoremap <unique> <buffer> <C-P> <C-R>=<SID>AdaCompletion("\<lt>C-P>")<cr> 48endif 49if mapcheck('<C-X><C-]>','i') == '' 50 inoremap <unique> <buffer> <C-X><C-]> <C-R>=<SID>AdaCompletion("\<lt>C-X>\<lt>C-]>")<cr> 51endif 52if mapcheck('<bs>','i') == '' 53 inoremap <silent> <unique> <buffer> <bs> <C-R>=<SID>AdaInsertBackspace()<cr> 54endif 55 56 57" Only do this when not done yet for this buffer & matchit is used 58if ! exists("b:match_words") && exists("loaded_matchit") 59 " The following lines enable the macros/matchit.vim plugin for 60 " Ada-specific extended matching with the % key. 61 let s:notend = '\%(\<end\s\+\)\@<!' 62 let b:match_words= 63 \ s:notend . '\<if\>:\<elsif\>:\<else\>:\<end\>\s\+\<if\>,' . 64 \ s:notend . '\<case\>:\<when\>:\<end\>\s\+\<case\>,' . 65 \ '\%(\<while\>.*\|\<for\>.*\|'.s:notend.'\)\<loop\>:\<end\>\s\+\<loop\>,' . 66 \ '\%(\<do\>\|\<begin\>\):\<exception\>:\<end\>\s*\%($\|[;A-Z]\),' . 67 \ s:notend . '\<record\>:\<end\>\s\+\<record\>' 68endif 69 70 71" Prevent re-load of functions 72if exists('s:id') 73 finish 74endif 75 76" Get this script's unique id 77map <script> <SID>?? <SID>?? 78let s:id = substitute( maparg('<SID>??'), '^<SNR>\(.*\)_??$', '\1', '' ) 79unmap <script> <SID>?? 80 81 82" Extract current Ada word across multiple lines 83" AdaWord( [line, column] )\ 84let s:AdaWordRegex = '\a\w*\(\_s*\.\_s*\a\w*\)*' 85let s:AdaComment = "\\v^(\"[^\"]*\"|'.'|[^\"']){-}\\zs\\s*--.*" 86 87function! AdaWord(...) 88 if a:0 > 1 89 let linenr = a:1 90 let colnr = a:2 - 1 91 else 92 let linenr = line('.') 93 let colnr = col('.') - 1 94 endif 95 let line = substitute( getline(linenr), s:AdaComment, '', '' ) 96 " Cope with tag searching for items in comments; if we are, don't loop 97 " backards looking for previous lines 98 if colnr > strlen(line) 99 " We were in a comment 100 let line = getline(linenr) 101 let search_prev_lines = 0 102 else 103 let search_prev_lines = 1 104 endif 105 106 " Go backwards until we find a match (Ada ID) that *doesn't* include our 107 " location - i.e., the previous ID. This is because the current 'correct' 108 " match will toggle matching/not matching as we traverse characters 109 " backwards. Thus, we have to find the previous unrelated match, exclude 110 " it, then use the next full match (ours). 111 " Remember to convert vim column 'colnr' [1..n] to string offset [0..(n-1)] 112 " ... but start, here, one after the required char. 113 let newcol = colnr + 1 114 while 1 115 let newcol = newcol - 1 116 if newcol < 0 117 " Have to include previous line from file 118 let linenr = linenr - 1 119 if linenr < 1 || !search_prev_lines 120 " Start of file or matching in a comment 121 let linenr = 1 122 let newcol = 0 123 let ourmatch = match( line, s:AdaWordRegex ) 124 break 125 endif 126 " Get previous line, and prepend it to our search string 127 let newline = substitute( getline(linenr), s:AdaComment, '', '' ) 128 let newcol = strlen(newline) - 1 129 let colnr = colnr + newcol 130 let line = newline . line 131 endif 132 " Check to see if this is a match excluding 'us' 133 let mend = newcol + matchend( strpart(line,newcol), s:AdaWordRegex ) - 1 134 if mend >= newcol && mend < colnr 135 " Yes 136 let ourmatch = mend+1 + match( strpart(line,mend+1), s:AdaWordRegex ) 137 break 138 endif 139 endwhile 140 141 " Got anything? 142 if ourmatch < 0 143 return '' 144 else 145 let line = strpart( line, ourmatch) 146 endif 147 148 " Now simply add further lines until the match gets no bigger 149 let matchstr = matchstr( line, s:AdaWordRegex ) 150 let lastline = line('$') 151 let linenr = line('.') + 1 152 while linenr <= lastline 153 let lastmatch = matchstr 154 let line = line . substitute( getline(linenr), s:AdaComment, '', '' ) 155 let matchstr = matchstr( line, s:AdaWordRegex ) 156 if matchstr == lastmatch 157 break 158 endif 159 endwhile 160 161 " Strip whitespace & return 162 return substitute( matchstr, '\s\+', '', 'g' ) 163endfunction 164 165 166" Word tag - include '.' and if Ada make uppercase 167" Name allows a common JumpToTag() to look for an ft specific JumpToTag_ft(). 168function! JumpToTag_ada(word,...) 169 if a:word == '' 170 " Get current word 171 let word = AdaWord() 172 if word == '' 173 return 174 endif 175 else 176 let word = a:word 177 endif 178 if a:0 > 0 179 let mode = a:1 180 else 181 let mode = 'tj' 182 endif 183 184 let v:errmsg = '' 185 execute 'silent!' mode word 186 if v:errmsg != '' 187 if v:errmsg =~ '^E426:' " Tag not found 188 let ignorecase = &ignorecase 189 set ignorecase 190 execute mode word 191 let &ignorecase = ignorecase 192 else 193 " Repeat to give error 194 execute mode word 195 endif 196 endif 197endfunction 198 199 200" Word completion (^N/^R/^X^]) - force '.' inclusion 201function! s:AdaCompletion(cmd) 202 set iskeyword+=46 203 return a:cmd . "\<C-R>=<SNR>" . s:id . "_AdaCompletionEnd()\<CR>" 204endfunction 205function! s:AdaCompletionEnd() 206 set iskeyword-=46 207 return '' 208endfunction 209 210 211" Backspace at end of line after auto-inserted commentstring '-- ' wipes it 212function! s:AdaInsertBackspace() 213 let line = getline('.') 214 if col('.') > strlen(line) && match(line,'-- $') != -1 && match(&comments,'--') != -1 215 return "\<bs>\<bs>\<bs>" 216 else 217 return "\<bs>" 218 endif 219endfunction 220 221 222" Reset cpoptions 223let &cpoptions = s:cpoptions 224unlet s:cpoptions 225 226" vim: sts=2 sw=2 : 227