v0.3.0 cf370a0

stash_cover_test.go RawHistoryFolder

1package core
2
3import (
4	"testing"
5
6	"github.com/bnema/neferwl/internal/ports"
7)
8
9// stashCoverCore has two screens; the first holds tile 1 and the hidden
10// stash [2 3], 3 selected, under a covering fullscreen window: tile 1, or
11// float 4 with float set.
12func stashCoverCore(t *testing.T, overflow Overflow, float bool) (*Core, *Workspace, WindowID) {
13	t.Helper()
14	cfg := ports.Config{}
15	cfg.Keyboard.CmdKey = "super"
16	cfg.Layout.Overflow = string(overflow)
17	cfg.Layout.MaxColumns = 2
18	c, err := New(cfg, Channels{Scenes: make(chan []ports.Scene, 1)})
19	if err != nil {
20		t.Fatal(err)
21	}
22	c.addScreen(ports.OutputInfo{Name: "A", Width: 100, Height: 80})
23	c.addScreen(ports.OutputInfo{Name: "B", Width: 100, Height: 80})
24	m := c.screens[0].mon
25	for id := WindowID(1); id <= 3; id++ {
26		m.AddWindow(id)
27	}
28	w := m.Current()
29	for _, id := range []WindowID{2, 3} {
30		w.FocusID(id)
31		w.ToggleWindowStash()
32	}
33	c.applyAction(ActionToggleStashVisible) // hidden
34	cover := WindowID(1)
35	if float {
36		cover = 4
37		m.AddFloating(4, 100, 80)
38		m.SetFullscreen(4, true)
39	} else {
40		c.applyAction(ActionToggleFullscreen)
41	}
42	if w.cover() != cover || c.focusScreen != 0 {
43		t.Fatalf("setup: cover %d", w.cover())
44	}
45	return c, w, cover
46}
47
48// toggle-stash-visible is a user override: under any covering fullscreen
49// window it shows the stash on top, focused, the window fullscreen
50// behind. Moves stay in the stash, at its edges too. Toggling again
51// hides it, back on the fullscreen window.
52func TestStashShowsOverCover(t *testing.T) {
53	for _, tc := range []struct {
54		name     string
55		overflow Overflow
56		float    bool
57	}{
58		{"fixed tile", OverflowFixed, false},
59		{"scroll tile", OverflowScroll, false},
60		{"fixed float", OverflowFixed, true},
61		{"scroll float", OverflowScroll, true},
62	} {
63		t.Run(tc.name, func(t *testing.T) {
64			c, w, cover := stashCoverCore(t, tc.overflow, tc.float)
65			c.applyAction(ActionToggleStashVisible)
66			ps := w.Layout()
67			if id, _ := w.Focused(); id != 3 || w.cover() != cover {
68				t.Fatalf("focused %d cover %d", id, w.cover())
69			}
70			if p := previewOf(t, ps, cover); p.Hidden || !p.Fullscreen {
71				t.Fatalf("cover %+v", p)
72			}
73			if p := previewOf(t, ps, 3); p.Hidden || ps[len(ps)-1].ID != 3 && ps[len(ps)-2].ID != 3 {
74				t.Fatalf("stash not on top: %+v", ps)
75			}
76			c.applyAction(ActionFocusColumnLeft)
77			if id, _ := w.Focused(); id != 2 || w.cover() != cover {
78				t.Fatalf("left: focused %d cover %d", id, w.cover())
79			}
80			c.applyAction(ActionFocusColumnRight)
81			c.applyAction(ActionFocusColumnRight) // stash edge: stays, like a shown stash
82			if id, _ := w.Focused(); id != 3 || c.focusScreen != 0 {
83				t.Fatalf("edge: focused %d screen %d", id, c.focusScreen)
84			}
85			c.applyAction(ActionToggleStashVisible)
86			if id, _ := w.Focused(); id != cover || w.cover() != cover || !previewOf(t, w.Layout(), 3).Hidden {
87				t.Fatalf("hide: focused %d cover %d", id, w.cover())
88			}
89		})
90	}
91}
92
93// Only the user shows the stash over the cover: a window mapping
94// meanwhile is not captured, a dialog of the cover shows above the
95// stash, and the override ends with its cover.
96func TestStashOverCoverEdges(t *testing.T) {
97	c, w, cover := stashCoverCore(t, OverflowFixed, false)
98	m := c.screens[0].mon
99	m.SetStashCapture(true)
100	c.applyAction(ActionToggleStashVisible)
101	m.AddWindow(5)
102	if w.stashIndex(5) >= 0 || !previewOf(t, w.Layout(), 5).Hidden {
103		t.Fatalf("new window shown: %+v", w.Layout())
104	}
105	w.AddDialog(6, cover, 20, 20)
106	if ps := w.Layout(); ps[len(ps)-1].ID != 6 {
107		t.Fatalf("dialog under the stash: %+v", ps)
108	}
109	if id, _ := w.Focused(); id != 6 {
110		t.Fatalf("dialog focus %d", id)
111	}
112	c.applyAction(ActionFocusColumnLeft) // back to the stash
113	if id, _ := w.Focused(); id != 3 || !w.stashOverCover() {
114		t.Fatalf("from dialog: focused %d", id)
115	}
116	w.RemoveWindow(6)
117	// The cover closes: the stash it showed over is a plain shown stash;
118	// a later fullscreen window is never covered by it.
119	w.RemoveWindow(cover)
120	if w.stashOver != 0 {
121		t.Fatal("override outlived its cover")
122	}
123	w.FocusID(5)
124	w.ToggleFullscreen()
125	if p := previewOf(t, w.Layout(), 3); !p.Hidden {
126		t.Fatalf("stash over a new cover: %+v", p)
127	}
128}
129
130// Another window's fullscreen request ends the override: the old cover
131// asking again never brings the stash back over it.
132func TestStashOverCoverOtherRequest(t *testing.T) {
133	c, w, cover := stashCoverCore(t, OverflowScroll, false)
134	m := c.screens[0].mon
135	m.AddWindow(5)
136	c.applyAction(ActionToggleStashVisible)
137	m.SetFullscreen(5, true)
138	m.SetFullscreen(cover, true)
139	if w.cover() != cover || w.stashOverCover() {
140		t.Fatalf("cover %d, override revived", w.cover())
141	}
142}
143
144// Acting on a stashed window over the cover leaves the cover for it:
145// toggle-window-stash returns it to a visible column, toggle-fullscreen
146// makes it the fullscreen window.
147func TestStashOverCoverLeaves(t *testing.T) {
148	c, w, _ := stashCoverCore(t, OverflowFixed, false)
149	c.applyAction(ActionToggleStashVisible)
150	c.applyAction(ActionToggleWindowStash)
151	if id, _ := w.Focused(); id != 3 || w.fullscreen != 0 || previewOf(t, w.Layout(), 3).Hidden {
152		t.Fatalf("unstash: focused %d fullscreen %d", id, w.fullscreen)
153	}
154	c, w, _ = stashCoverCore(t, OverflowFixed, false)
155	c.applyAction(ActionToggleStashVisible)
156	c.applyAction(ActionToggleFullscreen)
157	if w.cover() != 3 || w.left != 1 {
158		t.Fatalf("fullscreen: cover %d left %d", w.cover(), w.left)
159	}
160}

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 25

Tags 10

↑↓ moveenter openesc close