detached 5041353

workspace_close_context.go RawHistoryFolder

1package coordinator
2
3import (
4	"errors"
5	"fmt"
6
7	"github.com/bnema/dumber/internal/domain/entity"
8	"github.com/bnema/dumber/internal/ui/layout"
9)
10
11type incrementalCloseContext struct {
12	parentNode           *entity.PaneNode
13	siblingNode          *entity.PaneNode
14	grandparentNode      *entity.PaneNode
15	parentWidget         layout.Widget
16	siblingIsStartChild  bool
17	parentIsStartInGrand bool
18	precheckReason       string
19}
20
21func deriveIncrementalCloseTreeContext(closingPane *entity.PaneNode) (incrementalCloseContext, error) {
22	var closeCtx incrementalCloseContext
23	if closingPane == nil {
24		return closeCtx, errors.New("closing pane missing")
25	}
26
27	parentNode := closingPane.Parent
28	if parentNode == nil {
29		return closeCtx, errors.New("closing pane has no parent")
30	}
31
32	closeCtx.parentNode = parentNode
33	closeCtx.grandparentNode = parentNode.Parent
34
35	if parentNode.IsStacked {
36		return closeCtx, nil
37	}
38
39	if !parentNode.IsSplit() {
40		return closeCtx, fmt.Errorf("parent node is not split: %s", parentNode.ID)
41	}
42
43	if len(parentNode.Children) != 2 {
44		return closeCtx, fmt.Errorf("split parent has invalid child count: %d", len(parentNode.Children))
45	}
46
47	leftChild := parentNode.Left()
48	rightChild := parentNode.Right()
49	if leftChild == closingPane && rightChild == nil {
50		return closeCtx, errors.New("sibling missing")
51	}
52	if rightChild == closingPane && leftChild == nil {
53		return closeCtx, errors.New("sibling missing")
54	}
55	if leftChild == nil || rightChild == nil {
56		return closeCtx, errors.New("split parent has nil child")
57	}
58
59	switch {
60	case leftChild == closingPane:
61		closeCtx.siblingNode = rightChild
62		closeCtx.siblingIsStartChild = false
63	case rightChild == closingPane:
64		closeCtx.siblingNode = leftChild
65		closeCtx.siblingIsStartChild = true
66	default:
67		return closeCtx, fmt.Errorf("closing pane not found under parent: %s", parentNode.ID)
68	}
69
70	if closeCtx.siblingNode == nil {
71		return closeCtx, errors.New("sibling missing")
72	}
73
74	if closeCtx.grandparentNode != nil {
75		switch {
76		case closeCtx.grandparentNode.Left() == parentNode:
77			closeCtx.parentIsStartInGrand = true
78		case closeCtx.grandparentNode.Right() == parentNode:
79			closeCtx.parentIsStartInGrand = false
80		default:
81			return closeCtx, fmt.Errorf("parent not found under grandparent: %s", closeCtx.grandparentNode.ID)
82		}
83	}
84
85	return closeCtx, nil
86}
87
88func paneNodeID(node *entity.PaneNode) string {
89	if node == nil {
90		return nilString
91	}
92	return node.ID
93}

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 8

Tags 42

↑↓ moveenter openesc close