blob: f4848d1c60d5a3f6403b8c0b3b71440b117926b7 [file] [log] [blame]
Bram Moolenaar5e3dae82010-03-02 16:19:40 +01001" Vim filetype plugin
2" Language: Cucumber
3" Maintainer: Tim Pope <vimNOSPAM@tpope.org>
Bram Moolenaar89bcfda2016-08-30 23:26:57 +02004" Last Change: 2016 Aug 29
Bram Moolenaar5e3dae82010-03-02 16:19:40 +01005
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
Bram Moolenaar543b7ef2013-06-01 14:50:56 +020012let s:keepcpo= &cpo
13set cpo&vim
14
Bram Moolenaar5e3dae82010-03-02 16:19:40 +010015setlocal formatoptions-=t formatoptions+=croql
16setlocal comments=:# commentstring=#\ %s
17setlocal omnifunc=CucumberComplete
18
19let b:undo_ftplugin = "setl fo< com< cms< ofu<"
20
21let b:cucumber_root = expand('%:p:h:s?.*[\/]\%(features\|stories\)\zs[\/].*??')
Bram Moolenaar89bcfda2016-08-30 23:26:57 +020022if !exists("b:cucumber_steps_glob")
23 let b:cucumber_steps_glob = b:cucumber_root.'/**/*.rb'
24endif
Bram Moolenaar5e3dae82010-03-02 16:19:40 +010025
26if !exists("g:no_plugin_maps") && !exists("g:no_cucumber_maps")
Bram Moolenaar89bcfda2016-08-30 23:26:57 +020027 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 Moolenaar543b7ef2013-06-01 14:50:56 +020034 let b:undo_ftplugin .=
Bram Moolenaar543b7ef2013-06-01 14:50:56 +020035 \ "|sil! nunmap <buffer> [<C-D>" .
36 \ "|sil! nunmap <buffer> ]<C-D>" .
Bram Moolenaar543b7ef2013-06-01 14:50:56 +020037 \ "|sil! nunmap <buffer> <C-W>d" .
38 \ "|sil! nunmap <buffer> <C-W><C-D>" .
Bram Moolenaar543b7ef2013-06-01 14:50:56 +020039 \ "|sil! nunmap <buffer> [d" .
40 \ "|sil! nunmap <buffer> ]d"
Bram Moolenaar5e3dae82010-03-02 16:19:40 +010041endif
42
43function! 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
53endfunction
54
55function! s:allsteps()
Bram Moolenaar543b7ef2013-06-01 14:50:56 +020056 let step_pattern = '\C^\s*\K\k*\>\s*(\=\s*\zs\S.\{-\}\ze\s*)\=\s*\%(do\|{\)\s*\%(|[^|]*|\s*\)\=\%($\|#\)'
Bram Moolenaar5e3dae82010-03-02 16:19:40 +010057 let steps = []
Bram Moolenaar89bcfda2016-08-30 23:26:57 +020058 for file in split(glob(b:cucumber_steps_glob),"\n")
Bram Moolenaar5e3dae82010-03-02 16:19:40 +010059 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
70endfunction
71
72function! s:steps(lnum)
Bram Moolenaar543b7ef2013-06-01 14:50:56 +020073 let c = match(getline(a:lnum), '\S') + 1
Bram Moolenaar5e3dae82010-03-02 16:19:40 +010074 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)')
79endfunction
80
81function! 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 Moolenaar6af737f2010-08-09 20:13:35 +020098 if has("ruby") && pattern !~ '\\\@<!#{'
Bram Moolenaar5e3dae82010-03-02 16:19:40 +010099 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
103endfunction
104
105function! s:bsub(target,pattern,replacement)
106 return substitute(a:target,'\C\\\@<!'.a:pattern,a:replacement,'g')
107endfunction
108
109function! 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)
145endfunction
146
Bram Moolenaar543b7ef2013-06-01 14:50:56 +0200147let &cpo = s:keepcpo
148unlet s:keepcpo
149
Bram Moolenaar5e3dae82010-03-02 16:19:40 +0100150" vim:set sts=2 sw=2: