From a91b713dcec4d17f76155f0cd6b26903c59b9c19 Mon Sep 17 00:00:00 2001 From: Lukasz Kasprzak Date: Mon, 14 Sep 2026 22:31:12 +0200 Subject: plan 10: stderr messages cannot be split by quoted newlines; config paths escaped; krino new refuses control characters; independent terminal oracle --- cmd/krino/display.go | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'cmd/krino/display.go') diff --git a/cmd/krino/display.go b/cmd/krino/display.go index 193d8b8..d468c6b 100644 --- a/cmd/krino/display.go +++ b/cmd/krino/display.go @@ -58,18 +58,22 @@ func controlRune(r rune) bool { return (r >= 0x80 && r <= 0x9f) || unicode.Is(unicode.Bidi_Control, r) || unicode.In(r, unicode.Zl, unicode.Zp) } -// safeWriter writes through display line by line, keeping the newlines: -// every error and warning krino writes to stderr may quote a file name or a -// tool's message, and nothing krino itself writes there is styled (review -// M5). +// safeWriter writes through display: every error and warning krino writes +// to stderr may quote a file name or a tool's message, and nothing krino +// itself writes there is styled (review M5). Each Write is one message line: +// only its final newline is kept, and a newline inside it - from quoted text +// - is escaped, so it cannot start a line that reads as krino's own +// (re-review term F1). A message of several lines is written with one Write +// per line. type safeWriter struct{ w io.Writer } func (s safeWriter) Write(p []byte) (int, error) { - lines := strings.Split(string(p), "\n") - for i, l := range lines { - lines[i] = display(l) + text := string(p) + end := "" + if strings.HasSuffix(text, "\n") { + text, end = text[:len(text)-1], "\n" } - if _, err := io.WriteString(s.w, strings.Join(lines, "\n")); err != nil { + if _, err := io.WriteString(s.w, display(text)+end); err != nil { return 0, err } return len(p), nil -- cgit v1.3