wcswidth_test.go 3.4 KB

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