From 5e7448912618b6199310f0974118633aadbc3ccb Mon Sep 17 00:00:00 2001 From: Michael Muré Date: Sat, 1 Dec 2018 15:15:57 +0100 Subject: text: fix broken truncate with unicode and use the ellipsis character in LeftPadMaxLine --- util/text/left_padded.go | 25 +++++++++++-------- util/text/left_padded_test.go | 56 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+), 10 deletions(-) create mode 100644 util/text/left_padded_test.go diff --git a/util/text/left_padded.go b/util/text/left_padded.go index 78d772d5..729834db 100644 --- a/util/text/left_padded.go +++ b/util/text/left_padded.go @@ -2,22 +2,27 @@ package text import ( "bytes" + "fmt" "strings" - "unicode/utf8" ) // LeftPadMaxLine pads a string on the left by a specified amount and pads the string on the right to fill the maxLength -func LeftPadMaxLine(value string, maxValueLength, leftPad int) string { - valueLength := utf8.RuneCountInString(value) - if maxValueLength-leftPad >= valueLength { - return strings.Repeat(" ", leftPad) + value + strings.Repeat(" ", maxValueLength-valueLength-leftPad) - } else if maxValueLength-leftPad < valueLength { - tmp := strings.Trim(value[0:maxValueLength-leftPad-3], " ") + "..." - tmpLength := utf8.RuneCountInString(tmp) - return strings.Repeat(" ", leftPad) + tmp + strings.Repeat(" ", maxValueLength-tmpLength-leftPad) +func LeftPadMaxLine(text string, length, leftPad int) string { + runes := []rune(text) + + // truncate and ellipse if needed + if len(runes)+leftPad > length { + runes = append(runes[:(length-leftPad-1)], '…') + } + + if len(runes)+leftPad < length { + runes = append(runes, []rune(strings.Repeat(" ", length-len(runes)-leftPad))...) } - return value + return fmt.Sprintf("%s%s", + strings.Repeat(" ", leftPad), + string(runes), + ) } // LeftPad left pad each line of the given text diff --git a/util/text/left_padded_test.go b/util/text/left_padded_test.go new file mode 100644 index 00000000..0be79e32 --- /dev/null +++ b/util/text/left_padded_test.go @@ -0,0 +1,56 @@ +package text + +import "testing" + +func TestLeftPadMaxLine(t *testing.T) { + cases := []struct { + input, output string + maxValueLength int + leftPad int + }{ + { + "foo", + "foo ", + 4, + 0, + }, + { + "foofoofoo", + "foo…", + 4, + 0, + }, + { + "foo", + "foo ", + 10, + 0, + }, + { + "foo", + " f…", + 4, + 2, + }, + { + "foofoofoo", + " foo…", + 6, + 2, + }, + { + "foo", + " foo ", + 10, + 2, + }, + } + + for i, tc := range cases { + result := LeftPadMaxLine(tc.input, tc.maxValueLength, tc.leftPad) + if result != tc.output { + t.Fatalf("Case %d Input:\n\n`%s`\n\nExpected Output:\n\n`%s`\n\nActual Output:\n\n`%s`", + i, tc.input, tc.output, result) + } + } +} -- cgit