Bram Moolenaar | 5e3dae8 | 2010-03-02 16:19:40 +0100 | [diff] [blame] | 1 | " Vim filetype plugin |
| 2 | " Language: Cucumber |
| 3 | " Maintainer: Tim Pope <vimNOSPAM@tpope.org> |
Bram Moolenaar | 89bcfda | 2016-08-30 23:26:57 +0200 | [diff] [blame] | 4 | " Last Change: 2016 Aug 29 |
Bram Moolenaar | 5e3dae8 | 2010-03-02 16:19:40 +0100 | [diff] [blame] | 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 | |
Bram Moolenaar | 543b7ef | 2013-06-01 14:50:56 +0200 | [diff] [blame] | 12 | let s:keepcpo= &cpo |
| 13 | set cpo&vim |
| 14 | |
Bram Moolenaar | 5e3dae8 | 2010-03-02 16:19:40 +0100 | [diff] [blame] | 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[\/].*??') |
Bram Moolenaar | 89bcfda | 2016-08-30 23:26:57 +0200 | [diff] [blame] | 22 | if !exists("b:cucumber_steps_glob") |
| 23 | let b:cucumber_steps_glob = b:cucumber_root.'/**/*.rb' |
| 24 | endif |
Bram Moolenaar | 5e3dae8 | 2010-03-02 16:19:40 +0100 | [diff] [blame] | 25 | |
| 26 | if !exists("g:no_plugin_maps") && !exists("g:no_cucumber_maps") |
Bram Moolenaar | 89bcfda | 2016-08-30 23:26:57 +0200 | [diff] [blame] | 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> |
Bram Moolenaar | 543b7ef | 2013-06-01 14:50:56 +0200 | [diff] [blame] | 34 | let b:undo_ftplugin .= |
Bram Moolenaar | 543b7ef | 2013-06-01 14:50:56 +0200 | [diff] [blame] | 35 | \ "|sil! nunmap <buffer> [<C-D>" . |
| 36 | \ "|sil! nunmap <buffer> ]<C-D>" . |
Bram Moolenaar | 543b7ef | 2013-06-01 14:50:56 +0200 | [diff] [blame] | 37 | \ "|sil! nunmap <buffer> <C-W>d" . |
| 38 | \ "|sil! nunmap <buffer> <C-W><C-D>" . |
Bram Moolenaar | 543b7ef | 2013-06-01 14:50:56 +0200 | [diff] [blame] | 39 | \ "|sil! nunmap <buffer> [d" . |
| 40 | \ "|sil! nunmap <buffer> ]d" |
Bram Moolenaar | 5e3dae8 | 2010-03-02 16:19:40 +0100 | [diff] [blame] | 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() |
Bram Moolenaar | 543b7ef | 2013-06-01 14:50:56 +0200 | [diff] [blame] | 56 | let step_pattern = '\C^\s*\K\k*\>\s*(\=\s*\zs\S.\{-\}\ze\s*)\=\s*\%(do\|{\)\s*\%(|[^|]*|\s*\)\=\%($\|#\)' |
Bram Moolenaar | 5e3dae8 | 2010-03-02 16:19:40 +0100 | [diff] [blame] | 57 | let steps = [] |
Bram Moolenaar | 89bcfda | 2016-08-30 23:26:57 +0200 | [diff] [blame] | 58 | for file in split(glob(b:cucumber_steps_glob),"\n") |
Bram Moolenaar | 5e3dae8 | 2010-03-02 16:19:40 +0100 | [diff] [blame] | 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) |
Bram Moolenaar | 543b7ef | 2013-06-01 14:50:56 +0200 | [diff] [blame] | 73 | let c = match(getline(a:lnum), '\S') + 1 |
Bram Moolenaar | 5e3dae8 | 2010-03-02 16:19:40 +0100 | [diff] [blame] | 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 |
Bram Moolenaar | 6af737f | 2010-08-09 20:13:35 +0200 | [diff] [blame] | 98 | if has("ruby") && pattern !~ '\\\@<!#{' |
Bram Moolenaar | 5e3dae8 | 2010-03-02 16:19:40 +0100 | [diff] [blame] | 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 | |
Bram Moolenaar | 543b7ef | 2013-06-01 14:50:56 +0200 | [diff] [blame] | 147 | let &cpo = s:keepcpo |
| 148 | unlet s:keepcpo |
| 149 | |
Bram Moolenaar | 5e3dae8 | 2010-03-02 16:19:40 +0100 | [diff] [blame] | 150 | " vim:set sts=2 sw=2: |