1" Vim indent file 2" Language: YAML 3" Maintainer: Nikolai Pavlov <[email protected]> 4" Last Change: 2015 Nov 01 5 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) 17setlocal indentkeys=!^F,o,O,0#,0},0],<:>,0- 18setlocal 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 119 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 126 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 139