main ab6686c

scroll_exposed_test.go RawHistoryFolder

1package ansi_test
2
3import (
4	"fmt"
5	"testing"
6
7	vt "github.com/bnema/vev-vt"
8	"github.com/bnema/vev-vt/ansi"
9)
10
11// An embedded source exercises the generic path rather than Frame dispatch.
12type scrollCellSource struct{ vt.CellSource }
13
14func TestScrollExposedCellsRequireBlankOrRepaint(t *testing.T) {
15	for _, down := range []bool{false, true} {
16		for _, sourceKind := range []string{"frame", "pointer", "generic"} {
17			for _, tc := range []struct {
18				name     string
19				cell     vt.Cell
20				coverage int
21				kind     vt.DamageKind
22				fallback bool
23			}{
24				{"blank", vt.BlankCell(), 0, vt.DamageText, false},
25				{"uncovered text", vt.Cell{Rune: 'X', Style: vt.DefaultStyle()}, 0, vt.DamageText, true},
26				{"uncovered styled blank", vt.Cell{Rune: ' ', Style: vt.Style{Bold: true}}, 0, vt.DamageText, true},
27				{"partial coverage", vt.Cell{Rune: 'X', Style: vt.DefaultStyle()}, 1, vt.DamageText, true},
28				{"text coverage", vt.Cell{Rune: 'X', Style: vt.DefaultStyle()}, 2, vt.DamageText, false},
29				{"clear coverage", vt.Cell{Rune: 'X', Style: vt.DefaultStyle()}, 2, vt.DamageClear, false},
30			} {
31				t.Run(fmt.Sprintf("down=%v/%s/%s", down, sourceKind, tc.name), func(t *testing.T) {
32					committed := vt.NewFrame(12, 10)
33					for y := range committed.Height {
34						committed.FillRow(y, 0, committed.Width, vt.Cell{Rune: rune('a' + y), Style: vt.DefaultStyle()})
35					}
36					frame := committed.Clone()
37					kind, exposed := vt.DamageScrollUp, 6
38					if down {
39						kind, exposed = vt.DamageScrollDown, 2
40						frame.ScrollDown(2, 7, 2)
41					} else {
42						frame.ScrollUp(2, 7, 2)
43					}
44					for y := exposed; y < exposed+2; y++ {
45						frame.Set(0, y, tc.cell)
46					}
47					damage := []vt.Damage{{Kind: kind, Y: 2, Width: 12, Height: 6, Count: 2}}
48					if tc.coverage > 0 {
49						damage = append(damage, vt.Damage{Kind: tc.kind, Y: exposed, Width: 12, Height: tc.coverage})
50					}
51					var source vt.CellSource = frame
52					switch sourceKind {
53					case "pointer":
54						source = &frame
55					case "generic":
56						source = scrollCellSource{frame}
57					}
58					candidate, err := ansi.PlanDelta(source, damage, committed, false)
59					if err != nil {
60						t.Fatal(err)
61					}
62					if candidate.Plan.Snapshot != tc.fallback {
63						t.Fatalf("plan = %+v, want fallback %v", candidate.Plan, tc.fallback)
64					}
65					r := ansi.New(ansi.Capabilities{})
66					terminal := vt.NewScreen(12, 10)
67					initial, err := r.Draw(committed, nil)
68					if err != nil {
69						t.Fatal(err)
70					}
71					terminal.Write(initial)
72					data, err := r.Draw(source, damage)
73					if err != nil {
74						t.Fatal(err)
75					}
76					terminal.Write(data)
77					for y := range frame.Height {
78						for x := range frame.Width {
79							if !frame.Cell(x, y).Equal(terminal.Cell(x, y)) {
80								t.Fatalf("replay differs at %d,%d", x, y)
81							}
82						}
83					}
84					data, err = r.Draw(source, nil)
85					if err != nil || len(data) != 0 {
86						t.Fatalf("committed shadow differs: %q, %v", data, err)
87					}
88				})
89			}
90		}
91	}
92}

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