aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--util/text/text.go48
-rw-r--r--util/text/text_test.go70
2 files changed, 118 insertions, 0 deletions
diff --git a/util/text/text.go b/util/text/text.go
index ee9d278c..ad920bd8 100644
--- a/util/text/text.go
+++ b/util/text/text.go
@@ -127,3 +127,51 @@ func wordLen(word string) int {
return length
}
+
+// splitWord split a word at the given length, while ignoring the terminal escape sequences
+func splitWord(word string, length int) (string, string) {
+ runes := []rune(word)
+ var result []rune
+ added := 0
+ escape := false
+
+ if length == 0 {
+ return "", word
+ }
+
+ for _, r := range runes {
+ if r == '\x1b' {
+ escape = true
+ }
+
+ width := runewidth.RuneWidth(r)
+ if width+added > length {
+ // wide character made the length overflow
+ break
+ }
+
+ result = append(result, r)
+
+ if !escape {
+ added += width
+ if added >= length {
+ break
+ }
+ }
+
+ if r == 'm' {
+ escape = false
+ }
+ }
+
+ leftover := runes[len(result):]
+
+ return string(result), string(leftover)
+}
+
+func minInt(a, b int) int {
+ if a > b {
+ return b
+ }
+ return a
+}
diff --git a/util/text/text_test.go b/util/text/text_test.go
index c70d2ccd..f5b15a43 100644
--- a/util/text/text_test.go
+++ b/util/text/text_test.go
@@ -203,3 +203,73 @@ func TestWordLen(t *testing.T) {
}
}
}
+
+func TestSplitWord(t *testing.T) {
+ cases := []struct {
+ Input string
+ Length int
+ Result, Leftover string
+ }{
+ // A simple word passes through.
+ {
+ "foo",
+ 4,
+ "foo", "",
+ },
+ // Cut at the right place
+ {
+ "foobarHoy",
+ 4,
+ "foob", "arHoy",
+ },
+ // A simple word passes through with colors
+ {
+ "\x1b[31mbar\x1b[0m",
+ 4,
+ "\x1b[31mbar\x1b[0m", "",
+ },
+ // Cut at the right place with colors
+ {
+ "\x1b[31mfoobarHoy\x1b[0m",
+ 4,
+ "\x1b[31mfoob", "arHoy\x1b[0m",
+ },
+ // Handle prefix and suffix properly
+ {
+ "foo\x1b[31mfoobarHoy\x1b[0mbaaar",
+ 4,
+ "foo\x1b[31mf", "oobarHoy\x1b[0mbaaar",
+ },
+ // Cut properly with length = 0
+ {
+ "foo",
+ 0,
+ "", "foo",
+ },
+ // Handle chinese
+ {
+ "快檢什麼望對",
+ 4,
+ "快檢", "什麼望對",
+ },
+ {
+ "快檢什麼望對",
+ 5,
+ "快檢", "什麼望對",
+ },
+ // Handle chinese with colors
+ {
+ "快\x1b[31m檢什麼\x1b[0m望對",
+ 4,
+ "快\x1b[31m檢", "什麼\x1b[0m望對",
+ },
+ }
+
+ for i, tc := range cases {
+ result, leftover := splitWord(tc.Input, tc.Length)
+ if result != tc.Result || leftover != tc.Leftover {
+ t.Fatalf("Case %d Input:\n\n`%s`\n\nExpected Output:\n\n`%s` - `%s`\n\nActual Output:\n\n`%s` - `%s`",
+ i, tc.Input, tc.Result, tc.Leftover, result, leftover)
+ }
+ }
+}