row_shares_test.go RawHistoryFolder

1package core
2
3import (
4	"slices"
5	"testing"
6)
7
8func heights(w *Workspace) map[WindowID]int {
9	out := map[WindowID]int{}
10	for _, p := range w.Layout() {
11		if !p.Floating {
12			out[p.ID] = p.Rect.H
13		}
14	}
15	return out
16}
17
18func sum(v []int) int {
19	t := 0
20	for _, x := range v {
21		t += x
22	}
23	return t
24}
25
26func TestRowRectsEqualWithoutShares(t *testing.T) {
27	r := Rect{X: 0, Y: 0, W: 50, H: 103}
28	c := Column{Windows: []WindowID{1, 2, 3}}
29	if !slices.Equal(rowRects(r, c, 5), stackRects(r, 3, 5)) {
30		t.Fatal(rowRects(r, c, 5))
31	}
32	c.Shares = []int{50, 50} // wrong length: ignored
33	if !slices.Equal(rowRects(r, c, 5), stackRects(r, 3, 5)) {
34		t.Fatal(rowRects(r, c, 5))
35	}
36	c.Shares = []int{50, 30, 30} // wrong sum: ignored
37	if !slices.Equal(rowRects(r, c, 5), stackRects(r, 3, 5)) {
38		t.Fatal(rowRects(r, c, 5))
39	}
40	c.Shares = []int{50, 30, 20}
41	rows := rowRects(r, c, 5)
42	if rows[0].H != 46 || rows[1].H != 27 || rows[2].H != 93-46-27 || rows[2].Y+rows[2].H != 103 {
43		t.Fatal(rows)
44	}
45}
46
47func TestResizeRow(t *testing.T) {
48	for _, o := range []Overflow{OverflowScroll, OverflowFixed} {
49		w := workspace()
50		w.Overflow = o
51		w.SetOutput(1000, 800)
52		w.Columns = []Column{{Windows: []WindowID{1, 2}}}
53		w.Apply("set-window-height +10%")
54		if !slices.Equal(w.Columns[0].Shares, []int{60, 40}) {
55			t.Fatal(o, w.Columns[0].Shares)
56		}
57		h := heights(w)
58		if h[1] <= h[2] {
59			t.Fatal(o, h)
60		}
61		for range 10 {
62			w.Apply("set-window-height +10%")
63		}
64		if !slices.Equal(w.Columns[0].Shares, []int{90, 10}) {
65			t.Fatal(o, w.Columns[0].Shares)
66		}
67		for range 10 {
68			w.Apply("set-window-height -10%")
69		}
70		if !slices.Equal(w.Columns[0].Shares, []int{10, 90}) {
71			t.Fatal(o, w.Columns[0].Shares)
72		}
73	}
74}
75
76func TestResizeRowThree(t *testing.T) {
77	w := workspace()
78	w.SetOutput(1000, 800)
79	w.Columns = []Column{{Windows: []WindowID{1, 2, 3}, Focus: 1}}
80	w.Apply("set-window-height +10%")
81	s := w.Columns[0].Shares
82	if sum(s) != 100 || s[1] != 43 || s[0] < 10 || s[2] < 10 {
83		t.Fatal(s)
84	}
85	for _, step := range []string{"+25%", "+25%", "-7%", "-100%", "+100%", "-3%"} {
86		w.Apply(Action("set-window-height " + step))
87		s := w.Columns[0].Shares
88		if sum(s) != 100 || slices.Min(s) < 10 {
89			t.Fatal(step, s)
90		}
91	}
92	if s := w.Columns[0].Shares; s[1] != 77 {
93		t.Fatal(s)
94	}
95	// Proportional: the others shrink by their room above the minimum.
96	w.Columns[0].Shares = []int{50, 20, 30}
97	w.Columns[0].Focus = 1
98	w.Apply("set-window-height +20%")
99	if s := w.Columns[0].Shares; !slices.Equal(s, []int{37, 40, 23}) {
100		t.Fatal(s)
101	}
102}
103
104func TestResizeRowNoops(t *testing.T) {
105	w := workspace()
106	w.Columns = []Column{{Windows: []WindowID{1}}}
107	w.Apply("set-window-height +10%")
108	if w.Columns[0].Shares != nil {
109		t.Fatal(w.Columns[0].Shares)
110	}
111	w.Columns = []Column{{Windows: []WindowID{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}}}
112	w.Apply("set-window-height +10%")
113	if w.Columns[0].Shares != nil {
114		t.Fatal(w.Columns[0].Shares)
115	}
116	w.Columns = []Column{{Windows: []WindowID{1, 2}}}
117	w.AddFloating(3, 10, 10)
118	w.Apply("set-window-height +10%")
119	if w.Columns[0].Shares != nil {
120		t.Fatal(w.Columns[0].Shares)
121	}
122	// A fullscreen window hides its column.
123	w = workspace()
124	w.Columns = []Column{{Windows: []WindowID{1, 2}}}
125	w.SetFullscreen(1, true)
126	w.Apply("set-window-height +10%")
127	if w.Columns[0].Shares != nil {
128		t.Fatal(w.Columns[0].Shares)
129	}
130}
131
132func TestSharesResetAndTravel(t *testing.T) {
133	m := monitor()
134	m.SetOutput(1000, 800)
135	m.AddWindow(1)
136	m.AddWindow(2)
137	w := m.Current()
138	w.ConsumeOrExpel(-1)
139	if len(w.Columns) != 1 {
140		t.Fatal(w.Columns)
141	}
142	w.Apply("set-window-height +20%")
143	if !slices.Equal(w.Columns[0].Shares, []int{30, 70}) {
144		t.Fatal(w.Columns[0].Shares)
145	}
146	// Moving the window inside the column swaps the shares with it.
147	w.Apply(ActionMoveWindowUp)
148	if !slices.Equal(w.Columns[0].Shares, []int{70, 30}) || w.Columns[0].Windows[0] != 2 {
149		t.Fatal(w.Columns[0])
150	}
151	// The column takes its shares to another workspace.
152	m.MoveToWorkspace(1, true)
153	m.FocusNumber(2)
154	if c := m.Current().Columns[0]; !slices.Equal(c.Shares, []int{70, 30}) {
155		t.Fatal(c)
156	}
157	// MoveColumn keeps them.
158	m.AddWindow(3)
159	m.Current().FocusColumn(-1)
160	m.Current().MoveColumn(1)
161	if c := m.Current().Columns[1]; !slices.Equal(c.Shares, []int{70, 30}) {
162		t.Fatal(m.Current().Columns)
163	}
164	// A window leaving resets the column to equal rows.
165	m.RemoveWindow(2)
166	m.AddWindow(4)
167	w = m.Current()
168	for _, c := range w.Columns {
169		if c.Shares != nil {
170			t.Fatal(w.Columns)
171		}
172	}
173	// A window joining invalidates them: equal rows.
174	w.Columns = []Column{{Windows: []WindowID{1, 3}, Shares: []int{80, 20}}}
175	w.Columns[0].Windows = append(w.Columns[0].Windows, 4)
176	h := heights(w)
177	if h[1] != h[3] {
178		t.Fatal(h)
179	}
180}
181
182func TestOverviewPreviewUsesShares(t *testing.T) {
183	w := workspace()
184	w.SetOutput(1000, 800)
185	w.Columns = []Column{{Windows: []WindowID{1, 2}, Shares: []int{70, 30}}}
186	tiles, _, _ := w.previewTiles()
187	h := map[WindowID]int{}
188	for _, p := range tiles {
189		h[p.ID] = p.Rect.H
190	}
191	live := heights(w)
192	if h[1] != live[1] || h[2] != live[2] {
193		t.Fatal(h, live)
194	}
195}

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