" Vim indent file " Language: YAML " Maintainer: Nikolai Pavlov " 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