detached 90ccc85

refactor(layout): share the equal column width between fixed and cascade

commit
90ccc85322e811f65957842dff90035428286d80
author
brice · · 2026-10-07 15:54 UTC
parent
9376c1c
signature
GPG VerifiedCD88F9E564E0102646FB6077A1A07C7C7C3E349D · arch-gpg Verified for the committer email
2 files · +9 -8
M internal/core/cascade.go +7 -1
@@ -19,7 +19,13 @@ func (w *Workspace) cascadeBands() (n, spacing int) {
1919 // fills it.
2020 func (w *Workspace) cellWidth(i int) int {
2121 first, last := w.laneBounds(w.band(i))
22- k := max(last-first+1, 1)
22+ return w.equalShare(last - first + 1)
23+}
24+
25+// equalShare is the width of each of k columns sharing the usable width
26+// after gaps; a remainder under k pixels stays empty.
27+func (w *Workspace) equalShare(k int) int {
28+ k = max(k, 1)
2329 return max((w.Usable.W-w.gap()*(k+1))/k, 0)
2430 }
2531 func (w *Workspace) cellInBand(b int) int {
@@ -19,7 +19,13 @@ func (w *Workspace) cascadeBands() (n, spacing int) {
19 // fills it.19 // fills it.
20 func (w *Workspace) cellWidth(i int) int {20 func (w *Workspace) cellWidth(i int) int {
21 first, last := w.laneBounds(w.band(i))21 first, last := w.laneBounds(w.band(i))
22- k := max(last-first+1, 1)22+ return w.equalShare(last - first + 1)
23+}
24+
25+// equalShare is the width of each of k columns sharing the usable width
26+// after gaps; a remainder under k pixels stays empty.
27+func (w *Workspace) equalShare(k int) int {
28+ k = max(k, 1)
23 return max((w.Usable.W-w.gap()*(k+1))/k, 0)29 return max((w.Usable.W-w.gap()*(k+1))/k, 0)
24 }30 }
25 func (w *Workspace) cellInBand(b int) int {31 func (w *Workspace) cellInBand(b int) int {
M internal/core/layout.go +2 -7
@@ -1393,12 +1393,7 @@ func (w *Workspace) columnWidthFor(i int, ignoreFullWidth bool) int {
13931393 return w.cellWidth(i)
13941394 }
13951395 if w.Columns[i].Width == (Width{}) || w.policy().equalCells {
1396- if len(w.Columns) == 1 {
1397- return max(w.Usable.W-2*g, 0)
1398- }
1399- // Equal shares of the width left after gaps; a remainder under k pixels stays empty.
1400- k := min(len(w.Columns), max(w.MaxColumns, 1))
1401- return max((w.Usable.W-g*(k+1))/k, 0)
1396+ return w.equalShare(min(len(w.Columns), max(w.MaxColumns, 1)))
14021397 }
14031398 return w.Columns[i].Width.Resolve(w.Usable.W, g)
14041399 }
@@ -1492,7 +1487,7 @@ func (w *Workspace) columnRectsInto(dst []Rect, ignoreFullWidth bool) []Rect {
14921487 // right; the two strips share the last cell.
14931488 func (w *Workspace) expandedRects(rects []Rect, e, k, y, h int) []Rect {
14941489 g := w.gap()
1495- cell := max((w.Usable.W-g*(k+1))/k, 0)
1490+ cell := w.equalShare(k)
14961491 wide := (k-1)*cell + (k-2)*g
14971492 rest := max(w.Usable.W-2*g-wide-g, 0)
14981493 before, after := w.Columns[:e], w.Columns[e+1:]
@@ -1393,12 +1393,7 @@ func (w *Workspace) columnWidthFor(i int, ignoreFullWidth bool) int {
1393 return w.cellWidth(i)1393 return w.cellWidth(i)
1394 }1394 }
1395 if w.Columns[i].Width == (Width{}) || w.policy().equalCells {1395 if w.Columns[i].Width == (Width{}) || w.policy().equalCells {
1396- if len(w.Columns) == 1 {1396+ return w.equalShare(min(len(w.Columns), max(w.MaxColumns, 1)))
1397- return max(w.Usable.W-2*g, 0)
1398- }
1399- // Equal shares of the width left after gaps; a remainder under k pixels stays empty.
1400- k := min(len(w.Columns), max(w.MaxColumns, 1))
1401- return max((w.Usable.W-g*(k+1))/k, 0)
1402 }1397 }
1403 return w.Columns[i].Width.Resolve(w.Usable.W, g)1398 return w.Columns[i].Width.Resolve(w.Usable.W, g)
1404 }1399 }
@@ -1492,7 +1487,7 @@ func (w *Workspace) columnRectsInto(dst []Rect, ignoreFullWidth bool) []Rect {
1492 // right; the two strips share the last cell.1487 // right; the two strips share the last cell.
1493 func (w *Workspace) expandedRects(rects []Rect, e, k, y, h int) []Rect {1488 func (w *Workspace) expandedRects(rects []Rect, e, k, y, h int) []Rect {
1494 g := w.gap()1489 g := w.gap()
1495- cell := max((w.Usable.W-g*(k+1))/k, 0)1490+ cell := w.equalShare(k)
1496 wide := (k-1)*cell + (k-2)*g1491 wide := (k-1)*cell + (k-2)*g
1497 rest := max(w.Usable.W-2*g-wide-g, 0)1492 rest := max(w.Usable.W-2*g-wide-g, 0)
1498 before, after := w.Columns[:e], w.Columns[e+1:]1493 before, after := w.Columns[:e], w.Columns[e+1:]

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 23

Tags 10

↑↓ moveenter openesc close