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