1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
|
// License: GPLv3 Copyright: 2022, Kovid Goyal, <kovid at kovidgoyal.net>
package wcswidth
import (
"testing"
"github.com/google/go-cmp/cmp"
)
func TestWCSWidth(t *testing.T) {
wcswidth := func(text string, expected int) {
if w := Stringwidth(text); w != expected {
t.Fatalf("The width for %#v was %d instead of %d", text, w, expected)
}
}
wcwidth := func(text string, widths ...int) {
for i, q := range []rune(text) {
if w := Runewidth(q); w != widths[i] {
t.Fatalf("The width of the char: U+%x was %d instead of %d", q, w, widths[i])
}
}
}
wcwidth("a1\000コニチ ✔", 1, 1, 0, 2, 2, 2, 1, 1)
wcswidth("a\033[2mb", 2)
wcswidth("\033a\033[2mb", 2)
wcswidth("a\033]8;id=moo;https://foo\033\\a", 2)
wcswidth("a\033x", 2)
wcswidth("\u2716\u2716\ufe0f\U0001f337", 5)
wcswidth("\u25b6\ufe0f", 2)
wcswidth("\U0001f610\ufe0e", 1)
wcswidth("\U0001f1e6a", 3)
wcswidth("\U0001F1E6a\U0001F1E8a", 6)
wcswidth("\U0001F1E6\U0001F1E8a", 3)
wcswidth("\U0001F1E6\U0001F1E8\U0001F1E6", 4)
wcswidth("a\u00adb", 2)
wcswidth("a\x1b[22bcd", 25)
// Flags individually and together
wcwidth("\U0001f1ee\U0001f1f3", 2, 2)
wcswidth("\U0001f1ee\U0001f1f3", 2)
truncate := func(text string, length int, expected string, expected_width int) {
actual, actual_width := TruncateToVisualLengthWithWidth(text, length)
if actual != expected {
t.Fatalf("Failed to truncate \"%s\" to %d\nExpected: %#v\nActual: %#v", text, length, expected, actual)
}
if actual_width != expected_width {
t.Fatalf("Failed to truncate with width \"%s\" to %d\nExpected: %d\nActual: %d", text, length, expected_width, actual_width)
}
}
truncate("abc", 4, "abc", 3)
truncate("abc", 3, "abc", 3)
truncate("abc", 2, "ab", 2)
truncate("abc", 0, "", 0)
truncate("a🌷", 2, "a", 1)
truncate("a🌷", 3, "a🌷", 3)
truncate("a🌷b", 3, "a🌷", 3)
truncate("a🌷b", 4, "a🌷b", 4)
truncate("a🌷\ufe0e", 2, "a🌷\ufe0e", 2)
truncate("a🌷\ufe0eb", 3, "a🌷\ufe0eb", 3)
truncate("a\x1b[31mb", 2, "a\x1b[31mb", 2)
truncate("a\x1b[7bb", 2, "a", 1)
truncate("a\x1b[3bbc", 5, "a\x1b[3bb", 5)
}
func TestCellIterator(t *testing.T) {
f := func(text string, expected ...string) {
ci := NewCellIterator(text)
actual := make([]string, 0, len(expected))
for ci.Forward() {
actual = append(actual, ci.Current())
}
if diff := cmp.Diff(expected, actual); diff != "" {
t.Fatalf("Failed forward iteration for string: %#v\n%s", text, diff)
}
}
f("abc", "a", "b", "c")
f("a🌷ò", "a", "🌷", "ò")
f("a🌷\ufe0eò", "a", "🌷\ufe0e", "ò")
f("òne", "ò", "n", "e")
r := func(text string, expected ...string) {
ci := NewCellIterator(text).GotoEnd()
actual := make([]string, 0, len(expected))
for ci.Backward() {
actual = append(actual, ci.Current())
}
if diff := cmp.Diff(expected, actual); diff != "" {
t.Fatalf("Failed reverse iteration for string: %#v\n%s", text, diff)
}
}
r("abc", "c", "b", "a")
r("a🌷ò", "ò", "🌷", "a")
r("òne", "e", "n", "ò")
ci := NewCellIterator("123")
ci.Forward()
ci.Forward()
ci.Forward()
ci.Backward()
if ci.Current() != "2" {
t.Fatalf("switching to backward failed, %#v != %#v", "2", ci.Current())
}
ci.Backward()
if ci.Current() != "1" {
t.Fatalf("switching to backward failed, %#v != %#v", "1", ci.Current())
}
ci.Forward()
if ci.Current() != "2" {
t.Fatalf("switching to forward failed, %#v != %#v", "2", ci.Current())
}
}
|