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

Default chomping indicator in ScalarStyle.LITERAL #86

Closed
kekavc24 opened this issue Jun 3, 2024 · 4 comments · Fixed by #87
Closed

Default chomping indicator in ScalarStyle.LITERAL #86

kekavc24 opened this issue Jun 3, 2024 · 4 comments · Fixed by #87

Comments

@kekavc24
Copy link
Contributor

kekavc24 commented Jun 3, 2024

It seems ScalarStyle.LITERAL applies the stripping chomping indicator - by default.

/// Generates a YAML-safe literal string.
///
/// It is important that we ensure that [string] is free of unprintable
/// characters by calling [_hasUnprintableCharacters] before invoking this
/// function.
String _tryYamlEncodeLiteral(
String string, int indentation, String lineEnding) {
final result = '|-\n$string';
/// Assumes the user did not try to account for windows documents by using
/// `\r\n` already
return result.replaceAll('\n', lineEnding + ' ' * indentation);
}

ScalarStyle.FOLDED at least checks if there is any line break.

/// Generates a YAML-safe folded string.
///
/// It is important that we ensure that [string] is free of unprintable
/// characters by calling [_hasUnprintableCharacters] before invoking this
/// function.
String _tryYamlEncodeFolded(String string, int indentation, String lineEnding) {
String result;
final trimmedString = string.trimRight();
final removedPortion = string.substring(trimmedString.length);
if (removedPortion.contains('\n')) {
result = '>+\n${' ' * indentation}';
} else {
result = '>-\n${' ' * indentation}';
}
/// Duplicating the newline for folded strings preserves it in YAML.
/// Assumes the user did not try to account for windows documents by using
/// `\r\n` already
return result +
trimmedString.replaceAll('\n', lineEnding * 2 + ' ' * indentation) +
removedPortion;
}

Expected Behaviour

As indicated in the spec, we should check for both line breaks & trailing spaces in order to apply the correct chomping indicator for block styles:

  • - for stripping any trailing line breaks/spaces (strip)
  • + for preserving trailing line breaks/spaces (keep)
  • Omitting them preserves the line breaks but removes the trailing space (clip)

Ideally, we should end up using the keep chomping indicator + only since we may have no use for the strip chomping indicator -.

Fixing this may have desirable ripple effects for #41 & #44.

@kekavc24
Copy link
Contributor Author

kekavc24 commented Jun 3, 2024

@jonasfj should the string from the user be preserved "as is" when inserting it in the yaml or should we mutate it to match the behaviour of yaml?

By "as-is", I mean should we respect how the user wants it to look like when it is parsed by package:yaml ?

@jonasfj
Copy link
Member

jonasfj commented Jun 3, 2024

should the string from the user be preserved "as is" when inserting it in the yaml or should we mutate it to match the behaviour of yaml?

I'm not sure exactly what this means.

If I do:

final myString = 'my string....';

yamlEditor.update(['key'], myString);
final result = json.decode(json.encode(yamlEditor.parseAt([])));
assert(result['key'] == myString);

Meaning, when I insert a string then, yes, when I parse the YAML document produced I expect I'll get the same string out.

That's what makes literal and folded strings somewhat tricky.
There are values that cannot be correctly encoded in folded and literal mode.

Example: try encoding " \nfoo" in folded mode or literal mode. When we run into a scenario where we've been given a YamlScalar, where YamlScalar.style is folded or literal, and YamlScalar.value is a string that can't be encoded in said style, we have to fallback to most similar mode that can be used.

Sometimes I suppose that using a chomping indicator might help. Many times I suspect we'll simply have to fallback to quoted string with escape characters " \nfoo".

The most important thing is that the result is correct, when parsed back. Producing the style requested is more of a best-effort approach.

And yes, there clearly are hole in how all this logic works today.


I don't know if we can always make the chomping indicator be +, how would we encode a string like "foo\nbar" for that we need to use >-\n foo\n bar\n (if folded) or |-\n foo\n bar\n (if literal). Right?

@kekavc24
Copy link
Contributor Author

kekavc24 commented Jun 3, 2024

I don't know if we can always make the chomping indicator be +, how would we encode a string like "foo\nbar" for that we need to use >-\n foo\n bar\n (if folded) or |-\n foo\n bar\n (if literal). Right?

That would result in foo bar. The \n will be converted to a space

To achieve:

  1. foo\nbar, we just add another \n and it becomes >\n foo\n\n bar. No need for chomping. Default behaviour for YamlEditor but messes with option 2.
  2. foo\n bar, we leave untouched >\n foo\n bar. No need for chomping.

The real pain is: whitespace\n \nbetween line breaks. I think for that we have to fall back to a safe approach. I have tried all solutions and it's not coming out as expected with my fix. I am still at it.

I'll make a PR by the end of the day for your feedback and add this whitespace\n \nbetween line breaks as a test case in string_test.dart.

@jonasfj
Copy link
Member

jonasfj commented Jun 3, 2024

  1. foo\nbar, we just add another \n and it becomes >\n foo\n\n bar. No need for chomping. Default behaviour for YamlEditor but messes with option 2.

Yeah, I got this example wrong 🙈

Which probably is another example of how these strings are hard.

But you do need the - chomping indicator, if you have something like:

key1: >-  # <-- omitting the chomping indicator will add \n at the end
  foo


  bar
key2: other-value

It's easy to see this if you use a tool like: https://onlineyamltools.com/convert-yaml-to-json


@kekavc24 kekavc24 mentioned this issue Jun 4, 2024
1 task
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants