v0.5.1 8e4df5c

screen_integration_test.go RawHistoryFolder

1package vt
2
3import (
4	"testing"
5
6	renderer "github.com/bnema/vev-vt/ansi"
7)
8
9func TestZshAutosuggestionRepaintEmitsForwardDamage(t *testing.T) {
10	s := NewScreen(20, 2)
11	r := renderer.New(renderer.Capabilities{})
12
13	s.Write([]byte("❯ "))
14	if _, err := r.Draw(s.frame, s.Damage()); err != nil {
15		t.Fatal(err)
16	}
17	s.ClearDamage()
18
19	s.Write([]byte("h"))
20	if _, err := r.Draw(s.frame, s.Damage()); err != nil {
21		t.Fatal(err)
22	}
23	s.ClearDamage()
24
25	s.Write([]byte("\x1b[31mh\x1b[39m"))
26	s.Write([]byte("\x1b[38mello\x1b[39m\r \x1b[31mh\x1b[39m"))
27
28	for y := range s.frame.Height {
29		for x := range s.frame.Width {
30			r := s.frame.At(x, y).Rune
31			if r == '\r' || r == '\n' {
32				t.Fatalf("cell(%d,%d) contains control rune %q", x, y, r)
33			}
34		}
35	}
36
37	out, err := r.Draw(s.frame, s.Damage())
38	if err != nil {
39		t.Fatal(err)
40	}
41	for _, b := range out {
42		if b == '\r' || b == '\n' {
43			t.Fatalf("incremental output contains raw control byte %q: %q", b, string(out))
44		}
45	}
46}
47
48func TestIntegrationScenarios(t *testing.T) {
49	tests := []struct {
50		name string
51		run  func(t *testing.T)
52	}{
53		{
54			name: "renderer stays in sync after VT edit damage",
55			run: func(t *testing.T) {
56				s := NewScreen(8, 2)
57				r := renderer.New(renderer.Capabilities{})
58				s.Write([]byte("abcdef"))
59				if _, err := r.Draw(s.frame, s.Damage()); err != nil {
60					t.Fatal(err)
61				}
62				s.ClearDamage()
63
64				s.Write([]byte("\x1b[1;3H\x1b[2@XY"))
65				if _, err := r.Draw(s.frame, s.Damage()); err != nil {
66					t.Fatal(err)
67				}
68				s.ClearDamage()
69
70				out, err := r.Draw(s.frame, nil)
71				if err != nil {
72					t.Fatal(err)
73				}
74				if len(out) != 0 {
75					t.Fatalf("renderer emitted stale follow-up output after VT edit damage: %q", string(out))
76				}
77			},
78		},
79		{
80			name: "DCS sequence terminated by ST is ignored",
81			run: func(t *testing.T) {
82				s := NewScreen(20, 2)
83				s.Write([]byte("\x1bP+q696e646e\x1b\\prompt"))
84
85				assertCell(t, s, 0, 0, 'p')
86				assertCell(t, s, 1, 0, 'r')
87				assertCell(t, s, 2, 0, 'o')
88				assertCell(t, s, 3, 0, 'm')
89				assertCell(t, s, 4, 0, 'p')
90				assertCell(t, s, 5, 0, 't')
91				if s.Col != 6 || s.Row != 0 {
92					t.Errorf("cursor at row=%d col=%d, want row=0 col=6", s.Row, s.Col)
93				}
94			},
95		},
96		{
97			name: "fish-like prompt redraw preserves typed characters",
98			run: func(t *testing.T) {
99				s := NewScreen(10, 2)
100				s.Write([]byte("> "))
101				s.Write([]byte("a\r\x1b[3C"))
102				s.Write([]byte("\x1b[91mb\x1b[39m\x1b[K\r\x1b[4C"))
103
104				assertCell(t, s, 0, 0, '>')
105				assertCell(t, s, 1, 0, ' ')
106				assertCell(t, s, 2, 0, 'a')
107				assertCell(t, s, 3, 0, 'b')
108				if s.Row != 0 || s.Col != 4 {
109					t.Errorf("cursor at row=%d col=%d, want row=0 col=4", s.Row, s.Col)
110				}
111			},
112		},
113	}
114
115	for _, tt := range tests {
116		t.Run(tt.name, tt.run)
117	}
118}

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 2

Tags 13

↑↓ moveenter openesc close