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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
|
" Vim indent file
" Language: YAML
" Maintainer: Nikolai Pavlov <zyx.vim@gmail.com>
" Only load this indent file when no other was loaded.
if exists('b:did_indent')
finish
endif
let s:save_cpo = &cpo
set cpo&vim
let b:did_indent = 1
setlocal indentexpr=GetYAMLIndent(v:lnum)
setlocal indentkeys=!^F,o,O,0#,0},0],<:>,-
setlocal nosmartindent
let b:undo_indent = 'setlocal indentexpr< indentkeys< smartindent<'
" Only define the function once.
if exists('*GetYAMLIndent')
finish
endif
if exists('*shiftwidth')
let s:shiftwidth = function('shiftwidth')
else
function s:shiftwidth()
return &shiftwidth
endfunction
endif
function s:FindPrevLessIndentedLine(lnum, ...)
let prevlnum = prevnonblank(a:lnum-1)
let curindent = a:0 ? a:1 : indent(a:lnum)
while prevlnum
\&& indent(prevlnum) >= curindent
\&& getline(prevlnum) !~# '^\s*#'
let prevlnum = prevnonblank(prevlnum-1)
endwhile
return prevlnum
endfunction
function s:FindPrevLEIndentedLineMatchingRegex(lnum, regex)
let plilnum = s:FindPrevLessIndentedLine(a:lnum, indent(a:lnum)+1)
while plilnum && getline(plilnum) !~# a:regex
let plilnum = s:FindPrevLessIndentedLine(plilnum)
endwhile
return plilnum
endfunction
let s:mapkeyregex='\v^\s*%(\''%([^'']|'''')*\'''.
\ '|\"%([^"\\]|\\.)*\"'.
\ '|%(%(\:\ )@!.)*)\:%(\ |$)'
let s:liststartregex='\v^\s*%(\-%(\ |$))'
function GetYAMLIndent(lnum)
if a:lnum == 1 || !prevnonblank(a:lnum-1)
return 0
endif
let prevlnum = prevnonblank(a:lnum-1)
let previndent = indent(prevlnum)
let line = getline(a:lnum)
if line =~# '^\s*#' && getline(a:lnum-1) =~# '^\s*#'
" Comment blocks should have identical indent
return previndent
elseif line =~# '^\s*[\]}]'
" Lines containing only closing braces should have previous indent
return indent(s:FindPrevLessIndentedLine(a:lnum))
endif
" Ignore comment lines when calculating indent
while getline(prevlnum) =~# '^\s*#'
let prevlnum = prevnonblank(prevlnum-1)
if !prevlnum
return previndent
endif
endwhile
let prevline = getline(prevlnum)
let previndent = indent(prevlnum)
" Any examples below assume that shiftwidth=2
if prevline =~# '\v[{[:]$|[:-]\ [|>][+\-]?%(\s+\#.*|\s*)$'
" Mapping key:
" nested mapping: ...
"
" - {
" key: [
" list value
" ]
" }
"
" - |-
" Block scalar without indentation indicator
return previndent+s:shiftwidth()
elseif prevline =~# '\v[:-]\ [|>]%(\d+[+\-]?|[+\-]?\d+)%(\#.*|\s*)$'
" - |+2
" block scalar with indentation indicator
"#^^ indent+2, not indent+shiftwidth
return previndent + str2nr(matchstr(prevline,
\'\v([:-]\ [|>])@<=[+\-]?\d+%([+\-]?%(\s+\#.*|\s*)$)@='))
elseif prevline =~# '\v\"%([^"\\]|\\.)*\\$'
" "Multiline string \
" with escaped end"
let qidx = match(prevline, '\v\"%([^"\\]|\\.)*\\')
return virtcol([prevlnum, qidx+1])
elseif line =~# s:liststartregex
" List line should have indent equal to previous list line unless it was
" caught by one of the previous rules
return indent(s:FindPrevLEIndentedLineMatchingRegex(a:lnum,
\ s:liststartregex))
elseif line =~# s:mapkeyregex
" Same for line containing mapping key
return indent(s:FindPrevLEIndentedLineMatchingRegex(a:lnum,
\ s:mapkeyregex))
elseif prevline =~# '^\s*- '
" - List with
" multiline scalar
return previndent+2
elseif prevline =~# s:mapkeyregex
" Mapping with: value
" that is multiline scalar
return previndent+s:shiftwidth()
endif
return previndent
endfunction
let &cpo = s:save_cpo
|