view runtime/indent/yaml.vim @ 34456:e3d2ba1fd1a3

runtime(yaml): disable multiline_scalar detection by default Commit: https://github.com/vim/vim/commit/b4eb3f1e44896b12fdfa3885a78c6eaa181eaeff Author: Christian Brabandt <cb@256bit.org> Date: Thu Feb 29 17:23:51 2024 +0100 runtime(yaml): disable multiline_scalar detection by default There have been many complaints about Yaml indenting too much, because it considers values to be multi-line by default, which leads to unintended indenting for (apparently most) users. So let's hide this feature behind the new feature flag, keep it simple and prefer single line value key pairs by default. If you want the old behaviour, set the following value: > :let g:yaml_indent_multiline_scalar = 1 If not set, it will indent the same as the previous line. closes #13845 Signed-off-by: Christian Brabandt <cb@256bit.org>
author Christian Brabandt <cb@256bit.org>
date Thu, 29 Feb 2024 17:30:10 +0100
parents ebed259f919f
children
line wrap: on
line source

" Vim indent file
" Language:	YAML
" Maintainer:	Nikolai Pavlov <zyx.vim@gmail.com>
" Last Updates:	Lukas Reineke, "lacygoill"
" Last Change:	2022 Jun 17
"      2024 Feb 29 disable mulitline indent by default (The Vim project)

" Only load this indent file when no other was loaded.
if exists('b:did_indent')
  finish
endif

let b:did_indent = 1

setlocal indentexpr=GetYAMLIndent(v:lnum)
setlocal indentkeys=!^F,o,O,0#,0},0],<:>,0-
setlocal nosmartindent

let b:undo_indent = 'setlocal indentexpr< indentkeys< smartindent<'

" Only define the function once.
if exists('*GetYAMLIndent')
    finish
endif

let s:save_cpo = &cpo
set cpo&vim

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*\#@!\S@=%(\''%([^'']|\''\'')*\''' ..
                \                 '|\"%([^"\\]|\\.)*\"' ..
                \                 '|%(%(\:\ )@!.)*)\:%(\ |$)'
let s:liststartregex = '\v^\s*%(\-%(\ |$))'

let s:c_ns_anchor_char = '\v%([\n\r\uFEFF \t,[\]{}]@!\p)'
let s:c_ns_anchor_name = s:c_ns_anchor_char .. '+'
let s:c_ns_anchor_property =  '\v\&' .. s:c_ns_anchor_name

let s:ns_word_char = '\v[[:alnum:]_\-]'
let s:ns_tag_char  = '\v%(\x\x|' .. s:ns_word_char .. '|[#/;?:@&=+$.~*''()])'
let s:c_named_tag_handle     = '\v\!' .. s:ns_word_char .. '+\!'
let s:c_secondary_tag_handle = '\v\!\!'
let s:c_primary_tag_handle   = '\v\!'
let s:c_tag_handle = '\v%(' .. s:c_named_tag_handle.
            \            '|' .. s:c_secondary_tag_handle.
            \            '|' .. s:c_primary_tag_handle .. ')'
let s:c_ns_shorthand_tag = '\v' .. s:c_tag_handle .. s:ns_tag_char .. '+'
let s:c_non_specific_tag = '\v\!'
let s:ns_uri_char  = '\v%(\x\x|' .. s:ns_word_char .. '\v|[#/;?:@&=+$,.!~*''()[\]])'
let s:c_verbatim_tag = '\v\!\<' .. s:ns_uri_char.. '+\>'
let s:c_ns_tag_property = '\v' .. s:c_verbatim_tag.
            \               '\v|' .. s:c_ns_shorthand_tag.
            \               '\v|' .. s:c_non_specific_tag

let s:block_scalar_header = '\v[|>]%([+-]?[1-9]|[1-9]?[+-])?'

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+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
        let prevmapline = s:FindPrevLEIndentedLineMatchingRegex(a:lnum,
                    \                                           s:mapkeyregex)
        if getline(prevmapline) =~# '^\s*- '
            return indent(prevmapline) + 2
        else
            return indent(prevmapline)
        endif
    elseif get(g:, 'yaml_indent_multiline_scalar', 0) &&
        \  prevline =~# '^\s*- '
        " - List with
        "   multiline scalar
        return previndent+2
    elseif get(g:, 'yaml_indent_multiline_scalar', 0) &&
        \ prevline =~# s:mapkeyregex .. '\v\s*%(%(' .. s:c_ns_tag_property ..
                \                              '\v|' .. s:c_ns_anchor_property ..
                \                              '\v|' .. s:block_scalar_header ..
                \                             '\v)%(\s+|\s*%(\#.*)?$))*'
        " Mapping with: value
        "     that is multiline scalar
        return previndent+shiftwidth()
    endif
    return previndent
endfunction

let &cpo = s:save_cpo