OK so I would like to change the way that my yaml gets indented.

Right now my vim indents a yaml list like this:

  - this
  - is
  - a list
  this: is a dict

I would like it to indent like this:

- this
- is
- a list
  this: is a dict

Python module ruamel.yaml as equalprg

Installation of ruamel.yaml is possible with pip

$ pip install ruamel.yaml

ruamel.yaml is python3 compatible, i.e. pip3 install ruamel.yaml works as well. If you want to install it only in your home directory, use pip install --user ruamel.yaml.

Ensure that import ruamel.yaml works for the python version vim sees.

Configure equalprg of vim for yaml files with

augroup myequalprograms
  autocmd FileType yaml setlocal equalprg=python\ -c\ \'import\ sys;\ from\ ruamel.yaml\ import\ YAML;yaml=YAML();yaml.dump(yaml.load(sys.stdin),sys.stdout)\'
augroup END

Alternatively, place following line in ~/.vim/after/ftplugin/yaml.vim

setlocal equalprg=python\ -c\ \'import\ sys;\ from\ ruamel.yaml\ import\ YAML;yaml=YAML();yaml.dump(yaml.load(sys.stdin),sys.stdout)\'

Now you should be able to press =ip for your example to get the desired output. I have tried it on my machine with python3 and it works.

  • Note you could also use pyyaml with

    setlocal equalprg=python\ -c\ \'import\ yaml,sys;print(yaml.dump(yaml.safe_load(sys.stdin),default_flow_style=False))\'

    However, pyyaml changes order, removes comments and other things. ruamel.yaml explicitly tries to support the roundtrip of parsing and emitting without modifying these things.

  • There is also the project pretty-yaml with a convenient command line interface

    $ python -m pyaml demo.yaml

    Note the unfortunate similarity of the name pyaml to pyyaml. The author has made the decision that lists should be indented and therefore does not help you:

    • List items get indented, as they should be.
  • Finally, you could contact the maintainer of $VIMRUNTIME/indent/yaml.vim to ask him whether he would consider to add an option to achieve your style:

    " Vim indent file
    " Language:         YAML
    " Maintainer:       Nikolai Pavlov <zyx.vim@gmail.com>
    " Last Change:      2017 Jun 13

A solution that's more internal to vim, is to override indentexpr with a custom indent expression (most likely just overriding the builtin indentexpr for your specific instance).

The steps:

  • define a filetype override, either in an autocmd (group) or in a ftplugin override (preferred).
  • define a new (global, i.e. starting with a capital letter) function, say MyYamlIndent(lnum)
  • Add logic that detects the dash led entries. The main workhorse is likely getline(v:lnum) andgetline(v:lnum-1). The goal:
  • find the indent count (in spaces) for the previous line.
  • check if the current line contains a dash, if not, return the default (GetYAMLIndent(v:lnum))
  • If there is a leading dash, return the previous line's leading indent (in count of spaces)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.