package tui import ( "fmt" "strings" "github.com/charmbracelet/lipgloss" ) type hint struct { key string desc string } func renderHints(hints []hint) string { parts := make([]string, len(hints)) for i, h := range hints { parts[i] = hintKeyStyle.Render(h.key) + " " + hintDescStyle.Render(h.desc) } return strings.Join(parts, " ") } func renderTab(label, key string, active bool) string { if active { return hintKeyStyle.Render(label) + " " + hintDescStyle.Render(key) } return hintDescStyle.Render(label) + " " + hintKeyStyle.Render(key) } func renderStatusBar(m model, width int) string { var leftParts []string if m.status != "" { leftParts = append(leftParts, statusStyle.Render(m.status)) } else if preview := m.input.previewText(); m.focus == focusCapture && preview != "" { leftParts = append(leftParts, drawerPreviewStyle.Render(preview)) } else { leftParts = append(leftParts, statusStyle.Render(countText(m))) } leftRendered := strings.Join(leftParts, " "+separatorStyle.Render("│")+" ") right := renderHints(contextHints(m)) gap := width - lipgloss.Width(leftRendered) - lipgloss.Width(right) if gap < 0 { gap = 0 } pad := lipgloss.NewStyle().Width(gap).Render("") return leftRendered + pad + right } func countText(m model) string { var total int if m.mode == modeCards { total = len(m.cards.filtered) } else { total = len(m.list.displayEntities()) } if m.filterTag != "" { return fmt.Sprintf("%d entities #%s", total, m.filterTag) } return fmt.Sprintf("%d entities", total) } func contextHints(m model) []hint { switch m.state { case stateDetail: switch m.detail.mode { case detailRun: return []hint{{"space", "toggle"}, {"j/k", "nav"}, {"r", "reset"}, {"esc", "save+exit"}} case detailFill: return []hint{{"tab", "next"}, {"⇧tab", "prev"}, {"enter", "copy"}, {"esc", "cancel"}} default: return []hint{{"p", "promote"}, {"D", "demote"}, {"c", "copy"}, {"e", "edit"}, {"r", "run"}, {"f", "fill"}, {"!", "pin"}, {"esc", "back"}} } case stateTagFilter: return []hint{{"j/k", "nav"}, {"enter", "select"}, {"esc", "cancel"}} case stateConfirm: return []hint{{"y", "confirm"}, {"n", "cancel"}} case statePromote: return []hint{{"j/k", "nav"}, {"enter", "select"}, {"esc", "cancel"}} case stateAbsorb: return []hint{{"j/k", "nav"}, {"enter", "absorb"}, {"esc", "cancel"}} } switch m.focus { case focusCapture: return []hint{{"enter", "submit"}, {"esc", "browse"}, {"?…", "search"}, {"-", "todo"}, {"@", "event"}} case focusDetail: if m.splitDetail { return []hint{{"h", "list"}, {"c", "copy"}, {"e", "edit"}, {"p", "promote"}, {"!", "pin"}, {"tab", "capture"}} } return []hint{{"c", "copy"}, {"e", "edit"}, {"p", "promote"}, {"!", "pin"}, {"esc", "back"}} default: if m.splitDetail { return []hint{{"l", "detail"}, {"d", "del"}, {"#", "filter"}, {"tab", "capture"}, {"?", "help"}} } if m.mode == modeCards { return []hint{{"s", "sort"}, {"i", "intent"}, {"tab", "capture"}, {"?", "help"}} } return []hint{{"m", "absorb"}, {"d", "del"}, {"#", "filter"}, {"tab", "capture"}, {"?", "help"}} } }