feat/data-dnd e05cb15

workspaces.go RawHistoryFolder

1package core
2
3import (
4	"slices"
5	"strconv"
6
7	"github.com/bnema/neferwl/internal/ports"
8)
9
10// publishWorkspaces describes the numbered vertical stack and configured hidden
11// workspaces. Config-hidden named workspaces and empty numbered spares are
12// hidden unless shown; unlike State, hidden named workspaces remain addressable.
13// Like publishState, it is built in the owner's scratch and copied only
14// when sent.
15func (c *Core) publishWorkspaces() {
16	if c.ch.Workspaces == nil {
17		return
18	}
19	buf := &c.scratch.workspaces
20	buf.Outputs = buf.Outputs[:0]
21	for _, sc := range c.screens {
22		if sc.name() == "" {
23			continue
24		}
25		m := sc.mon
26		// Reuse the list of the entry this one overwrites.
27		var list []ports.WorkspaceInfo
28		if n := len(buf.Outputs); n < cap(buf.Outputs) {
29			list = buf.Outputs[:n+1][n].Workspaces[:0]
30		}
31		out := ports.WorkspaceOutput{Name: sc.name(), Workspaces: list}
32		i := -1
33		for w := range m.all() {
34			i++
35			name := w.Name
36			if name == "" {
37				name = strconv.Itoa(i + 1)
38			}
39			out.Workspaces = append(out.Workspaces, ports.WorkspaceInfo{ID: w.ID, Name: name, Index: i, Active: m.Current() == w, Hidden: m.Current() != w && (m.isHidden(w) || w.empty()), Configured: w.Name, Frame: w.Output})
40		}
41		buf.Outputs = append(buf.Outputs, out)
42	}
43	// The first snapshot is always sent, even an empty one.
44	if c.sent.workspaces.Outputs != nil && sameWorkspaces(*buf, c.sent.workspaces) {
45		return
46	}
47	// Empty lists stay non-nil (JSON []).
48	snapshot := ports.Workspaces{Outputs: make([]ports.WorkspaceOutput, len(buf.Outputs))}
49	for k, o := range buf.Outputs {
50		snapshot.Outputs[k] = ports.WorkspaceOutput{Name: o.Name, Workspaces: append([]ports.WorkspaceInfo{}, o.Workspaces...)}
51	}
52	c.sent.workspaces = snapshot
53	latest(c.ch.Workspaces, snapshot)
54}
55
56func sameWorkspaces(a, b ports.Workspaces) bool {
57	return slices.EqualFunc(a.Outputs, b.Outputs, func(x, y ports.WorkspaceOutput) bool {
58		return x.Name == y.Name && slices.Equal(x.Workspaces, y.Workspaces)
59	})
60}

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