cue icon indicating copy to clipboard operation
cue copied to clipboard

go/encoding/yaml uses LiteralStyle

Open nyarly opened this issue 2 years ago • 6 comments

Is your feature request related to a problem? Please describe. I'm always frustrated when I want to encode CUE values in YAML and multiline strings are serialized as the YAML flow literal style (like\nthis\n) rather than in block style (i.e. with | )

Describe the solution you'd like I'd like multiline strings to stay multi-line when exported to YAML.

Describe alternatives you've considered Currently, I use yq -P a lot

nyarly avatar Aug 16 '23 18:08 nyarly

Would this be driven only by a heuristic, or also via some option?

mvdan avatar Aug 24 '23 13:08 mvdan

I'm not sure what heuristics are available, curious what you are thinking there.

My intuition is that

  1. it would be an option (flag/attr/other)
  2. default would be the one most human readable / what a human would write, which is block style, but there are many variations/chomps... fortunately, a kind soul made a site just for YAML multiline craziness: https://yaml-multiline.info/

Another consideration is that a user may want to use different variations on different values

verdverm avatar Aug 24 '23 14:08 verdverm

Yeah, I'm not sure what configuration you could usefully use? Maybe a callback function, where the caller could decide how to format. Alternatively, a well known CUE attribute (@yaml(multiline)?) would let CUE authors decide. A callback and a default attribute handler? So you'd yaml.Encode(value, yaml.DefaultFormatter) to let @yaml(multiline) work, or wrap it in your own function to make other choices?

As for a default heuristic "The string includes an internal \n" feels sufficient. Client code of the YAML shouldn't care what format it's presented in, so we're mostly concerned with human readibility.

nyarly avatar Aug 24 '23 17:08 nyarly

As soon as you open up on configuration value, there are a whole lot more. For example, there are times where CUE outputs !!binary ... which other programs dislike (this was k8s related, and maybe changed since?) Should I expect to be able to change this, what about indentation?

Rhetorically, which multiline yaml format (there's more than one) should something like @yaml(multiline) use?

That attr probably can't be used, or would have to be changed to cover more intents, as it is already used in en/decoding Go structs.

verdverm avatar Aug 24 '23 21:08 verdverm

Rhetorically, which multiline yaml format (there's more than one) should something like @yaml(multiline) use?

I can't see why CUE wouldn't always use |+ - what I'm looking for is for strings with internal newlines to be serialized in YAML with raw newlines instead of "\n".

If you wanted to get very clever, you could decide on |-,|,|+ based on trailing newlines. Heck, you could even use > for strings longer than ~70 bytes with internal " "s. But I don't think "clever" is recommended here.

Also, you could use @yaml(multiline="|+")

That attr probably can't be used, or would have to be changed to cover more intents, as it is already used in en/decoding Go structs.

Maybe I don't understand what you mean here. Wouldn't the @go(yaml='') attr be used for Go?

nyarly avatar Aug 24 '23 21:08 nyarly

We always use the new YAML decoder as of v0.10.0, based on the latest go-yaml: https://github.com/cue-lang/cue/issues/3027

And, from what I can see, we already do use multi-line YAML strings when the input CUE string contains any newlines: https://cuelang.org/play/?id=uiGBaBknij2#w=function&i=cue&f=export&o=yaml

So what exactly isn't working correctly as of v0.10.0?

mvdan avatar Aug 28 '24 17:08 mvdan

It seems to be using yaml multiline (|-) as long as there is no lines that end with whitespace.

See the following example:

spec: {
	pipeline: [{
		input: {
			inline: template: """
				#{{$xr :=.observed.composite.resource}}
				---
				apiVersion: network.azure.upbound.io/v1beta1 
				kind: Subnet
				spec:
				  ...
				"""
		}
	}, {
		input: {
			inline: template: """
				#{{$xr :=.observed.composite.resource}}
				--- 
				apiVersion: network.azure.upbound.io/v1beta1
				kind: Subnet
				spec:
				  ...
				"""
		}
	}]
}

The first template here uses yaml multiline, while the other one uses doublequoted string with newlines

elzapp avatar Nov 20 '24 13:11 elzapp

I see. In that specific scenario I would say the YAML library is working as intended: it avoids producing output with trailing whitespace in lines, as that is very often misleading or causes the lines to be "trimmed", changing the values of the strings. I think it's correct for https://github.com/go-yaml/yaml and CUE to avoid using the multi-line form in that case.

mvdan avatar Nov 20 '24 13:11 mvdan

Yes, I'm happy with the current behaviour now that I know what causes it.

elzapp avatar Nov 20 '24 13:11 elzapp