home *** CD-ROM | disk | FTP | other *** search
/ vim.ftp.fu-berlin.de / 2015-02-03.vim.ftp.fu-berlin.de.tar / vim.ftp.fu-berlin.de / runtime / plugin / matchparen.vim < prev    next >
Encoding:
Text File  |  2012-05-31  |  4.8 KB  |  153 lines

  1. " Vim plugin for showing matching parens
  2. " Maintainer:  Bram Moolenaar <Bram@vim.org>
  3. " Last Change: 2011 Aug 27
  4.  
  5. " Exit quickly when:
  6. " - this plugin was already loaded (or disabled)
  7. " - when 'compatible' is set
  8. " - the "CursorMoved" autocmd event is not availble.
  9. if exists("g:loaded_matchparen") || &cp || !exists("##CursorMoved")
  10.   finish
  11. endif
  12. let g:loaded_matchparen = 1
  13.  
  14. augroup matchparen
  15.   " Replace all matchparen autocommands
  16.   autocmd! CursorMoved,CursorMovedI,WinEnter * call s:Highlight_Matching_Pair()
  17. augroup END
  18.  
  19. " Skip the rest if it was already done.
  20. if exists("*s:Highlight_Matching_Pair")
  21.   finish
  22. endif
  23.  
  24. let s:cpo_save = &cpo
  25. set cpo-=C
  26.  
  27. " The function that is invoked (very often) to define a ":match" highlighting
  28. " for any matching paren.
  29. function! s:Highlight_Matching_Pair()
  30.   " Remove any previous match.
  31.   if exists('w:paren_hl_on') && w:paren_hl_on
  32.     3match none
  33.     let w:paren_hl_on = 0
  34.   endif
  35.  
  36.   " Avoid that we remove the popup menu.
  37.   " Return when there are no colors (looks like the cursor jumps).
  38.   if pumvisible() || (&t_Co < 8 && !has("gui_running"))
  39.     return
  40.   endif
  41.  
  42.   " Get the character under the cursor and check if it's in 'matchpairs'.
  43.   let c_lnum = line('.')
  44.   let c_col = col('.')
  45.   let before = 0
  46.  
  47.   let c = getline(c_lnum)[c_col - 1]
  48.   let plist = split(&matchpairs, '.\zs[:,]')
  49.   let i = index(plist, c)
  50.   if i < 0
  51.     " not found, in Insert mode try character before the cursor
  52.     if c_col > 1 && (mode() == 'i' || mode() == 'R')
  53.       let before = 1
  54.       let c = getline(c_lnum)[c_col - 2]
  55.       let i = index(plist, c)
  56.     endif
  57.     if i < 0
  58.       " not found, nothing to do
  59.       return
  60.     endif
  61.   endif
  62.  
  63.   " Figure out the arguments for searchpairpos().
  64.   if i % 2 == 0
  65.     let s_flags = 'nW'
  66.     let c2 = plist[i + 1]
  67.   else
  68.     let s_flags = 'nbW'
  69.     let c2 = c
  70.     let c = plist[i - 1]
  71.   endif
  72.   if c == '['
  73.     let c = '\['
  74.     let c2 = '\]'
  75.   endif
  76.  
  77.   " Find the match.  When it was just before the cursor move it there for a
  78.   " moment.
  79.   if before > 0
  80.     let save_cursor = winsaveview()
  81.     call cursor(c_lnum, c_col - before)
  82.   endif
  83.  
  84.   " When not in a string or comment ignore matches inside them.
  85.   " We match "escape" for special items, such as lispEscapeSpecial.
  86.   let s_skip ='synIDattr(synID(line("."), col("."), 0), "name") ' .
  87.     \ '=~?  "string\\|character\\|singlequote\\|escape\\|comment"'
  88.   execute 'if' s_skip '| let s_skip = 0 | endif'
  89.  
  90.   " Limit the search to lines visible in the window.
  91.   let stoplinebottom = line('w$')
  92.   let stoplinetop = line('w0')
  93.   if i % 2 == 0
  94.     let stopline = stoplinebottom
  95.   else
  96.     let stopline = stoplinetop
  97.   endif
  98.  
  99.   try
  100.     " Limit the search time to 300 msec to avoid a hang on very long lines.
  101.     " This fails when a timeout is not supported.
  102.     let [m_lnum, m_col] = searchpairpos(c, '', c2, s_flags, s_skip, stopline, 300)
  103.   catch /E118/
  104.     " Can't use the timeout, restrict the stopline a bit more to avoid taking
  105.     " a long time on closed folds and long lines.
  106.     " The "viewable" variables give a range in which we can scroll while
  107.     " keeping the cursor at the same position.
  108.     " adjustedScrolloff accounts for very large numbers of scrolloff.
  109.     let adjustedScrolloff = min([&scrolloff, (line('w$') - line('w0')) / 2])
  110.     let bottom_viewable = min([line('$'), c_lnum + &lines - adjustedScrolloff - 2])
  111.     let top_viewable = max([1, c_lnum-&lines+adjustedScrolloff + 2])
  112.     " one of these stoplines will be adjusted below, but the current values are
  113.     " minimal boundaries within the current window
  114.     if i % 2 == 0
  115.       if has("byte_offset") && has("syntax_items") && &smc > 0
  116.     let stopbyte = min([line2byte("$"), line2byte(".") + col(".") + &smc * 2])
  117.     let stopline = min([bottom_viewable, byte2line(stopbyte)])
  118.       else
  119.     let stopline = min([bottom_viewable, c_lnum + 100])
  120.       endif
  121.       let stoplinebottom = stopline
  122.     else
  123.       if has("byte_offset") && has("syntax_items") && &smc > 0
  124.     let stopbyte = max([1, line2byte(".") + col(".") - &smc * 2])
  125.     let stopline = max([top_viewable, byte2line(stopbyte)])
  126.       else
  127.     let stopline = max([top_viewable, c_lnum - 100])
  128.       endif
  129.       let stoplinetop = stopline
  130.     endif
  131.     let [m_lnum, m_col] = searchpairpos(c, '', c2, s_flags, s_skip, stopline)
  132.   endtry
  133.  
  134.   if before > 0
  135.     call winrestview(save_cursor)
  136.   endif
  137.  
  138.   " If a match is found setup match highlighting.
  139.   if m_lnum > 0 && m_lnum >= stoplinetop && m_lnum <= stoplinebottom 
  140.     exe '3match MatchParen /\(\%' . c_lnum . 'l\%' . (c_col - before) .
  141.       \ 'c\)\|\(\%' . m_lnum . 'l\%' . m_col . 'c\)/'
  142.     let w:paren_hl_on = 1
  143.   endif
  144. endfunction
  145.  
  146. " Define commands that will disable and enable the plugin.
  147. command! NoMatchParen windo 3match none | unlet! g:loaded_matchparen |
  148.       \ au! matchparen
  149. command! DoMatchParen runtime plugin/matchparen.vim | windo doau CursorMoved
  150.  
  151. let &cpo = s:cpo_save
  152. unlet s:cpo_save
  153.