go-yaml
go-yaml copied to clipboard
[Question]: Apply global indentation rules
Say I have an input like
root1:
- element1
- element2
root2:
- element3
root3:
- element4
and I want to canonicalise the indentation to some defined standard, say
root1:
- element1
- element2
root2:
- element3
root3:
- element4
How would I go about doing that? I've tried walking over the AST and setting each node's token's column to its indentlevel*2+1 (for the case here) and that almost works, but does not correctly handle the root* indentation positions (resulting in both ugliness and broken yaml).
This can be done by decoding the target yaml once and then specifying the yaml.Indent and yaml.IndentSequence option when encoding.
So not from the AST? In the use I have, I have already done mutations on the AST to rewrite parts, so it seems like I could continue to use it, but I guess just piping it through again works if it does.
Actually, unless we go through the AST this won't work for me since I need to retain comments.
@efd6 It is possible to decode/encode while retaining comments, using yaml.CommentToMap / yaml.WithComment option. If you don't know how to use it, please refer to the test code.
Thanks. It appears to not be able to differentiate 0-level sequence from above, so any sequence-only docs end up with a gutter of indentation. This is solved by post-processing, but there is other lossiness due to moving out of the AST: movement of comments and change of string types.
func redent(doc string, indent int) (string, error) {
cm := make(yaml.CommentMap)
var v interface{}
err := yaml.NewDecoder(strings.NewReader(doc), yaml.CommentToMap(cm)).Decode(&v)
if err != nil {
return "", err
}
var buf strings.Builder
err = yaml.NewEncoder(&buf,
yaml.WithComment(cm),
yaml.Indent(indent),
yaml.IndentSequence(true),
).Encode(v)
if err != nil {
return "", err
}
return buf.String(), nil
}
(For others, works with 1.10.0, not with 1.9.8)
I wasn't sure of the situation, could you share the yaml you are targeting in more detail ? If you provide it to me in the form of reproduced code, I can verify it as well.
Sure, the tool is github.com/efd6/fumpt, I've put the state with this reformatting in https://github.com/efd6/fumpt/tree/redent The test data shows the kind of things we see (txtar format for ease of reading). current master: https://github.com/efd6/fumpt/blob/master/pkg_want.txtar with this addition: https://github.com/efd6/fumpt/blob/redent/pkg_want.txtar