wip
This commit is contained in:
@@ -1,5 +1,19 @@
|
||||
package app
|
||||
|
||||
import "github.com/hjbdev/patterm/internal/scratchpad"
|
||||
|
||||
// navEntry is one row in the unified sidebar navigation list. Exactly
|
||||
// one of childID or pad is set. childID points at a Child by ID; pad
|
||||
// names a scratchpad entry. Empty zero-value means "no target".
|
||||
type navEntry struct {
|
||||
childID string
|
||||
pad string
|
||||
}
|
||||
|
||||
func (n navEntry) empty() bool { return n.childID == "" && n.pad == "" }
|
||||
func (n navEntry) isPad() bool { return n.pad != "" }
|
||||
func (n navEntry) isChild() bool { return n.childID != "" }
|
||||
|
||||
// visibleAgentTree returns the running entries under the active agent
|
||||
// tab (root agent + its sub-agents). With the new Processes pane,
|
||||
// command processes live in their own section and never show up here —
|
||||
@@ -200,9 +214,66 @@ func sidebarNavList(children []*Child, activeAgentID string) []*Child {
|
||||
return out
|
||||
}
|
||||
|
||||
// nextChildID returns the id `step` positions away from the current
|
||||
// focus in the combined Processes + active-agent-tree navigation list,
|
||||
// wrapping at both ends. Empty when there's nothing else to land on.
|
||||
// sidebarNav returns the combined Processes + Agent Tree + Scratchpads
|
||||
// navigation list. Scratchpads always appear after children so the
|
||||
// existing "step past the tree" expectation still holds.
|
||||
func sidebarNav(children []*Child, activeAgentID string, pads []scratchpad.Entry) []navEntry {
|
||||
flat := sidebarNavList(children, activeAgentID)
|
||||
out := make([]navEntry, 0, len(flat)+len(pads))
|
||||
for _, c := range flat {
|
||||
out = append(out, navEntry{childID: c.ID})
|
||||
}
|
||||
for _, p := range pads {
|
||||
out = append(out, navEntry{pad: p.Name})
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// nextNavEntry returns the entry `step` positions away from the
|
||||
// current focus in the unified nav list. Either focusChildID or
|
||||
// focusPad will be set (or both empty for "nothing focused yet").
|
||||
// Empty when there's nothing else to land on.
|
||||
func nextNavEntry(children []*Child, focusChildID, focusPad, activeAgentID string, pads []scratchpad.Entry, step int) navEntry {
|
||||
flat := sidebarNav(children, activeAgentID, pads)
|
||||
if len(flat) == 0 {
|
||||
return navEntry{}
|
||||
}
|
||||
matches := func(e navEntry) bool {
|
||||
if focusPad != "" && e.pad != "" {
|
||||
return e.pad == focusPad
|
||||
}
|
||||
if focusChildID != "" && e.childID != "" {
|
||||
return e.childID == focusChildID
|
||||
}
|
||||
return false
|
||||
}
|
||||
if len(flat) == 1 {
|
||||
if matches(flat[0]) {
|
||||
return navEntry{}
|
||||
}
|
||||
return flat[0]
|
||||
}
|
||||
idx := -1
|
||||
for i, e := range flat {
|
||||
if matches(e) {
|
||||
idx = i
|
||||
break
|
||||
}
|
||||
}
|
||||
if idx < 0 {
|
||||
idx = 0
|
||||
}
|
||||
idx = (idx + step) % len(flat)
|
||||
if idx < 0 {
|
||||
idx += len(flat)
|
||||
}
|
||||
if matches(flat[idx]) {
|
||||
return navEntry{}
|
||||
}
|
||||
return flat[idx]
|
||||
}
|
||||
|
||||
// nextChildID is retained for tests; it ignores scratchpads.
|
||||
func nextChildID(children []*Child, focusID, activeAgentID string, step int) string {
|
||||
flat := sidebarNavList(children, activeAgentID)
|
||||
if len(flat) == 0 {
|
||||
|
||||
Reference in New Issue
Block a user