Yaml How Many Spaces Per Indent

YAML How many spaces per indent?

There is no requirement in YAML to indent any concrete number of spaces. There is also no requirement to be consistent. So for example, this is valid YAML:

a:
b:
- c
- d
- e
f:
"ghi"

Some rules might be of interest:

  • Flow content (i.e. everything that starts with { or [) can span multiple lines, but must be indented at least as many spaces as the surrounding current block level.
  • Block list items can (but don't need to) have the same indentation as the surrounding block level because - is considered part of the indentation:
a:    # top-level key
- b # value of that key, which is a list
- c
c: # next top-level key
d # non-list value which must be more indented

A YAML file cannot contain tabs as indentation

A YAML file use spaces as indentation, you can use 2 or 4 spaces for indentation, but no tab. In other words, tab indentation is forbidden:

Why does YAML forbid tabs?

Tabs have been outlawed since they are treated differently by different editors and tools. And since indentation is so critical to proper interpretation of YAML, this issue is just too tricky to even attempt.

(source: YAML FAQ (thanks to Destiny Architect for the link))

For example, the Symfony configuration file can be written with 2 or 4 spaces as indentation:

4 spaces

doctrine:
dbal:
default_connection: default

2 spaces

doctrine:
dbal:
default_connection: default

Why isn't two-spaced YAML parsed like four-spaced YAML?

The trouble is that you cannot simply replace every two spaces with four spaces. That is because in this pair of lines:

  - shell:
panes:

these two spaces in the second line:

    panes:
^^

Are an abbrevation for the "- " in the line above. If the second line were not abbreviated, then the pair of lines would be:

  - shell:
- panes:

So when doubling the indentation, the second of these line should only have its first pair of spaces doubled, not the second. That would yield the correct indentation for the pair:

    - shell:
panes:

So, if you only expand the first pair of spaces in the "panes:" line, you get:

windows:
- shell:
panes:
- git status

Which correctly parses to the expected result.

How to automatically re-indent a YAML file?

What you seem to want to do is making sure that your YAML files are uniformly indented (e.g. before being checked into a revision control system). Your idea of dedenting and then re-indenting will not work as you lose information if you flatten your structure. This:

foo:
alice: female
bob: male

consists of two mappings: a mapping with one key and a value that is mapping of two keys to two values.

This:

foo:
alice: female
bob: male

is one mapping with three keys, and key foo has as value the null scalar (also writable, apart from the empty string, as ~, NULL, null in YAML files).

Most YAML parsers will lose information when reading in a file into internal data:

  • comments are dropped
  • key ordering is not preserved for mappings
  • extra spaces around scalars are not preserved

The ruamel.yaml Python package (of which I am the author) is an enhancemed parser which to allows round-tripping a YAML file to data and back to YAML to preserve more of the original information. It will preserve comments and key ordering, but it drops e.g. extra spacing around single line scalars.

This round-tripping normally stabilizes on a second round-trip and so this can be used to reindent a YAML file. The yaml utility included in the package ruamel.yaml.cmd, can be used for that without the need to program things yourself:

yaml round-trip your_file.yml --verbose

(round-trip can be shortened to rt) will check whether and how the file would change. It shows a unified diff if it does change. Based on that you can decide to save the file if it stabilizes:

yaml round-trip your_file.yml --save

the output for example.yml:

---
foo:
alice: female # verified
bob: male
bar:
- node: 42
name: none
- node: 43
name: none

would be:

example.yml:
stabilzes on second round trip, ok without comments
--- example.yml
+++ round trip YAML
@@ -1,9 +1,9 @@
---
foo:
alice: female # verified
- bob: male
+ bob: male
bar:
-- node: 42
+- node: 42
name: none
-- node: 43
- name: none
+- node: 43
+ name: none

and when saved look like:

---
foo:
alice: female # verified
bob: male
bar:
- node: 42
name: none
- node: 43
name: none

The indentation level is by default 2, but can be set with an option to yaml.

How to preserve all leading indents in yaml?

Use a block indentation indicator:

SomeText: |1
This is some text that I would like for
The leading indents to be preserved.
It would be really nice for the leading indents to be preserved.

This explicitly specifies the indentation of the scalar content relative to the surrounding indentation, i.e. in this case, the block scalar's indentation is defined to be 1 more than SomeText:. Everything after the first space is interpreted as content, not indentation, and will be part of the scalar's value.

Mind that the indentation indicator must be at least 1 because the block scalar's indentation must be at least 1 more than the surrounding indentation, since it would end at anything having the surrounding indentation (or lesser). You can never preserve whitespace that is interpreted as indentation (which would be contrary to the idea of indentation) but you can still put an arbitrary amount of whitespace in front of your lines by adding whitespace.



Related Topics



Leave a reply



Submit