Install vim73
[git/jnareb-git.git] / share / vim / vim73 / ftplugin / cucumber.vim
bloba29d46a039b5d1814903265280f01615f57a7f6d
1 " Vim filetype plugin
2 " Language:     Cucumber
3 " Maintainer:   Tim Pope <vimNOSPAM@tpope.org>
4 " Last Change:  2010 Aug 09
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
12 setlocal formatoptions-=t formatoptions+=croql
13 setlocal comments=:# commentstring=#\ %s
14 setlocal omnifunc=CucumberComplete
16 let b:undo_ftplugin = "setl fo< com< cms< ofu<"
18 let b:cucumber_root = expand('%:p:h:s?.*[\/]\%(features\|stories\)\zs[\/].*??')
20 if !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! iunmap! <C-]>| sil! iunmap! <C-W>]| sil! iunmap! <C-W><C-]>| sil! iunmap! <C-W>}"
26 endif
28 function! 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
38 endfunction
40 function! 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
55 endfunction
57 function! 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)')
64 endfunction
66 function! 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
88 endfunction
90 function! s:bsub(target,pattern,replacement)
91   return  substitute(a:target,'\C\\\@<!'.a:pattern,a:replacement,'g')
92 endfunction
94 function! 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)
130 endfunction
132 " vim:set sts=2 sw=2: