summaryrefslogtreecommitdiffstats
path: root/indent/plantuml.vim
blob: 414ea9893b56de047d96ccb87fb1db1e08525240 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
let files = filter(globpath(&rtp, 'indent/plantuml.vim', 1, 1), { _, v -> v !~ "vim-polyglot" && v !~ $VIMRUNTIME && v !~ "after" })
if len(files) > 0
  exec 'source ' . files[0]
  finish
endif
if !exists('g:polyglot_disabled') || index(g:polyglot_disabled, 'plantuml') == -1

scriptencoding utf-8
" Vim indent file
" Language:     PlantUML
" Maintainer:   Anders Thøgersen <first name at bladre dot dk>
" License:      VIM LICENSE

if exists('b:did_indent')
  finish
endif
let b:did_indent = 1

setlocal indentexpr=GetPlantUMLIndent()
setlocal indentkeys=o,O,<CR>,<:>,!^F,0end,0else,}

" only define the indent code once
if exists('*GetPlantUMLIndent')
  finish
endif

let s:decIndent = '^\s*\%(end\|else\|}\)'

function! GetPlantUMLIndent(...) abort
  "for current line, use arg if given or v:lnum otherwise
  let clnum = a:0 ? a:1 : v:lnum

  if !s:insidePlantUMLTags(clnum)
    return indent(clnum)
  endif

  let pnum = prevnonblank(clnum-1)
  let pindent = indent(pnum)
  let pline = getline(pnum)
  let cline = getline(clnum)

  let s:incIndent = s:getIncIndent()

  if cline =~ s:decIndent
    if pline =~ s:incIndent
      return pindent
    else
      return pindent - shiftwidth()
    endif

  elseif pline =~ s:incIndent
    return pindent + shiftwidth()
  endif

  return pindent

endfunction

function! s:insidePlantUMLTags(lnum) abort
  call cursor(a:lnum, 1)
  return search('@startuml', 'Wbn') && search('@enduml', 'Wn')
endfunction

function! s:listSyntax(syntaxKeyword) abort
  " Get a list of words assigned to a syntax keyword
  " The 'syntax list <syntax keyword>' command returns
  " a string with the keyword itself, followed by xxx,
  " on which we can split to extract the keywords string.
  " This string must then be split on whitespace
  let syntaxWords = split(
        \ execute('syntax list ' . a:syntaxKeyword),
        \ a:syntaxKeyword . ' xxx ')[-1]
  return split(syntaxWords)
endfunction

function! s:typeKeywordIncPattern() abort
  " Extract keywords for plantumlTypeKeyword, returning the inc pattern
  let syntaxWords = join(s:listSyntax('plantumlTypeKeyword'), '\\\|')
  return '^\s*\%(' . syntaxWords . '\)\>.*{'
endfunction

function! s:getIncIndent() abort
  " Function to determine the s:incIndent pattern
  return
        \ '^\s*\%(artifact\|class\|cloud\|database\|entity\|enum\|file\|folder\|frame\|interface\|namespace\|node\|object\|package\|partition\|rectangle\|skinparam\|state\|storage\|together\)\>.*{\s*$\|' .
        \ '^\s*\%(loop\|alt\|opt\|group\|critical\|else\|legend\|box\|if\|while\|fork\|split\)\>\|' .
        \ '^\s*ref\>[^:]*$\|' .
        \ '^\s*[hr]\?note\>\%(\%("[^"]*" \<as\>\)\@![^:]\)*$\|' .
        \ '^\s*title\s*$\|' .
        \ '^\s*skinparam\>.*{\s*$\|' .
        \ s:typeKeywordIncPattern()
endfunction

endif