cucumber.vim (2960B)
1 " Vim indent file 2 " Language: Cucumber 3 " Maintainer: Tim Pope <vimNOSPAM@tpope.org> 4 " Last Change: 2023 Dec 28 5 " 2025 Apr 16 by Vim Project (set 'cpoptions' for line continuation, #17121) 6 7 if exists("b:did_indent") 8 finish 9 endif 10 let b:did_indent = 1 11 let s:cpo_save = &cpo 12 set cpo&vim 13 14 setlocal autoindent 15 setlocal indentexpr=GetCucumberIndent() 16 setlocal indentkeys=o,O,*<Return>,<:>,0<Bar>,0#,=,!^F 17 18 let b:undo_indent = 'setl ai< inde< indk<' 19 20 " Only define the function once. 21 if exists("*GetCucumberIndent") 22 finish 23 endif 24 25 let s:headings = { 26 \ 'Feature': 'feature', 27 \ 'Rule': 'rule', 28 \ 'Background': 'bg_or_scenario', 29 \ 'Scenario': 'bg_or_scenario', 30 \ 'ScenarioOutline': 'bg_or_scenario', 31 \ 'Examples': 'examples', 32 \ 'Scenarios': 'examples'} 33 34 function! s:Line(lnum) abort 35 if getline(a:lnum) =~# ':' 36 let group = matchstr(synIDattr(synID(a:lnum,1+indent(a:lnum), 1), 'name'), '^cucumber\zs.*') 37 if !has_key(s:headings, group) 38 let group = substitute(matchstr(getline(a:lnum), '^\s*\zs\%([^:]\+\)\ze:\S\@!'), '\s\+', '', 'g') 39 endif 40 else 41 let group = '' 42 endif 43 let char = matchstr(getline(a:lnum), '^\s*\zs[[:punct:]]') 44 return { 45 \ 'lnum': a:lnum, 46 \ 'indent': indent(a:lnum), 47 \ 'heading': get(s:headings, group, ''), 48 \ 'tag': char ==# '@', 49 \ 'table': char ==# '|', 50 \ 'comment': char ==# '#', 51 \ } 52 endfunction 53 54 function! GetCucumberIndent(...) abort 55 let lnum = a:0 ? a:1 : v:lnum 56 let sw = shiftwidth() 57 let prev = s:Line(prevnonblank(lnum-1)) 58 let curr = s:Line(lnum) 59 let next = s:Line(nextnonblank(lnum+1)) 60 if curr.heading ==# 'feature' 61 " feature heading 62 return 0 63 elseif curr.heading ==# 'examples' 64 " examples heading 65 return 2 * sw 66 elseif curr.heading ==# 'bg_or_scenario' 67 " background, scenario or outline heading 68 return sw 69 elseif prev.heading ==# 'feature' 70 " line after feature heading 71 return sw 72 elseif prev.heading ==# 'examples' 73 " line after examples heading 74 return 3 * sw 75 elseif prev.heading ==# 'bg_or_scenario' 76 " line after background, scenario or outline heading 77 return 2 * sw 78 elseif (curr.tag || curr.comment) && (next.heading ==# 'feature' || prev.indent <= 0) 79 " tag or comment before a feature heading 80 return 0 81 elseif curr.tag 82 " other tags 83 return sw 84 elseif (curr.table || curr.comment) && prev.table 85 " mid-table 86 " preserve indent 87 return prev.indent 88 elseif curr.table && !prev.table 89 " first line of a table, relative indent 90 return prev.indent + sw 91 elseif !curr.table && prev.table 92 " line after a table, relative unindent 93 return prev.indent - sw 94 elseif curr.comment && getline(v:lnum-1) =~# '^\s*$' && next.heading ==# 'bg_or_scenario' 95 " comments on scenarios 96 return sw 97 endif 98 return prev.indent < 0 ? 0 : prev.indent 99 endfunction 100 101 let &cpo = s:cpo_save 102 unlet s:cpo_save 103 104 " vim:set sts=2 sw=2: