okami.mom/ultraviolet

git clone https://git.nkp.pet/okami.mom/ultraviolet

Christian Rochafeat(terminal): auto-enable grapheme mode, when possible3a9b1e4

main
3.8 KiB117 linesraw
1package uv
2
3import (
4	"io"
5	"testing"
6
7	"github.com/charmbracelet/x/ansi"
8)
9
10// warningSign is U+26A0 followed by a VS16 emoji-presentation selector
11// (U+FE0F). Terminals in Unicode core mode (DEC mode 2027) measure it as a
12// wide, width-2 glyph.
13const warningSign = "\u26a0\ufe0f"
14
15func TestGraphemeWidthNegotiation(t *testing.T) {
16	s := NewTerminalScreen(io.Discard, Environ{"TERM=xterm-256color"})
17
18	if got := s.StringWidth(warningSign); got != 1 {
19		t.Fatalf("default width method: StringWidth(%q) = %d, want 1", warningSign, got)
20	}
21
22	s.enableGraphemeWidth()
23
24	if got := s.StringWidth(warningSign); got != 2 {
25		t.Fatalf("grapheme mode: StringWidth(%q) = %d, want 2", warningSign, got)
26	}
27	if s.WidthMethod() != ansi.GraphemeWidth {
28		t.Fatalf("grapheme mode: WidthMethod() = %v, want GraphemeWidth", s.WidthMethod())
29	}
30	if !s.rend.flags.Contains(tGraphemeWidth) {
31		t.Fatal("grapheme mode: renderer tGraphemeWidth flag not set")
32	}
33	if s.rend.method != ansi.GraphemeWidth {
34		t.Fatalf("grapheme mode: renderer method = %v, want GraphemeWidth", s.rend.method)
35	}
36}
37
38func TestGraphemeWidthOverride(t *testing.T) {
39	s := NewTerminalScreen(io.Discard, Environ{"TERM=xterm-256color"})
40
41	s.SetWidthMethod(ansi.GraphemeWidth)
42	if got := s.StringWidth(warningSign); got != 2 {
43		t.Fatalf("override: StringWidth(%q) = %d, want 2", warningSign, got)
44	}
45	if s.rend.method != ansi.GraphemeWidth {
46		t.Fatalf("override: renderer method = %v, want GraphemeWidth", s.rend.method)
47	}
48
49	s.SetWidthMethod(ansi.WcWidth)
50	if got := s.StringWidth(warningSign); got != 1 {
51		t.Fatalf("override back: StringWidth(%q) = %d, want 1", warningSign, got)
52	}
53}
54
55// TestGraphemeWidthGating verifies that the mode-2027 report only switches the
56// width method to grapheme clustering for settable or active states, and never
57// for not-recognized or permanently-reset terminals.
58func TestGraphemeWidthGating(t *testing.T) {
59	tests := []struct {
60		name    string
61		value   ansi.ModeSetting
62		enabled bool
63	}{
64		{"set", ansi.ModeSet, true},
65		{"reset", ansi.ModeReset, true},
66		{"permanently set", ansi.ModePermanentlySet, true},
67		{"not recognized", ansi.ModeNotRecognized, false},
68		{"permanently reset", ansi.ModePermanentlyReset, false},
69	}
70
71	for _, tt := range tests {
72		t.Run(tt.name, func(t *testing.T) {
73			s := NewTerminalScreen(io.Discard, Environ{"TERM=xterm-256color"})
74			tm := &Terminal{scr: s}
75
76			tm.handleEvent(ModeReportEvent{Mode: ansi.ModeUnicodeCore, Value: tt.value})
77
78			wantWidth := 1
79			wantMethod := ansi.Method(ansi.WcWidth)
80			if tt.enabled {
81				wantWidth = 2
82				wantMethod = ansi.GraphemeWidth
83			}
84
85			if got := s.StringWidth(warningSign); got != wantWidth {
86				t.Fatalf("StringWidth(%q) = %d, want %d", warningSign, got, wantWidth)
87			}
88			if s.rend.method != wantMethod {
89				t.Fatalf("renderer method = %v, want %v", s.rend.method, wantMethod)
90			}
91			if got := s.rend.flags.Contains(tGraphemeWidth); got != tt.enabled {
92				t.Fatalf("renderer tGraphemeWidth flag = %v, want %v", got, tt.enabled)
93			}
94		})
95	}
96}
97
98// TestGraphemeWidthGatingPreservesOverride verifies that a late mode-2027
99// report does not clobber a width method the application set explicitly.
100func TestGraphemeWidthGatingPreservesOverride(t *testing.T) {
101	s := NewTerminalScreen(io.Discard, Environ{"TERM=xterm-256color"})
102	tm := &Terminal{scr: s}
103
104	s.SetWidthMethod(ansi.WcWidth)
105
106	tm.handleEvent(ModeReportEvent{Mode: ansi.ModeUnicodeCore, Value: ansi.ModeSet})
107
108	if got := s.StringWidth(warningSign); got != 1 {
109		t.Fatalf("explicit override clobbered: StringWidth(%q) = %d, want 1", warningSign, got)
110	}
111	if s.rend.method != ansi.WcWidth {
112		t.Fatalf("explicit override clobbered: renderer method = %v, want WcWidth", s.rend.method)
113	}
114	if s.rend.flags.Contains(tGraphemeWidth) {
115		t.Fatal("explicit override clobbered: renderer tGraphemeWidth flag set")
116	}
117}