diff options
Diffstat (limited to 'runtime/ftplugin/ada.vim')
-rw-r--r-- | runtime/ftplugin/ada.vim | 226 |
1 files changed, 226 insertions, 0 deletions
diff --git a/runtime/ftplugin/ada.vim b/runtime/ftplugin/ada.vim new file mode 100644 index 000000000..06c057fc8 --- /dev/null +++ b/runtime/ftplugin/ada.vim @@ -0,0 +1,226 @@ +" Vim Ada plugin file +" Language: Ada +" Maintainer: Neil Bird <neil@fnxweb.com> +" Last Change: 2003 May 11 +" Version: $Id$ +" 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 : |