main f2d166b

window_actions_test.go RawHistoryFolder

1package core
2
3import (
4	"reflect"
5	"slices"
6	"testing"
7)
8
9func TestMoveWindowInColumn(t *testing.T) {
10	for _, o := range []Overflow{OverflowScroll, OverflowFixed} {
11		w := workspace()
12		w.Overflow = o
13		w.Columns = []Column{{Windows: []WindowID{1, 2, 3}, Focus: 1}}
14		w.Apply(ActionMoveWindowUp)
15		if !slices.Equal(w.Columns[0].Windows, []WindowID{2, 1, 3}) || w.Columns[0].Focus != 0 {
16			t.Fatal(o, w.Columns)
17		}
18		// Top end: nothing moves.
19		w.Apply(ActionMoveWindowUp)
20		if !slices.Equal(w.Columns[0].Windows, []WindowID{2, 1, 3}) || w.Columns[0].Focus != 0 {
21			t.Fatal(o, w.Columns)
22		}
23		w.Apply(ActionMoveWindowDown)
24		w.Apply(ActionMoveWindowDown)
25		if !slices.Equal(w.Columns[0].Windows, []WindowID{1, 3, 2}) || w.Columns[0].Focus != 2 {
26			t.Fatal(o, w.Columns)
27		}
28		w.Apply(ActionMoveWindowDown)
29		if id, _ := w.Focused(); id != 2 || w.Columns[0].Focus != 2 {
30			t.Fatal(o, w.Columns)
31		}
32	}
33}
34
35func TestMoveWindowReleasesSlot(t *testing.T) {
36	w := workspace()
37	w.Columns = []Column{{Windows: []WindowID{1, 2}, Slot: 7}}
38	w.Apply(ActionMoveWindowDown)
39	if w.Columns[0].Slot != 0 || !slices.Equal(w.Columns[0].Windows, []WindowID{2, 1}) {
40		t.Fatal(w.Columns)
41	}
42	// A window moving into row 0 takes the place of the slot window: the
43	// slot is released too.
44	w = workspace()
45	w.Columns = []Column{{Windows: []WindowID{1, 2}, Slot: 7, Focus: 1}}
46	w.Apply(ActionMoveWindowUp)
47	if w.Columns[0].Slot != 0 {
48		t.Fatal(w.Columns)
49	}
50	// Rows below keep it.
51	w = workspace()
52	w.Columns = []Column{{Windows: []WindowID{1, 2, 3}, Slot: 7, Focus: 1}}
53	w.Apply(ActionMoveWindowDown)
54	if w.Columns[0].Slot != 7 {
55		t.Fatal(w.Columns)
56	}
57}
58
59func TestMoveWindowOnFloat(t *testing.T) {
60	w := workspace()
61	w.Columns = []Column{{Windows: []WindowID{1, 2}}}
62	w.AddFloating(3, 20, 20)
63	w.Apply(ActionMoveWindowDown)
64	if !slices.Equal(w.Columns[0].Windows, []WindowID{1, 2}) {
65		t.Fatal(w.Columns)
66	}
67}
68
69// set-column-width +N/-N moves cells with no cycle, and a column never
70// goes below one cell.
71func TestSetColumnWidth(t *testing.T) {
72	w := workspace()
73	w.SetOutput(1000, 800)
74	w.SetGaps(10)
75	w.SetMaxColumns(4)
76	w.Overflow = OverflowFixed
77	w.AddWindow(1)
78	w.AddWindow(2)
79	before := w.columnWidth(w.Focus)
80	w.Apply("set-column-width +1")
81	if w.Columns[w.Focus].Cells != 3 || w.columnWidth(w.Focus) <= before {
82		t.Fatal(w.Columns, w.columnWidth(w.Focus), before)
83	}
84	// No donor is left: the width stays, it does not cycle back.
85	w.Apply("set-column-width +1")
86	if w.Columns[0].Cells != 1 || w.Columns[1].Cells != 3 {
87		t.Fatal(w.Columns)
88	}
89	w.Apply("set-column-width -1")
90	if w.Columns[0].Cells != 2 || w.Columns[1].Cells != 2 || w.columnWidth(w.Focus) != before {
91		t.Fatal(w.Columns, w.columnWidth(w.Focus), before)
92	}
93	for range 5 {
94		w.Apply("set-column-width -1")
95	}
96	if w.Columns[1].Cells != 1 || w.Columns[0].Cells != 3 {
97		t.Fatal(w.Columns)
98	}
99	w.Apply("set-column-width +2")
100	if w.Columns[1].Cells != 3 || w.Columns[0].Cells != 1 {
101		t.Fatal(w.Columns)
102	}
103}
104
105func TestSetColumnWidthScroll(t *testing.T) {
106	w := workspace()
107	w.SetOutput(1000, 800)
108	w.SetMaxColumns(4)
109	w.Overflow = OverflowScroll
110	w.AddWindow(1)
111	w.AddWindow(2)
112	w.Apply("set-column-width +1")
113	if w.Columns[w.Focus].Cells != 3 {
114		t.Fatal(w.Columns)
115	}
116	for range 5 {
117		w.Apply("set-column-width +1")
118	}
119	if w.Columns[w.Focus].Cells != 4 {
120		t.Fatal("grows up to max-columns", w.Columns)
121	}
122	for range 9 {
123		w.Apply("set-column-width -1")
124	}
125	if w.Columns[w.Focus].Cells != 1 {
126		t.Fatal("never below one cell", w.Columns)
127	}
128}
129
130func TestSetColumnWidthUnmaximizes(t *testing.T) {
131	for _, a := range []Action{"set-column-width +1", "set-column-width -1", ActionCycleColumnWidth} {
132		w := workspace()
133		w.SetOutput(1000, 800)
134		w.SetMaxColumns(4)
135		w.AddWindow(1)
136		w.ToggleFullWidth()
137		w.Apply(a)
138		if w.Columns[0].FullWidth {
139			t.Fatalf("%s: still maximized", a)
140		}
141	}
142}
143
144func TestColumnEditsUnderFullscreen(t *testing.T) {
145	w := workspace()
146	w.SetOutput(1000, 800)
147	w.Columns = []Column{{Windows: []WindowID{1, 2}, Cells: 1}}
148	w.SetFullscreen(1, true)
149	w.Apply("set-column-width -1")
150	w.Apply(ActionCycleColumnWidth)
151	w.Apply(ActionMoveWindowDown)
152	c := w.Columns[0]
153	if c.Cells != 1 || !slices.Equal(c.Windows, []WindowID{1, 2}) {
154		t.Fatal(c)
155	}
156}
157
158func TestSetColumnWidthFixedPastMax(t *testing.T) {
159	w := workspace()
160	w.Overflow = OverflowFixed
161	for id := WindowID(1); id <= 3; id++ {
162		w.AddWindow(id)
163	}
164	w.Apply("set-column-width +1")
165	w.Apply("set-column-width -1")
166	w.Apply(ActionCycleColumnWidth)
167	for _, c := range w.Columns {
168		if c.Cells != 0 {
169			t.Fatal(w.Columns)
170		}
171	}
172}
173
174func TestMoveWorkspace(t *testing.T) {
175	m := monitor()
176	m.AddWindow(1)
177	m.FocusNumber(2)
178	m.AddWindow(2)
179	m.FocusNumber(3)
180	m.AddWindow(3)
181	// [1:{1}] [2:{2}] [3:{3}] [4:{}]
182	m.Apply(ActionMoveWorkspacePrev)
183	if !reflect.DeepEqual(windows(m), [][]WindowID{{1}, {3}, {2}, {}}) || m.Active != 1 {
184		t.Fatal(windows(m), m.Active)
185	}
186	m.Apply(ActionMoveWorkspacePrev)
187	m.Apply(ActionMoveWorkspacePrev)
188	if !reflect.DeepEqual(windows(m), [][]WindowID{{3}, {1}, {2}, {}}) || m.Active != 0 {
189		t.Fatal(windows(m), m.Active)
190	}
191	m.Apply(ActionMoveWorkspaceNext)
192	m.Apply(ActionMoveWorkspaceNext)
193	// Never past the trailing empty workspace.
194	m.Apply(ActionMoveWorkspaceNext)
195	if !reflect.DeepEqual(windows(m), [][]WindowID{{1}, {2}, {3}, {}}) || m.Active != 2 {
196		t.Fatal(windows(m), m.Active)
197	}
198	// The trailing empty workspace does not move.
199	m.FocusNumber(4)
200	m.Apply(ActionMoveWorkspacePrev)
201	if !reflect.DeepEqual(windows(m), [][]WindowID{{1}, {2}, {3}, {}}) || m.Active != 3 {
202		t.Fatal(windows(m), m.Active)
203	}
204}
205
206func TestMoveWorkspaceHidden(t *testing.T) {
207	m := named(monitor(), NamedWorkspace{Name: "dev"})
208	m.AddWindow(1)
209	m.FocusNumber(2)
210	m.AddWindow(2)
211	m.ToggleNamed("dev")
212	m.Apply(ActionMoveWorkspacePrev)
213	if !reflect.DeepEqual(windows(m), [][]WindowID{{1}, {2}, {}}) {
214		t.Fatal(windows(m))
215	}
216}

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