cucumber.vim 2.7 KB

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