codekingpro/portable-devtools
114k
1" Vim indent file2" Language: YAML3" Maintainer: Nikolai Pavlov <zyx.vim@gmail.com>4" Last Updates: Lukas Reineke, "lacygoill"5" Last Change: 2022 Jun 176" 2024 Feb 29 by Vim project: disable mulitline indent by default7" 2024 Aug 14 by Vim project: fix re-indenting when commenting out lines8" 2026 Jan 08 by Vim project: fix object indentation in array9" 2026 Jan 15 by Vim project: fix double shiftwidth from previous change10 11" Only load this indent file when no other was loaded.12if exists('b:did_indent')13 finish14endif15 16let b:did_indent = 117 18setlocal indentexpr=GetYAMLIndent(v:lnum)19setlocal indentkeys=!^F,o,O,0},0],<:>,0-20setlocal nosmartindent21 22let b:undo_indent = 'setlocal indentexpr< indentkeys< smartindent<'23 24" Only define the function once.25if exists('*GetYAMLIndent')26 finish27endif28 29let s:save_cpo = &cpo30set cpo&vim31 32function s:FindPrevLessIndentedLine(lnum, ...)33 let prevlnum = prevnonblank(a:lnum-1)34 let curindent = a:0 ? a:1 : indent(a:lnum)35 while prevlnum36 \ && indent(prevlnum) >= curindent37 \ && getline(prevlnum) !~# '^\s*#'38 let prevlnum = prevnonblank(prevlnum-1)39 endwhile40 return prevlnum41endfunction42 43function s:FindPrevLEIndentedLineMatchingRegex(lnum, regex)44 let plilnum = s:FindPrevLessIndentedLine(a:lnum, indent(a:lnum)+1)45 while plilnum && getline(plilnum) !~# a:regex46 let plilnum = s:FindPrevLessIndentedLine(plilnum)47 endwhile48 return plilnum49endfunction50 51let s:mapkeyregex = '\v^\s*\#@!\S@=%(\''%([^'']|\''\'')*\''' ..52 \ '|\"%([^"\\]|\\.)*\"' ..53 \ '|%(%(\:\ )@!.)*)\:%(\ |$)'54let s:liststartregex = '\v^\s*%(\-%(\ |$))'55 56let s:c_ns_anchor_char = '\v%([\n\r\uFEFF \t,[\]{}]@!\p)'57let s:c_ns_anchor_name = s:c_ns_anchor_char .. '+'58let s:c_ns_anchor_property = '\v\&' .. s:c_ns_anchor_name59 60let s:ns_word_char = '\v[[:alnum:]_\-]'61let s:ns_tag_char = '\v%(\x\x|' .. s:ns_word_char .. '|[#/;?:@&=+$.~*''()])'62let s:c_named_tag_handle = '\v\!' .. s:ns_word_char .. '+\!'63let s:c_secondary_tag_handle = '\v\!\!'64let s:c_primary_tag_handle = '\v\!'65let s:c_tag_handle = '\v%(' .. s:c_named_tag_handle.66 \ '|' .. s:c_secondary_tag_handle.67 \ '|' .. s:c_primary_tag_handle .. ')'68let s:c_ns_shorthand_tag = '\v' .. s:c_tag_handle .. s:ns_tag_char .. '+'69let s:c_non_specific_tag = '\v\!'70let s:ns_uri_char = '\v%(\x\x|' .. s:ns_word_char .. '\v|[#/;?:@&=+$,.!~*''()[\]])'71let s:c_verbatim_tag = '\v\!\<' .. s:ns_uri_char.. '+\>'72let s:c_ns_tag_property = '\v' .. s:c_verbatim_tag.73 \ '\v|' .. s:c_ns_shorthand_tag.74 \ '\v|' .. s:c_non_specific_tag75 76let s:block_scalar_header = '\v[|>]%([+-]?[1-9]|[1-9]?[+-])?'77 78function GetYAMLIndent(lnum)79 if a:lnum == 1 || !prevnonblank(a:lnum-1)80 return 081 endif82 83 let prevlnum = prevnonblank(a:lnum-1)84 let previndent = indent(prevlnum)85 86 let line = getline(a:lnum)87 if line =~# '^\s*#' && getline(a:lnum-1) =~# '^\s*#'88 " Comment blocks should have identical indent89 return previndent90 elseif line =~# '^\s*[\]}]'91 " Lines containing only closing braces should have previous indent92 return indent(s:FindPrevLessIndentedLine(a:lnum))93 endif94 95 " Ignore comment lines when calculating indent96 while getline(prevlnum) =~# '^\s*#'97 let prevlnum = prevnonblank(prevlnum-1)98 if !prevlnum99 return previndent100 endif101 endwhile102 103 let prevline = getline(prevlnum)104 let previndent = indent(prevlnum)105 106 " Any examples below assume that shiftwidth=2107 if prevline =~# '\v[{[:]$|[:-]\ [|>][+\-]?%(\s+\#.*|\s*)$'108 " Mapping key:109 " nested mapping: ...110 "111 " - {112 " key: [113 " list value114 " ]115 " }116 "117 " - |-118 " Block scalar without indentation indicator119 if prevline =~# '^\s*-\s.*:$'120 " Special case: list item with mapping key (- key:)121 " Need to account for the "- " prefix122 return previndent + 2 + shiftwidth()123 else124 return previndent+shiftwidth()125 endif126 elseif prevline =~# '\v[:-]\ [|>]%(\d+[+\-]?|[+\-]?\d+)%(\#.*|\s*)$'127 " - |+2128 " block scalar with indentation indicator129 "#^^ indent+2, not indent+shiftwidth130 return previndent + str2nr(matchstr(prevline,131 \'\v([:-]\ [|>])@<=[+\-]?\d+%([+\-]?%(\s+\#.*|\s*)$)@='))132 elseif prevline =~# '\v\"%([^"\\]|\\.)*\\$'133 " "Multiline string \134 " with escaped end"135 let qidx = match(prevline, '\v\"%([^"\\]|\\.)*\\')136 return virtcol([prevlnum, qidx+1])137 elseif line =~# s:liststartregex138 " List line should have indent equal to previous list line unless it was 139 " caught by one of the previous rules140 return indent(s:FindPrevLEIndentedLineMatchingRegex(a:lnum,141 \ s:liststartregex))142 elseif line =~# s:mapkeyregex143 " Same for line containing mapping key144 let prevmapline = s:FindPrevLEIndentedLineMatchingRegex(a:lnum,145 \ s:mapkeyregex)146 if getline(prevmapline) =~# '^\s*- '147 " Previous mapping key is in a list item (- key:)148 " The key effectively starts at indent + 2 (after "- ")149 " Content under it should be indented relative to the key position150 return indent(prevmapline) + 2151 else152 return indent(prevmapline)153 endif154 elseif get(g:, 'yaml_indent_multiline_scalar', 0) &&155 \ prevline =~# '^\s*- '156 " - List with157 " multiline scalar158 return previndent+2159 elseif get(g:, 'yaml_indent_multiline_scalar', 0) &&160 \ prevline =~# s:mapkeyregex .. '\v\s*%(%(' .. s:c_ns_tag_property ..161 \ '\v|' .. s:c_ns_anchor_property ..162 \ '\v|' .. s:block_scalar_header ..163 \ '\v)%(\s+|\s*%(\#.*)?$))*'164 " Mapping with: value165 " that is multiline scalar166 return previndent+shiftwidth()167 endif168 return previndent169endfunction170 171let &cpo = s:save_cpo172 