blob: aa4906ce0a3aee2e3c8708857321b3fcd9914012 [file] [log] [blame]
Bram Moolenaar34feacb2012-12-05 19:01:43 +01001" Vim indent file
2" Language: YAML
3" Maintainer: Nikolai Pavlov <zyx.vim@gmail.com>
Bram Moolenaarb4ff5182015-11-10 21:15:48 +01004" Last Change: 2015 Nov 01
Bram Moolenaar34feacb2012-12-05 19:01:43 +01005
6" Only load this indent file when no other was loaded.
7if exists('b:did_indent')
8 finish
9endif
10
11let s:save_cpo = &cpo
12set cpo&vim
13
14let b:did_indent = 1
15
16setlocal indentexpr=GetYAMLIndent(v:lnum)
Bram Moolenaarb4ff5182015-11-10 21:15:48 +010017setlocal indentkeys=!^F,o,O,0#,0},0],<:>,0-
Bram Moolenaar34feacb2012-12-05 19:01:43 +010018setlocal nosmartindent
19
20let b:undo_indent = 'setlocal indentexpr< indentkeys< smartindent<'
21
22" Only define the function once.
23if exists('*GetYAMLIndent')
24 finish
25endif
26
27if exists('*shiftwidth')
28 let s:shiftwidth = function('shiftwidth')
29else
30 function s:shiftwidth()
31 return &shiftwidth
32 endfunction
33endif
34
35function s:FindPrevLessIndentedLine(lnum, ...)
36 let prevlnum = prevnonblank(a:lnum-1)
37 let curindent = a:0 ? a:1 : indent(a:lnum)
38 while prevlnum
39 \&& indent(prevlnum) >= curindent
40 \&& getline(prevlnum) !~# '^\s*#'
41 let prevlnum = prevnonblank(prevlnum-1)
42 endwhile
43 return prevlnum
44endfunction
45
46function s:FindPrevLEIndentedLineMatchingRegex(lnum, regex)
47 let plilnum = s:FindPrevLessIndentedLine(a:lnum, indent(a:lnum)+1)
48 while plilnum && getline(plilnum) !~# a:regex
49 let plilnum = s:FindPrevLessIndentedLine(plilnum)
50 endwhile
51 return plilnum
52endfunction
53
54let s:mapkeyregex='\v^\s*%(\''%([^'']|'''')*\'''.
55 \ '|\"%([^"\\]|\\.)*\"'.
56 \ '|%(%(\:\ )@!.)*)\:%(\ |$)'
57let s:liststartregex='\v^\s*%(\-%(\ |$))'
58
59function GetYAMLIndent(lnum)
60 if a:lnum == 1 || !prevnonblank(a:lnum-1)
61 return 0
62 endif
63
64 let prevlnum = prevnonblank(a:lnum-1)
65 let previndent = indent(prevlnum)
66
67 let line = getline(a:lnum)
68 if line =~# '^\s*#' && getline(a:lnum-1) =~# '^\s*#'
69 " Comment blocks should have identical indent
70 return previndent
71 elseif line =~# '^\s*[\]}]'
72 " Lines containing only closing braces should have previous indent
73 return indent(s:FindPrevLessIndentedLine(a:lnum))
74 endif
75
76 " Ignore comment lines when calculating indent
77 while getline(prevlnum) =~# '^\s*#'
78 let prevlnum = prevnonblank(prevlnum-1)
79 if !prevlnum
80 return previndent
81 endif
82 endwhile
83
84 let prevline = getline(prevlnum)
85 let previndent = indent(prevlnum)
86
87 " Any examples below assume that shiftwidth=2
88 if prevline =~# '\v[{[:]$|[:-]\ [|>][+\-]?%(\s+\#.*|\s*)$'
89 " Mapping key:
90 " nested mapping: ...
91 "
92 " - {
93 " key: [
94 " list value
95 " ]
96 " }
97 "
98 " - |-
99 " Block scalar without indentation indicator
100 return previndent+s:shiftwidth()
101 elseif prevline =~# '\v[:-]\ [|>]%(\d+[+\-]?|[+\-]?\d+)%(\#.*|\s*)$'
102 " - |+2
103 " block scalar with indentation indicator
104 "#^^ indent+2, not indent+shiftwidth
105 return previndent + str2nr(matchstr(prevline,
106 \'\v([:-]\ [|>])@<=[+\-]?\d+%([+\-]?%(\s+\#.*|\s*)$)@='))
107 elseif prevline =~# '\v\"%([^"\\]|\\.)*\\$'
108 " "Multiline string \
109 " with escaped end"
110 let qidx = match(prevline, '\v\"%([^"\\]|\\.)*\\')
111 return virtcol([prevlnum, qidx+1])
112 elseif line =~# s:liststartregex
113 " List line should have indent equal to previous list line unless it was
114 " caught by one of the previous rules
115 return indent(s:FindPrevLEIndentedLineMatchingRegex(a:lnum,
116 \ s:liststartregex))
117 elseif line =~# s:mapkeyregex
118 " Same for line containing mapping key
Bram Moolenaarca635012015-09-25 20:34:21 +0200119 let prevmapline = s:FindPrevLEIndentedLineMatchingRegex(a:lnum,
120 \ s:mapkeyregex)
121 if getline(prevmapline) =~# '^\s*- '
122 return indent(prevmapline) + 2
123 else
124 return indent(prevmapline)
125 endif
Bram Moolenaar34feacb2012-12-05 19:01:43 +0100126 elseif prevline =~# '^\s*- '
127 " - List with
128 " multiline scalar
129 return previndent+2
130 elseif prevline =~# s:mapkeyregex
131 " Mapping with: value
132 " that is multiline scalar
133 return previndent+s:shiftwidth()
134 endif
135 return previndent
136endfunction
137
138let &cpo = s:save_cpo