feat(tui-go): command-palette keybinds + configurable status bar
Palette: each command now shows its bare-key shortcut in a key column (and the filter matches on it), so the palette teaches the shortcuts instead of hiding them. Status bar: a new "status bar" palette command opens a toggle overlay to show/hide the non-essential segments (current stage, session status, workspace path, model, last-event clock, resource gauge); correx/connection/session-name/spinner stay. Choices persist TUI-local in tui-prefs.json (JSON in the config dir — display state, kept out of the shared/replayed server config) and reload on launch. Also trims the in-session footer (drops stats/model — both reachable via `p cmds`) so it no longer overflows + truncates `q quit` at ~100 cols after the transcript-nav additions. Tests cover toggle→render gating and prefs persistence; verified via cmd/preview renders. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -126,6 +126,8 @@ func (m Model) renderOverlay(base string) string {
|
||||
return m.center(m.sessionsModal())
|
||||
case OverlayFiles:
|
||||
return m.center(m.filesModal())
|
||||
case OverlayStatusbar:
|
||||
return m.center(m.statusbarModal())
|
||||
}
|
||||
return base
|
||||
}
|
||||
@@ -513,8 +515,13 @@ func (m Model) paletteModal() string {
|
||||
marker = lipgloss.NewStyle().Foreground(t.P.Accent).Background(t.P.BgPanel).Render("▌ ")
|
||||
titleFg = t.P.FgStrong
|
||||
}
|
||||
b.WriteString(marker +
|
||||
lipgloss.NewStyle().Foreground(titleFg).Background(t.P.BgPanel).Render(padRaw(c.title, 18)) +
|
||||
// keybind column: the bare-key shortcut, so the palette teaches the shortcuts.
|
||||
keyCell := mbg(t, padRaw("", 4), t.P.BgPanel)
|
||||
if c.key != "" {
|
||||
keyCell = lipgloss.NewStyle().Foreground(t.P.Accent2).Background(t.P.BgPanel).Bold(true).Render(padRaw(c.key, 4))
|
||||
}
|
||||
b.WriteString(marker + keyCell +
|
||||
lipgloss.NewStyle().Foreground(titleFg).Background(t.P.BgPanel).Render(padRaw(c.title, 16)) +
|
||||
mbg(t, " "+c.hint, t.P.Faint) + "\n")
|
||||
}
|
||||
b.WriteString("\n" + modalHints(t, [][2]string{{"↑↓", "select"}, {"enter", "run"}, {"esc", "close"}}))
|
||||
@@ -579,6 +586,35 @@ func (m Model) filesModal() string {
|
||||
return m.center(modal)
|
||||
}
|
||||
|
||||
// statusbarModal toggles which status-bar segments are shown. Choices persist to the local
|
||||
// tui-prefs.json so the bar stays as configured across launches.
|
||||
func (m Model) statusbarModal() string {
|
||||
t := m.theme
|
||||
w := m.modalWidth()
|
||||
|
||||
var b strings.Builder
|
||||
b.WriteString(m.titleLine("status bar") + "\n\n")
|
||||
b.WriteString(mbg(t, " show / hide segments (correx, connection, session name stay)", t.P.Faint) + "\n\n")
|
||||
|
||||
for i, seg := range statusSegments {
|
||||
marker := mbg(t, " ", t.P.BgPanel)
|
||||
labelFg := t.P.Fg
|
||||
if i == m.sbIndex {
|
||||
marker = lipgloss.NewStyle().Foreground(t.P.Accent).Background(t.P.BgPanel).Render("▌ ")
|
||||
labelFg = t.P.FgStrong
|
||||
}
|
||||
box := lipgloss.NewStyle().Foreground(t.P.OK).Background(t.P.BgPanel).Render("[✓] ")
|
||||
if !m.sbShow(seg.id) {
|
||||
box = mbg(t, "[ ] ", t.P.Faint)
|
||||
}
|
||||
b.WriteString(marker + box +
|
||||
lipgloss.NewStyle().Foreground(labelFg).Background(t.P.BgPanel).Render(seg.label) + "\n")
|
||||
}
|
||||
b.WriteString("\n" + modalHints(t, [][2]string{{"↑↓", "move"}, {"space", "toggle"}, {"esc", "close"}}))
|
||||
modal := t.Overlay.Width(w).Render(b.String())
|
||||
return m.center(modal)
|
||||
}
|
||||
|
||||
func (m Model) toolPaletteModal() string {
|
||||
t := m.theme
|
||||
w := m.modalWidth()
|
||||
|
||||
Reference in New Issue
Block a user