neovim

Neovim text editor
git clone https://git.dasho.dev/neovim.git
Log | Files | Refs | README

cucumber.vim (5115B)


      1 " Vim filetype plugin
      2 " Language:	Cucumber
      3 " Maintainer:	Tim Pope <vimNOSPAM@tpope.org>
      4 " Last Change:	2016 Aug 29
      5 
      6 " Only do this when not done yet for this buffer
      7 if (exists("b:did_ftplugin"))
      8  finish
      9 endif
     10 let b:did_ftplugin = 1
     11 
     12 let s:keepcpo= &cpo
     13 set cpo&vim
     14 
     15 setlocal formatoptions-=t formatoptions+=croql
     16 setlocal comments=:# commentstring=#\ %s
     17 setlocal omnifunc=CucumberComplete
     18 
     19 let b:undo_ftplugin = "setl fo< com< cms< ofu<"
     20 
     21 let b:cucumber_root = expand('%:p:h:s?.*[\/]\%(features\|stories\)\zs[\/].*??')
     22 if !exists("b:cucumber_steps_glob")
     23  let b:cucumber_steps_glob = b:cucumber_root.'/**/*.rb'
     24 endif
     25 
     26 if !exists("g:no_plugin_maps") && !exists("g:no_cucumber_maps")
     27  cnoremap <SID>foldopen <Bar>if &foldopen =~# 'tag'<Bar>exe 'norm! zv'<Bar>endif
     28  nnoremap <silent> <script> <buffer> [<C-D>      :<C-U>exe <SID>jump('edit',v:count)<SID>foldopen<CR>
     29  nnoremap <silent> <script> <buffer> ]<C-D>      :<C-U>exe <SID>jump('edit',v:count)<SID>foldopen<CR>
     30  nnoremap <silent> <script> <buffer> <C-W>d      :<C-U>exe <SID>jump('split',v:count)<SID>foldopen<CR>
     31  nnoremap <silent> <script> <buffer> <C-W><C-D>  :<C-U>exe <SID>jump('split',v:count)<SID>foldopen<CR>
     32  nnoremap <silent> <script> <buffer> [d          :<C-U>exe <SID>jump('pedit',v:count)<CR>
     33  nnoremap <silent> <script> <buffer> ]d          :<C-U>exe <SID>jump('pedit',v:count)<CR>
     34  let b:undo_ftplugin .=
     35        \ "|sil! nunmap <buffer> [<C-D>" .
     36        \ "|sil! nunmap <buffer> ]<C-D>" .
     37        \ "|sil! nunmap <buffer> <C-W>d" .
     38        \ "|sil! nunmap <buffer> <C-W><C-D>" .
     39        \ "|sil! nunmap <buffer> [d" .
     40        \ "|sil! nunmap <buffer> ]d"
     41 endif
     42 
     43 function! s:jump(command,count)
     44  let steps = s:steps('.')
     45  if len(steps) == 0 || len(steps) < a:count
     46    return 'echoerr "No matching step found"'
     47  elseif len(steps) > 1 && !a:count
     48    return 'echoerr "Multiple matching steps found"'
     49  else
     50    let c = a:count ? a:count-1 : 0
     51    return a:command.' +'.steps[c][1].' '.escape(steps[c][0],' %#')
     52  endif
     53 endfunction
     54 
     55 function! s:allsteps()
     56  let step_pattern = '\C^\s*\K\k*\>\s*(\=\s*\zs\S.\{-\}\ze\s*)\=\s*\%(do\|{\)\s*\%(|[^|]*|\s*\)\=\%($\|#\)'
     57  let steps = []
     58  for file in split(glob(b:cucumber_steps_glob),"\n")
     59    let lines = readfile(file)
     60    let num = 0
     61    for line in lines
     62      let num += 1
     63      if line =~ step_pattern
     64        let type = matchstr(line,'\w\+')
     65        let steps += [[file,num,type,matchstr(line,step_pattern)]]
     66      endif
     67    endfor
     68  endfor
     69  return steps
     70 endfunction
     71 
     72 function! s:steps(lnum)
     73  let c = match(getline(a:lnum), '\S') + 1
     74  while synIDattr(synID(a:lnum,c,1),'name') !~# '^$\|Region$'
     75    let c = c + 1
     76  endwhile
     77  let step = matchstr(getline(a:lnum)[c-1 : -1],'^\s*\zs.\{-\}\ze\s*$')
     78  return filter(s:allsteps(),'s:stepmatch(v:val[3],step)')
     79 endfunction
     80 
     81 function! s:stepmatch(receiver,target)
     82  if a:receiver =~ '^[''"].*[''"]$'
     83    let pattern = '^'.escape(substitute(a:receiver[1:-2],'$\w\+','(.*)','g'),'/').'$'
     84  elseif a:receiver =~ '^/.*/$'
     85    let pattern = a:receiver[1:-2]
     86  elseif a:receiver =~ '^%r..*.$'
     87    let pattern = escape(a:receiver[3:-2],'/')
     88  else
     89    return 0
     90  endif
     91  try
     92    let vimpattern = substitute(substitute(pattern,'\\\@<!(?:','%(','g'),'\\\@<!\*?','{-}','g')
     93    if a:target =~# '\v'.vimpattern
     94      return 1
     95    endif
     96  catch
     97  endtry
     98  if has("ruby") && pattern !~ '\\\@<!#{'
     99    ruby VIM.command("return #{if (begin; Kernel.eval('/'+VIM.evaluate('pattern')+'/'); rescue SyntaxError; end) === VIM.evaluate('a:target') then 1 else 0 end}")
    100  else
    101    return 0
    102  endif
    103 endfunction
    104 
    105 function! s:bsub(target,pattern,replacement)
    106  return  substitute(a:target,'\C\\\@<!'.a:pattern,a:replacement,'g')
    107 endfunction
    108 
    109 function! CucumberComplete(findstart,base) abort
    110  let indent = indent('.')
    111  let group = synIDattr(synID(line('.'),indent+1,1),'name')
    112  let type = matchstr(group,'\Ccucumber\zs\%(Given\|When\|Then\)')
    113  let e = matchend(getline('.'),'^\s*\S\+\s')
    114  if type == '' || col('.') < col('$') || e < 0
    115    return -1
    116  endif
    117  if a:findstart
    118    return e
    119  endif
    120  let steps = []
    121  for step in s:allsteps()
    122    if step[2] ==# type
    123      if step[3] =~ '^[''"]'
    124        let steps += [step[3][1:-2]]
    125      elseif step[3] =~ '^/\^.*\$/$'
    126        let pattern = step[3][2:-3]
    127        let pattern = substitute(pattern,'\C^(?:|I )','I ','')
    128        let pattern = s:bsub(pattern,'\\[Sw]','w')
    129        let pattern = s:bsub(pattern,'\\d','1')
    130        let pattern = s:bsub(pattern,'\\[sWD]',' ')
    131        let pattern = s:bsub(pattern,'\[\^\\\="\]','_')
    132        let pattern = s:bsub(pattern,'[[:alnum:]. _-][?*]?\=','')
    133        let pattern = s:bsub(pattern,'\[\([^^]\).\{-\}\]','\1')
    134        let pattern = s:bsub(pattern,'+?\=','')
    135        let pattern = s:bsub(pattern,'(\([[:alnum:]. -]\{-\}\))','\1')
    136        let pattern = s:bsub(pattern,'\\\([[:punct:]]\)','\1')
    137        if pattern !~ '[\\()*?]'
    138          let steps += [pattern]
    139        endif
    140      endif
    141    endif
    142  endfor
    143  call filter(steps,'strpart(v:val,0,strlen(a:base)) ==# a:base')
    144  return sort(steps)
    145 endfunction
    146 
    147 let &cpo = s:keepcpo
    148 unlet s:keepcpo
    149 
    150 " vim:set sts=2 sw=2: