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