endwise.vim 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. " endwise.vim - EndWise
  2. " Author: Tim Pope <http://tpo.pe/>
  3. " Version: 1.1
  4. " License: Same as Vim itself. See :help license
  5. " GetLatestVimScripts: 2386 1 :AutoInstall: endwise.vim
  6. if exists("g:loaded_endwise") || &cp
  7. finish
  8. endif
  9. let g:loaded_endwise = 1
  10. augroup endwise " {{{1
  11. autocmd!
  12. autocmd FileType lua
  13. \ let b:endwise_addition = '\=submatch(0)=="{" ? "}" : "end"' |
  14. \ let b:endwise_words = 'function,do,then' |
  15. \ let b:endwise_pattern = '^\s*\zs\%(function\|do\|then\)\>\%(.*[^.:@$]\<end\>\)\@!\|\<then\|do\ze\%(\s*|.*|\)\=\s*$' |
  16. \ let b:endwise_syngroups = 'luaFunction,luaStatement,luaCond'
  17. autocmd FileType elixir
  18. \ let b:endwise_addition = '\=submatch(0)=="{" ? "}" : "end"' |
  19. \ let b:endwise_words = 'case,cond,bc,lc,inlist,inbits,if,unless,try,receive,function,fn' |
  20. \ let b:endwise_pattern = '^\(.*=\)\?\s*\zs\%(case\|cond\|bc\|lc\|inlist\|inbits\|if\|unless\|try\|receive\|function\|fn\)\>\%(.*[^.:@$]\<end\>\)\@!\|\<do\ze\%(\s*|.*|\)\=\s*$' |
  21. \ let b:endwise_syngroups = 'elixirKeyword'
  22. autocmd FileType ruby
  23. \ let b:endwise_addition = '\=submatch(0)=="{" ? "}" : "end"' |
  24. \ let b:endwise_words = 'module,class,def,if,unless,case,while,until,begin,do' |
  25. \ let b:endwise_pattern = '^\(.*=\)\?\s*\zs\%(module\|class\|def\|if\|unless\|case\|while\|until\|for\|\|begin\)\>\%(.*[^.:@$]\<end\>\)\@!\|\<do\ze\%(\s*|.*|\)\=\s*$' |
  26. \ let b:endwise_syngroups = 'rubyModule,rubyClass,rubyDefine,rubyControl,rubyConditional,rubyRepeat'
  27. autocmd FileType sh,zsh
  28. \ let b:endwise_addition = '\=submatch(0)=="if" ? "fi" : submatch(0)=="case" ? "esac" : "done"' |
  29. \ let b:endwise_words = 'if,until,case,do' |
  30. \ let b:endwise_pattern = '\%(^\s*\zs\%(if\|case\)\>\ze\|\zs\<do\ze$\|^\s*\zsdo\s*\ze$\)' |
  31. \ let b:endwise_syngroups = 'shConditional,shLoop,shIf,shFor,shRepeat,shCaseEsac,zshConditional,zshRepeat,zshDelimiter'
  32. autocmd FileType vb,vbnet,aspvbs
  33. \ let b:endwise_addition = 'End &' |
  34. \ let b:endwise_words = 'Function,Sub,Class,Module,Enum,Namespace' |
  35. \ let b:endwise_pattern = '\%(\<End\>.*\)\@<!\<&\>' |
  36. \ let b:endwise_syngroups = 'vbStatement,vbnetStorage,vbnetProcedure,vbnet.*Words,AspVBSStatement'
  37. autocmd FileType vim
  38. \ let b:endwise_addition = 'end&' |
  39. \ let b:endwise_words = 'fu\%[nction],wh\%[ile],if,for,try' |
  40. \ let b:endwise_syngroups = 'vimFuncKey,vimNotFunc,vimCommand'
  41. autocmd FileType c,cpp,xdefaults
  42. \ let b:endwise_addition = '#endif' |
  43. \ let b:endwise_words = '#if,#ifdef,#ifndef' |
  44. \ let b:endwise_pattern = '^\s*#\%(if\|ifdef\|ifndef\)\s\+.\+$' |
  45. \ let b:endwise_syngroups = 'cPreCondit,cCppInWrapper,xdefaultsPreProc'
  46. autocmd FileType matlab
  47. \ let b:endwise_addition = '\=submatch(0)=="{" ? "}" : "end"' |
  48. \ let b:endwise_words = 'function,if,for' |
  49. \ let b:endwise_syngroups = 'matlabStatement,matlabFunction,matlabConditional,matlabRepeat'
  50. augroup END " }}}1
  51. " Maps {{{1
  52. if maparg("<Plug>DiscretionaryEnd") == ""
  53. inoremap <silent> <SID>DiscretionaryEnd <C-R>=<SID>crend(0)<CR>
  54. inoremap <silent> <SID>AlwaysEnd <C-R>=<SID>crend(1)<CR>
  55. imap <script> <Plug>DiscretionaryEnd <SID>DiscretionaryEnd
  56. imap <script> <Plug>AlwaysEnd <SID>AlwaysEnd
  57. endif
  58. if !exists('g:endwise_no_mappings')
  59. if maparg('<CR>','i') =~# '<C-R>=.*crend(.)<CR>\|<\%(Plug\|SNR\|SID\)>.*End'
  60. " Already mapped
  61. elseif maparg('<CR>','i') =~ '<CR>'
  62. exe "imap <script> <C-X><CR> ".maparg('<CR>','i')."<SID>AlwaysEnd"
  63. exe "imap <script> <CR> ".maparg('<CR>','i')."<SID>DiscretionaryEnd"
  64. elseif maparg('<CR>','i') =~ '<Plug>\w\+CR'
  65. exe "imap <C-X><CR> ".maparg('<CR>', 'i')."<Plug>AlwaysEnd"
  66. exe "imap <CR> ".maparg('<CR>', 'i')."<Plug>DiscretionaryEnd"
  67. else
  68. imap <C-X><CR> <CR><Plug>AlwaysEnd
  69. imap <CR> <CR><Plug>DiscretionaryEnd
  70. endif
  71. endif
  72. " }}}1
  73. " Code {{{1
  74. function! s:mysearchpair(beginpat,endpat,synpat)
  75. let g:endwise_syntaxes = ""
  76. let s:lastline = line('.')
  77. call s:synname()
  78. let line = searchpair(a:beginpat,'',a:endpat,'Wn','<SID>synname() !~# "^'.substitute(a:synpat,'\\','\\\\','g').'$"',line('.')+50)
  79. return line
  80. endfunction
  81. function! s:crend(always)
  82. let n = ""
  83. if !exists("b:endwise_addition") || !exists("b:endwise_words") || !exists("b:endwise_syngroups")
  84. return n
  85. end
  86. let synpat = '\%('.substitute(b:endwise_syngroups,',','\\|','g').'\)'
  87. let wordchoice = '\%('.substitute(b:endwise_words,',','\\|','g').'\)'
  88. if exists("b:endwise_pattern")
  89. let beginpat = substitute(b:endwise_pattern,'&',substitute(wordchoice,'\\','\\&','g'),'g')
  90. else
  91. let beginpat = '\<'.wordchoice.'\>'
  92. endif
  93. let lnum = line('.') - 1
  94. let space = matchstr(getline(lnum),'^\s*')
  95. let col = match(getline(lnum),beginpat) + 1
  96. let word = matchstr(getline(lnum),beginpat)
  97. let endword = substitute(word,'.*',b:endwise_addition,'')
  98. let y = n.endword."\<C-O>O"
  99. let endpat = '\w\@<!'.endword.'\w\@!'
  100. if a:always
  101. return y
  102. elseif col <= 0 || synIDattr(synID(lnum,col,1),'name') !~ '^'.synpat.'$'
  103. return n
  104. elseif getline('.') !~ '^\s*#\=$'
  105. return n
  106. endif
  107. let line = s:mysearchpair(beginpat,endpat,synpat)
  108. " even is false if no end was found, or if the end found was less
  109. " indented than the current line
  110. let even = strlen(matchstr(getline(line),'^\s*')) >= strlen(space)
  111. if line == 0
  112. let even = 0
  113. endif
  114. if !even && line == line('.') + 1
  115. return y
  116. endif
  117. if even
  118. return n
  119. endif
  120. return y
  121. endfunction
  122. function! s:synname()
  123. " Checking this helps to force things to stay in sync
  124. while s:lastline < line('.')
  125. let s = synIDattr(synID(s:lastline,indent(s:lastline)+1,1),'name')
  126. let s:lastline = nextnonblank(s:lastline + 1)
  127. endwhile
  128. let s = synIDattr(synID(line('.'),col('.'),1),'name')
  129. let g:endwise_syntaxes = g:endwise_syntaxes . line('.').','.col('.')."=".s."\n"
  130. let s:lastline = line('.')
  131. return s
  132. endfunction
  133. " }}}1
  134. " vim:set sw=2 sts=2: