@@ -220,33 +220,37 @@ const kyamlFoldStr = "\\\n"
220220func (ky * Encoder ) renderString (val string , indent int , flags flagMask , out io.Writer ) error {
221221 lazyQuote := flags & flagLazyQuote != 0
222222 compact := flags & flagCompact != 0
223+ multi := strings .Contains (val , "\n " )
223224
224- // If no newlines, just use standard Go quoting.
225- if compact || ! strings .Contains (val , "\n " ) {
226- if lazyQuote && ! needsQuotes (val ) {
227- fmt .Fprint (out , val )
228- } else {
229- fmt .Fprint (out , strconv .Quote (val ))
230- }
225+ if ! multi && lazyQuote && ! needsQuotes (val ) {
226+ fmt .Fprint (out , val )
231227 return nil
232228 }
233229
234- // The input has at least one newline. We will use YAML's line folding to
235- // make the output more readable.
230+ // What to print when we find a newline in the input.
231+ newline := "\\ n"
232+ if ! compact {
233+ // We use YAML's line folding to make the output more readable.
234+ newline += kyamlFoldStr
235+ }
236+
236237 //
237238 // The rest of this is borrowed from Go's strconv.Quote implementation.
238-
239- s := val
239+ //
240240
241241 // accumulate into a buffer
242242 buf := & bytes.Buffer {}
243243
244- // opening quote and fold
245- fmt .Fprint (buf , `"` , kyamlFoldStr )
244+ // opening quote
245+ fmt .Fprint (buf , `"` )
246+ if multi && ! compact {
247+ fmt .Fprintf (buf , kyamlFoldStr )
248+ }
246249
247250 // Iterating a string with invalid UTF8 returns RuneError rather than the
248251 // bytes, so we iterate the string and decode the runes. This is a bit
249252 // slower, but gives us a better result.
253+ s := val
250254 for width := 0 ; len (s ) > 0 ; s = s [width :] {
251255 r := rune (s [0 ])
252256 width = 1
@@ -258,15 +262,17 @@ func (ky *Encoder) renderString(val string, indent int, flags flagMask, out io.W
258262 fmt .Fprintf (buf , "%02x" , s [0 ])
259263 continue
260264 }
261- ky .appendEscapedRune (r , indent , buf )
265+ ky .appendEscapedRune (r , indent , newline , buf )
262266 }
263267
264268 // closing quote
265269 afterNewline := buf .Bytes ()[len (buf .Bytes ())- 1 ] == '\n'
266- if ! afterNewline {
267- fmt .Fprint (buf , kyamlFoldStr )
270+ if multi && ! compact {
271+ if ! afterNewline {
272+ fmt .Fprint (buf , kyamlFoldStr )
273+ }
274+ ky .writeIndent (indent , buf )
268275 }
269- ky .writeIndent (indent , buf )
270276 fmt .Fprint (buf , `"` )
271277
272278 fmt .Fprint (out , buf .String ())
@@ -415,7 +421,7 @@ func parseTimestamp(s string) (time.Time, bool) {
415421}
416422
417423// We use a buffer here so we can peek backwards.
418- func (ky * Encoder ) appendEscapedRune (r rune , indent int , buf * bytes.Buffer ) {
424+ func (ky * Encoder ) appendEscapedRune (r rune , indent int , newline string , buf * bytes.Buffer ) {
419425 afterNewline := buf .Bytes ()[len (buf .Bytes ())- 1 ] == '\n'
420426
421427 if afterNewline {
@@ -451,14 +457,25 @@ func (ky *Encoder) appendEscapedRune(r rune, indent int, buf *bytes.Buffer) {
451457 case '\f' :
452458 buf .WriteString (`\f` )
453459 case '\n' :
454- buf .WriteString (`\n` )
455- buf .WriteString (kyamlFoldStr )
460+ buf .WriteString (newline )
456461 case '\r' :
457462 buf .WriteString (`\r` )
458463 case '\t' :
459464 buf .WriteString (`\t` )
460465 case '\v' :
461466 buf .WriteString (`\v` )
467+ case '\x00' :
468+ buf .WriteString (`\0` )
469+ case '\x1b' :
470+ buf .WriteString (`\e` )
471+ case '\x85' :
472+ buf .WriteString (`\N` )
473+ case '\xa0' :
474+ buf .WriteString (`\_` )
475+ case '\u2028' :
476+ buf .WriteString (`\L` )
477+ case '\u2029' :
478+ buf .WriteString (`\P` )
462479 default :
463480 const hexits = "0123456789abcdef"
464481 switch {
0 commit comments