123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899 |
- " Vim indent file
- " Language: Cucumber
- " Maintainer: Tim Pope <vimNOSPAM@tpope.org>
- " Last Change: 2023 Dec 28
- if exists("b:did_indent")
- finish
- endif
- let b:did_indent = 1
- setlocal autoindent
- setlocal indentexpr=GetCucumberIndent()
- setlocal indentkeys=o,O,*<Return>,<:>,0<Bar>,0#,=,!^F
- let b:undo_indent = 'setl ai< inde< indk<'
- " Only define the function once.
- if exists("*GetCucumberIndent")
- finish
- endif
- let s:headings = {
- \ 'Feature': 'feature',
- \ 'Rule': 'rule',
- \ 'Background': 'bg_or_scenario',
- \ 'Scenario': 'bg_or_scenario',
- \ 'ScenarioOutline': 'bg_or_scenario',
- \ 'Examples': 'examples',
- \ 'Scenarios': 'examples'}
- function! s:Line(lnum) abort
- if getline(a:lnum) =~# ':'
- let group = matchstr(synIDattr(synID(a:lnum,1+indent(a:lnum), 1), 'name'), '^cucumber\zs.*')
- if !has_key(s:headings, group)
- let group = substitute(matchstr(getline(a:lnum), '^\s*\zs\%([^:]\+\)\ze:\S\@!'), '\s\+', '', 'g')
- endif
- else
- let group = ''
- endif
- let char = matchstr(getline(a:lnum), '^\s*\zs[[:punct:]]')
- return {
- \ 'lnum': a:lnum,
- \ 'indent': indent(a:lnum),
- \ 'heading': get(s:headings, group, ''),
- \ 'tag': char ==# '@',
- \ 'table': char ==# '|',
- \ 'comment': char ==# '#',
- \ }
- endfunction
- function! GetCucumberIndent(...) abort
- let lnum = a:0 ? a:1 : v:lnum
- let sw = shiftwidth()
- let prev = s:Line(prevnonblank(lnum-1))
- let curr = s:Line(lnum)
- let next = s:Line(nextnonblank(lnum+1))
- if curr.heading ==# 'feature'
- " feature heading
- return 0
- elseif curr.heading ==# 'examples'
- " examples heading
- return 2 * sw
- elseif curr.heading ==# 'bg_or_scenario'
- " background, scenario or outline heading
- return sw
- elseif prev.heading ==# 'feature'
- " line after feature heading
- return sw
- elseif prev.heading ==# 'examples'
- " line after examples heading
- return 3 * sw
- elseif prev.heading ==# 'bg_or_scenario'
- " line after background, scenario or outline heading
- return 2 * sw
- elseif (curr.tag || curr.comment) && (next.heading ==# 'feature' || prev.indent <= 0)
- " tag or comment before a feature heading
- return 0
- elseif curr.tag
- " other tags
- return sw
- elseif (curr.table || curr.comment) && prev.table
- " mid-table
- " preserve indent
- return prev.indent
- elseif curr.table && !prev.table
- " first line of a table, relative indent
- return prev.indent + sw
- elseif !curr.table && prev.table
- " line after a table, relative unindent
- return prev.indent - sw
- elseif curr.comment && getline(v:lnum-1) =~# '^\s*$' && next.heading ==# 'bg_or_scenario'
- " comments on scenarios
- return sw
- endif
- return prev.indent < 0 ? 0 : prev.indent
- endfunction
- " vim:set sts=2 sw=2:
|