Open walnutdust opened 4 years ago
Two (three?) proposals on how styling can happen.
Allow user-defined custom styling options for YAML mutations for the session as well as for individual mutations.
Users may have a preference for a specific formatting option that they wish to apply to the document as they perform mutations. We allow this by initializing YamlEditor
with a YamlStyle
class that defines the following options. Individual mutation operations will also take in an additional optional named argument style
that allows for a YamlStyle
to be defined for a specific mutation operation.
indentationStep
(positive int
) - Determines the number of spaces per YAML depth level.2a. flowLevel
(non-negative int
) - Nested collections at depth flowLevel
or greater will have flow styling enforced when elements are added into the YAML document. For example, a flowLevel
of 2 looks like:
a:
b: [c, d, [e, f]]
This does not mean that elements before the second level cannot be styled in flow styling. For example, if our original document was:
[1, 2, 3]
It is clear to see that any addition/update of elements into this YAML document has to take on flow styling since we cannot have block styling in flow structures. Note that this option will likely be mutually exclusive with 2b. This might be a more flexible alternative to 2b, since it allows for more customization, and it makes more sense (too many nested block structures will eat up line width). We can define flowLevel
(or give it a better name) to be with respect to the base level when used to initialize YamlEditor
, or with respect to the collection passed in when used in a mutation method.
2b. enforceFlow
(bool
) - If true, collections added will have flow styling enforced. If false, collections will default to block styling where possible. Note that this option will likely be mutually exclusive with 2a.
scalarStyle
(ScalarStyle
from package:yaml
) - Sets the default style to be used for scalars where possible. Cases where this might not work include where the style is set to plain, and the scalar is a string beginning with '
, "
, >
, or could be interpreted as a boolean/null (e.g. true
).As far as this proposal is concerned, these styling options will only be applied to the regions of the YAML affected by mutations. Original YAML text will not be affected.
style
collectionAn extension of Proposal 1, instead of the mutation methods receiving YamlStyle
objects for a custom style to be used for the specific mutation, we allow the user to pass in a collection that mimics the structure of the collection or item passed in. For example, if a list [Jan, Feb, Mar, Apr]
were to be passed in, the style
argument could take something like:
{
#style: CollectionStyle.BLOCK,
#indentation: 2,
children: [
'Jan': { #style: CollectionStyle.SINGLE_QUOTE, #indentation: 2}
...
]
}
Which should allow for maximum flexibility at the cost of being verbose.
There might not be as much value in allowing the user too much flexibility within the individual mutations. Rather, we can try to provide an opinionated yaml formatter service that could run before toString()
is called, which could try to align text:
one: 1
two: 2
three: 3
could become:
one: 1
two: 2
three: 3
or
one: 1
two: 2
three: 3
, make everything with a defined indentation step, and possibly wrap folded and literal strings to a certain line width.
This might also be useful in creating canonical output, although at the potential loss of some (probably non-essential) whitespace.
Will have to experiment to see how feasible this is.
package:yaml
currently doesn't have a way for external library users to create YamlNode
s with a specified style. This could be circumvented with access to src/style.dart
and src/yaml_node.dart
@jonasfj some preliminary thoughts above! Would love to hear what you think!
@walnutdust, in YamlEdit.assign(path, value)
do we allow value
to be a instance of YamlNode
. If so I suggest we patch package:yaml
, such that we have wrap constructors:
YamlScalar.wrap(dynamic value, {dynamic sourceUrl, ScalarStyle style})
YamlMap.wrap(dynamic value, {dynamic sourceUrl, CollectionStyle style})
YamlList.wrap(dynamic value, {dynamic sourceUrl, CollectionStyle style})
Adding an extra optional parameter won't break anyone. If users really want to control nested style they can then do:
yamlEdit.assign(path, YamlMap.wrap({
'myKey': YamlList.wrap([1,2,3], style: CollectionStyle.FLOW),
'otherKey': [1,2,3], // this just gets default flow...
}, style: CollectionStyle.BLOCK));
I think the criteria to judge this by is based on convenience and utility. Most of the use cases I can see for this might be in modifying configuration files, so I'm not too sure how much value allowing fully flexible might provide
I think this is a fair argument.. Maybe we should only offer is styling through Yaml(Map|List|Scalar).wrap(value, style: ...)
, and if input is not an YamlNode
or if it has ANY
style, we just use:
Implementation of a class that allows the user of the library to define the default options that will be used when the library modifies the YAML string.
This involves:
Examples of these style configurations include:
indentationStep
- number of additional spaces between block elements at adjacent levelsenforceFlow
- whether to always use flow styling, or to try to use block where possible.In addition, we might want to consider modifying the mutation methods to allow the user to specify settings for a specific mutation.