Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use "literal" multi-line string literals? #152

Closed
Gabriel439 opened this issue Sep 4, 2018 · 6 comments

Comments

@Gabriel439
Copy link

commented Sep 4, 2018

The context for this is that I was using this library to render a YAML configuration file with an inline code block (I know ...), and any indented code caused it to fall back to using non-multi-line string literals. The minimal reproducing example is any string containing relative indentation:

>>> -- Works fine
>>> Data.ByteString.Char8.putStr (Data.Yaml.encode (Data.Yaml.String "a\nb\n"))
! 'a

  b

'
>>> -- Falls back to non-multi-line string due to `b` being indented
>>> Data.ByteString.Char8.putStr (Data.Yaml.encode (Data.Yaml.String "a\n b\n"))
! "a\n b\n"

My understanding is that "plain" multi-line string literals in YAML don't support relative indentation since they strip leading newlines, so if you restrict yourself to plain multi-line string literals then the fallback is necessary. This is also the reason for the extra newlines in the rendered string since a blank line is required to generate a newline.

However, YAML does support an alternative "literal" multi-line string literal if you prefix the string with a |. This form preserves leading whitespace and also preserves newlines exactly, like this:

! |
  a
   b

Would it be possible to use that "literal" form for rendering multi-line string literals instead of the "plain" form?

(Note: I'm basing this off of https://yaml-multiline.info/ and some examples I've seen in the wild)

@snoyberg

This comment has been minimized.

Copy link
Owner

commented Sep 5, 2018

Three answers:

  1. The Data.Yaml API does not provide any support for controlling formatting, since it uses Data.Aeson.Value as an intermediate value.

  2. he underlying Text.Libyaml API provides for much more control over the serialization format via the Event datatype, which has such things as Style, which is what you're probably looking for here. Data.Yaml.Builder provides the beginnings of a higher-level interface for this approach, but it's incomplete.

  3. Data.Yaml gives no guarantees about how the output will look, only about its semantics. I'd be OK in theory with some heuristics to be added to change the rendering style of a String based on whether or not it has newlines in it, though such changes are likely to be controversial, and have others asking for their preferred rendering style.

I think it's probably about time to flesh out Data.Yaml.Builder properly and recommend that approach.

@Gabriel439

This comment has been minimized.

Copy link
Author

commented Sep 11, 2018

@snoyberg: What about making the default behavior the "literal" style (i.e. prefix with !)? The main reason I suggest this is that the literal style seems to be a more desirable default than the plain style. That said, I'd also be fine with using the lower-level API to customize the rendering

@snoyberg

This comment has been minimized.

Copy link
Owner

commented Sep 12, 2018

Plenty of people have complained when the YAML library has been too aggressive in the past with forcing literal style. Plain style is almost always preferable for normal (short) string values.

@Gabriel439

This comment has been minimized.

Copy link
Author

commented Sep 12, 2018

Right, but I'm referring to multi-line string literals, not short (presumably single-line) literals

@snoyberg

This comment has been minimized.

Copy link
Owner

commented Sep 12, 2018

I see the confusion here: the "literal" block style you're referring to isn't preceded by a ! (exclamation point), but by a | (pipe). Fortunately for clear communication, most fonts and eyes make those two looks virtually identical :D

Preceding a string with an exclamation point can be part of YAML's tagging system, which is what I thought you were referring to. Using literal style for multiline strings seems reasonable to me.

And if your takeaway from this is "YAML is too complicated," I can only agree with you.

@Gabriel439

This comment has been minimized.

Copy link
Author

commented Sep 12, 2018

Yeah, I was less concerned about the tagging system and only added the exclamation mark because the examples I was cribbing from did so, too. I was more interested in the pipe to switch to literal style

And yes, YAML is super-complicated :)

@snoyberg snoyberg closed this in e0f5c85 Sep 18, 2018

snoyberg added a commit that referenced this issue Sep 18, 2018
Merge pull request #154 from snoyberg/152-literal-multiline
Use literal style for multiline strings (fixes #152)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
2 participants
You can’t perform that action at this time.