From 00b1811a3d97bdd8f097cc128ab91600400e4c81 Mon Sep 17 00:00:00 2001 From: Klaus Post Date: Mon, 8 Apr 2024 13:10:58 +0200 Subject: [PATCH] Fix multi-parameter println spacing `fmt.Println` will add spaces between elements when there is multiple parameters sent. When wrapping the colors parameters were combined using `fmt.Sprint(a...)` - which does not space out parameters. Use `fmt.Sprintln` to combine parameters. Fixes #218 --- color.go | 13 +++++++++---- color_test.go | 31 +++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 4 deletions(-) diff --git a/color.go b/color.go index c423428..81094e8 100644 --- a/color.go +++ b/color.go @@ -269,7 +269,7 @@ func (c *Color) Printf(format string, a ...interface{}) (n int, err error) { // On Windows, users should wrap w with colorable.NewColorable() if w is of // type *os.File. func (c *Color) Fprintln(w io.Writer, a ...interface{}) (n int, err error) { - return fmt.Fprintln(w, c.wrap(fmt.Sprint(a...))) + return fmt.Fprintln(w, c.wrap(sprintln(a...))) } // Println formats using the default formats for its operands and writes to @@ -278,7 +278,7 @@ func (c *Color) Fprintln(w io.Writer, a ...interface{}) (n int, err error) { // encountered. This is the standard fmt.Print() method wrapped with the given // color. func (c *Color) Println(a ...interface{}) (n int, err error) { - return fmt.Fprintln(Output, c.wrap(fmt.Sprint(a...))) + return fmt.Fprintln(Output, c.wrap(sprintln(a...))) } // Sprint is just like Print, but returns a string instead of printing it. @@ -288,7 +288,7 @@ func (c *Color) Sprint(a ...interface{}) string { // Sprintln is just like Println, but returns a string instead of printing it. func (c *Color) Sprintln(a ...interface{}) string { - return fmt.Sprintln(c.Sprint(a...)) + return c.wrap(sprintln(a...)) + "\n" } // Sprintf is just like Printf, but returns a string instead of printing it. @@ -370,7 +370,7 @@ func (c *Color) SprintfFunc() func(format string, a ...interface{}) string { // string. Windows users should use this in conjunction with color.Output. func (c *Color) SprintlnFunc() func(a ...interface{}) string { return func(a ...interface{}) string { - return fmt.Sprintln(c.Sprint(a...)) + return c.wrap(sprintln(a...)) + "\n" } } @@ -648,3 +648,8 @@ func HiCyanString(format string, a ...interface{}) string { return colorString(f func HiWhiteString(format string, a ...interface{}) string { return colorString(format, FgHiWhite, a...) } + +// sprintln is a helper function to format a string with fmt.Sprintln and trim the trailing newline. +func sprintln(a ...interface{}) string { + return strings.TrimSuffix(fmt.Sprintln(a...), "\n") +} diff --git a/color_test.go b/color_test.go index a8cc887..eb76d53 100644 --- a/color_test.go +++ b/color_test.go @@ -504,3 +504,34 @@ func TestIssue206_2(t *testing.T) { t.Errorf("Expecting %v, got '%v'\n", expectedResult, result) } } + +func TestIssue218(t *testing.T) { + // Adds a newline to the end of the last string to make sure it isn't trimmed. + params := []interface{}{"word1", "word2", "word3", "word4\n"} + + c := New(FgCyan) + c.Println(params...) + + var result = c.Sprintln(params...) + fmt.Println(params...) + fmt.Print(result) + + const expectedResult = "\x1b[36mword1 word2 word3 word4\n\x1b[0m\n" + + if !bytes.Equal([]byte(result), []byte(expectedResult)) { + t.Errorf("Sprintln: Expecting %v (%v), got '%v (%v)'\n", expectedResult, []byte(expectedResult), result, []byte(result)) + } + + fn := c.SprintlnFunc() + result = fn(params...) + if !bytes.Equal([]byte(result), []byte(expectedResult)) { + t.Errorf("SprintlnFunc: Expecting %v (%v), got '%v (%v)'\n", expectedResult, []byte(expectedResult), result, []byte(result)) + } + + var buf bytes.Buffer + c.Fprintln(&buf, params...) + result = buf.String() + if !bytes.Equal([]byte(result), []byte(expectedResult)) { + t.Errorf("Fprintln: Expecting %v (%v), got '%v (%v)'\n", expectedResult, []byte(expectedResult), result, []byte(result)) + } +}