Skip to content

Commit

Permalink
internal/encoding/yaml: use cue/literal to quote string scalars
Browse files Browse the repository at this point in the history
The YAML decoder had a function to wrap literal.Quote to use the
multi-line """ form when the string had any newlines.
It turns out that cue/literal can already do this via the option
Form.WithOptionalTabIndent, which enables an "auto" multi-line mode
to use the """ form when any newlines are present.

While here, I noticed an optimization in our use of strings.Repeat
which has already been done upstream for Go 1.23.

Signed-off-by: Daniel Martí <mvdan@mvdan.cc>
Change-Id: Iba3b9bafb0b434001173db82718b30d1e1b680ef
Reviewed-on: https://review.gerrithub.io/c/cue-lang/cue/+/1193240
TryBot-Result: CUEcueckoo <cueckoo@cuelang.org>
Unity-Result: CUE porcuepine <cue.porcuepine@gmail.com>
Reviewed-by: Roger Peppe <rogpeppe@gmail.com>
  • Loading branch information
mvdan committed Apr 18, 2024
1 parent ff533f4 commit 16edd40
Show file tree
Hide file tree
Showing 2 changed files with 2 additions and 41 deletions.
1 change: 1 addition & 0 deletions cue/literal/quote.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ func tabs(n int) string {
// WithOptionalIndent is like WithTabIndent, but only returns a multiline
// strings if it doesn't contain any newline characters.
func (f Form) WithOptionalTabIndent(tabs int) Form {
// TODO(mvdan): remove this optimization once Go 1.23 lands with https://go.dev/cl/536615
if tabs < len(tabIndent) {
f.indent = tabIndent[:tabs]
} else {
Expand Down
42 changes: 1 addition & 41 deletions internal/encoding/yaml/decode.go
Original file line number Diff line number Diff line change
Expand Up @@ -498,7 +498,7 @@ func (d *decoder) scalar(yn *yaml.Node) (ast.Expr, error) {
return &ast.BasicLit{
ValuePos: d.pos(yn),
Kind: token.STRING,
Value: quoteString(yn.Value),
Value: literal.String.WithOptionalTabIndent(1).Quote(yn.Value),
}, nil

case binaryTag:
Expand Down Expand Up @@ -618,46 +618,6 @@ func (d *decoder) alias(yn *yaml.Node) (ast.Expr, error) {
return node, err
}

// quoteString converts a string to a CUE multiline string if needed.
// TODO(mvdan): this is brought over from the old decoder; we should consider
// polishing this API and moving it someplace better like cue/literal.
func quoteString(s string) string {
lines := []string{}
last := 0
for i, c := range s {
if c == '\n' {
lines = append(lines, s[last:i])
last = i + 1
}
if c == '\r' {
goto quoted
}
}
lines = append(lines, s[last:])
if len(lines) >= 2 {
buf := []byte{}
buf = append(buf, `"""`+"\n"...)
for _, l := range lines {
if l == "" {
// no indentation for empty lines
buf = append(buf, '\n')
continue
}
buf = append(buf, '\t')
p := len(buf)
// TODO(mvdan): do not use Go's strconv for CUE syntax.
buf = strconv.AppendQuote(buf, l)
// remove quotes
buf[p] = '\t'
buf[len(buf)-1] = '\n'
}
buf = append(buf, "\t\t"+`"""`...)
return string(buf)
}
quoted:
return literal.String.Quote(s)
}

func labelStr(l ast.Label) string {
switch l := l.(type) {
case *ast.Ident:
Expand Down

0 comments on commit 16edd40

Please sign in to comment.