v0.10.0: TUI visual overhaul — dark-neutral theme, left-border messages, sidebar auto-show, cl-tty style-reset

- Theme: near-black (#0a0a0a) backgrounds, dark-grey panels (#141414),
  warm amber (#fab283) accent only. New keys: :bg, :bg-panel, :bg-element,
  :text-muted. All 13 presets updated.
- Messages: No background fills (sit on global black). User messages get
  amber left border (│). Agent response has no border (invisible).
  Streaming agent messages get grey left border. Gate traces and tool
  calls use grey ╎ prefix. No label lines, no time separators.
- Sidebar: :sidebar-mode with :auto/:visible/:hidden. Auto-shows at >120
  cols (opencode-style). Width 42 with version + connection dot footer.
- Input: 2-char hpad on each side. Grey panel (2 rows: separator +
  prompt). Hint right-aligned at bottom on black.
- Status bar: empty (clean black line).
- cl-tty backend: draw-text, draw-rect, draw-link, draw-border now use
  \e[22;23;24;25;27m (style-only reset) instead of \e[0m (full reset),
  preserving foreground/background across draw calls.
- Fix: all sidebar text draws pass explicit bg-panel background.
- Fix: hint at h-1 passes explicit (theme-color :bg).
- Fix: sidebar bottom row uses draw-text (no \n) to prevent scroll at h-1.
This commit is contained in:
2026-05-16 08:02:53 -04:00
parent 3bc1977632
commit 0a0478f502
3 changed files with 394 additions and 332 deletions

View File

@@ -33,152 +33,197 @@ All state mutation flows through event handlers in the controller.
(defvar *event-lock* (bt:make-lock "tui-event-lock"))
(defvar *tui-theme*
'(:user-fg "#FFB347" :user-bg "#3A2A1A" :user-border "#CC8800"
:agent-header "#D4956A" :agent-fg "#E8D5B7"
:system "#C8A87C"
:input-prompt "#FF8C42" :input-fg "#E8D5B7"
:hint "#A08060"
:status-bg "#2A1F1A" :status-fg "#D4A574"
:dot-connected "#7CCC6C" :dot-disconnected "#E2584A"
:error "#E2584A"
:tool-running "#FF8C42" :tool-done "#7CCC6C" :tool-error "#E2584A"
:separator "#4A3A2A" :accent "#FFB347" :dim "#8B7355")
"Warm amber/gold color theme. 20 semantic keys → hex color strings.")
'(:user-fg "#fab283" :user-bg "#1e1e1e" :user-border "#fab283"
:agent-header "#d4956a" :agent-fg "#e8e8e8"
:system "#808080"
:input-prompt "#fab283" :input-fg "#e8e8e8"
:hint "#606060"
:status-bg "#141414" :status-fg "#e8e8e8"
:bg "#0a0a0a" :bg-panel "#141414" :bg-element "#1e1e1e"
:text-muted "#808080"
:dot-connected "#7fd88f" :dot-disconnected "#e06c75"
:error "#e06c75"
:tool-running "#fab283" :tool-done "#7fd88f" :tool-error "#e06c75"
:separator "#3c3c3c" :accent "#fab283" :dim "#606060")
"Dark-neutral color theme with warm amber accent. Backgrounds are dark grays,
semantic text colors for context. Keys: :bg (deepest), :bg-panel, :bg-element,
:text-muted, :user-fg/bg/border, :agent-header/fg, :system, :input-prompt/fg,
:hint, :status-bg/fg, :dot-connected/disconnected, :error, :tool-*,
:separator, :accent, :dim.")
(defvar *tui-theme-presets*
'(:amber (:user-fg "#FFB347" :user-bg "#3A2A1A" :user-border "#CC8800"
:agent-header "#D4956A" :agent-fg "#E8D5B7"
:system "#C8A87C"
:input-prompt "#FF8C42" :input-fg "#E8D5B7"
:hint "#A08060"
:status-bg "#2A1F1A" :status-fg "#D4A574"
:dot-connected "#7CCC6C" :dot-disconnected "#E2584A"
:error "#E2584A"
:tool-running "#FF8C42" :tool-done "#7CCC6C" :tool-error "#E2584A"
:separator "#4A3A2A" :accent "#FFB347" :dim "#8B7355")
:gold (:user-fg "#FFD700" :user-bg "#3A3020" :user-border "#DAA520"
:agent-header "#D4A574" :agent-fg "#F0E6D0"
:system "#C8A87C"
:input-prompt "#FFA500" :input-fg "#F0E6D0"
:hint "#A08060"
:status-bg "#2A1F1A" :status-fg "#DAA520"
:dot-connected "#7CCC6C" :dot-disconnected "#E2584A"
:error "#E2584A"
:tool-running "#FFA500" :tool-done "#7CCC6C" :tool-error "#E2584A"
:separator "#4A3A2A" :accent "#FFD700" :dim "#8B7355")
:terracotta (:user-fg "#E87A5D" :user-bg "#2D1C15" :user-border "#C0684A"
:agent-header "#D4956A" :agent-fg "#E0C8B0"
:system "#A08060"
:input-prompt "#E87A5D" :input-fg "#E0C8B0"
:hint "#8B6F5E"
:status-bg "#1F1410" :status-fg "#D4956A"
:dot-connected "#6CB85C" :dot-disconnected "#D94A3A"
:error "#D94A3A"
:tool-running "#E87A5D" :tool-done "#6CB85C" :tool-error "#D94A3A"
:separator "#3A2820" :accent "#E87A5D" :dim "#7A6050")
:sepia (:user-fg "#C4A882" :user-bg "#2A2218" :user-border "#A08860"
:agent-header "#B89870" :agent-fg "#D4C4A8"
:system "#9A8A6A"
:input-prompt "#C4A882" :input-fg "#D4C4A8"
:hint "#8A7A5E"
:status-bg "#1E1810" :status-fg "#B89870"
:dot-connected "#7AAC5C" :dot-disconnected "#C84A3A"
:error "#C84A3A"
:tool-running "#C4A882" :tool-done "#7AAC5C" :tool-error "#C84A3A"
:separator "#3A3020" :accent "#C4A882" :dim "#7A6A50")
:nord-warm (:user-fg "#D4A574" :user-bg "#2A2220" :user-border "#B8885A"
:agent-header "#C49870" :agent-fg "#E0D0C0"
:system "#A89080"
:input-prompt "#D08770" :input-fg "#E0D0C0"
:hint "#908070"
:status-bg "#1E1A18" :status-fg "#C8A080"
:dot-connected "#7CB860" :dot-disconnected "#D06050"
:error "#D06050"
:tool-running "#D08770" :tool-done "#7CB860" :tool-error "#D06050"
:separator "#3A3030" :accent "#D4A574" :dim "#807060")
:monokai-warm (:user-fg "#E6B87D" :user-bg "#1E1A16" :user-border "#CC9966"
:agent-header "#D4A06A" :agent-fg "#D8C8B0"
:system "#A89070"
:input-prompt "#E6B87D" :input-fg "#D8C8B0"
:hint "#8A7A5E"
:status-bg "#141210" :status-fg "#CC9966"
:dot-connected "#7AB85C" :dot-disconnected "#D94A3A"
:error "#D94A3A"
:tool-running "#E6B87D" :tool-done "#7AB85C" :tool-error "#D94A3A"
:separator "#2E2820" :accent "#E6B87D" :dim "#7A6A50")
:gruvbox-warm (:user-fg "#D8A657" :user-bg "#1D1A16" :user-border "#B8884A"
:agent-header "#C8A070" :agent-fg "#E0C8A8"
:system "#A89070"
:input-prompt "#D8A657" :input-fg "#E0C8A8"
:hint "#8A7A5E"
:status-bg "#141210" :status-fg "#C8A070"
:dot-connected "#7AB85C" :dot-disconnected "#D94A3A"
:error "#D94A3A"
:tool-running "#D8A657" :tool-done "#7AB85C" :tool-error "#D94A3A"
:separator "#2E2820" :accent "#D8A657" :dim "#7A6A50")
:light-amber (:user-fg "#CC6600" :user-bg "#FFF5E6" :user-border "#CC8800"
:agent-header "#8B6914" :agent-fg "#3A2A1A"
:system "#6B5B3E"
:input-prompt "#CC6600" :input-fg "#3A2A1A"
:hint "#8B7355"
:status-bg "#E8D5B7" :status-fg "#3A2A1A"
:dot-connected "#2E8B57" :dot-disconnected "#CC3300"
:error "#CC3300"
:tool-running "#CC6600" :tool-done "#2E8B57" :tool-error "#CC3300"
:separator "#C8B898" :accent "#CC6600" :dim "#8B7355")
:catppuccin (:user-fg "#FAB387" :user-bg "#1E1E2E" :user-border "#F5A97F"
:agent-header "#CBA6F7" :agent-fg "#CDD6F4"
:system "#94E2D5"
:input-prompt "#FAB387" :input-fg "#CDD6F4"
:hint "#6C7086"
:status-bg "#181825" :status-fg "#A6ADC8"
:dot-connected "#A6E3A1" :dot-disconnected "#F38BA8"
:error "#F38BA8"
:tool-running "#FAB387" :tool-done "#A6E3A1" :tool-error "#F38BA8"
:separator "#313244" :accent "#FAB387" :dim "#585B70")
:tokyonight (:user-fg "#FF9E64" :user-bg "#1A1B26" :user-border "#F59E4C"
:agent-header "#7AA2F7" :agent-fg "#A9B1D6"
:system "#73DACA"
:input-prompt "#FF9E64" :input-fg "#A9B1D6"
:hint "#565F89"
:status-bg "#16161E" :status-fg "#9AA5CE"
:dot-connected "#9ECE6A" :dot-disconnected "#DB4B4B"
:error "#DB4B4B"
:tool-running "#FF9E64" :tool-done "#9ECE6A" :tool-error "#DB4B4B"
:separator "#292E42" :accent "#FF9E64" :dim "#444B6A")
:dracula (:user-fg "#FF9580" :user-bg "#1E1F2B" :user-border "#FF6E6E"
:agent-header "#BD93F9" :agent-fg "#F8F8F2"
:system "#8BE9FD"
:input-prompt "#FF9580" :input-fg "#F8F8F2"
:hint "#6272A4"
:status-bg "#191A24" :status-fg "#E0E0E0"
:dot-connected "#50FA7B" :dot-disconnected "#FF5555"
:error "#FF5555"
:tool-running "#FF9580" :tool-done "#50FA7B" :tool-error "#FF5555"
:separator "#34354A" :accent "#FF9580" :dim "#5A5B7A")
:gemini (:user-fg "#87AFFF" :user-bg "#000000" :user-border "#5F5F5F"
:agent-header "#D7AFFF" :agent-fg "#FFFFFF"
:system "#87D7D7"
:input-prompt "#87AFFF" :input-fg "#FFFFFF"
:hint "#AFAFAF"
:status-bg "#1A1A1A" :status-fg "#AFAFAF"
:dot-connected "#D7FFD7" :dot-disconnected "#FF87AF"
:error "#FF87AF"
:tool-running "#87AFFF" :tool-done "#D7FFD7" :tool-error "#FF87AF"
:separator "#3A3A3A" :accent "#87AFFF" :dim "#5F5F5F")
:mono (:user-fg "#E0E0E0" :user-bg "#1A1A1A" :user-border "#808080"
:agent-header "#C0C0C0" :agent-fg "#D0D0D0"
:system "#A0A0A0"
:input-prompt "#FFFFFF" :input-fg "#D0D0D0"
:hint "#606060"
:status-bg "#141414" :status-fg "#B0B0B0"
:dot-connected "#A0A0A0" :dot-disconnected "#808080"
:error "#808080"
:tool-running "#E0E0E0" :tool-done "#A0A0A0" :tool-error "#808080"
:separator "#303030" :accent "#FFFFFF" :dim "#505050"))
"13 warm theme presets (amber, gold, terracotta, sepia, nord-warm,
'(:amber
(:user-fg "#fab283" :user-bg "#1e1e1e" :user-border "#fab283"
:agent-header "#d4956a" :agent-fg "#e8e8e8"
:system "#808080"
:input-prompt "#fab283" :input-fg "#e8e8e8"
:hint "#606060"
:status-bg "#141414" :status-fg "#e8e8e8"
:bg "#0a0a0a" :bg-panel "#141414" :bg-element "#1e1e1e"
:text-muted "#808080"
:dot-connected "#7fd88f" :dot-disconnected "#e06c75"
:error "#e06c75"
:tool-running "#fab283" :tool-done "#7fd88f" :tool-error "#e06c75"
:separator "#3c3c3c" :accent "#fab283" :dim "#606060")
:gold
(:user-fg "#ffd700" :user-bg "#1e1e1e" :user-border "#ffd700"
:agent-header "#d4a574" :agent-fg "#e8e8e8"
:system "#808080"
:input-prompt "#ffd700" :input-fg "#e8e8e8"
:hint "#606060"
:status-bg "#141414" :status-fg "#ffd700"
:bg "#0a0a0a" :bg-panel "#141414" :bg-element "#1e1e1e"
:text-muted "#808080"
:dot-connected "#7fd88f" :dot-disconnected "#e06c75"
:error "#e06c75"
:tool-running "#ffd700" :tool-done "#7fd88f" :tool-error "#e06c75"
:separator "#3c3c3c" :accent "#ffd700" :dim "#606060")
:terracotta
(:user-fg "#e87a5d" :user-bg "#1e1e1e" :user-border "#e87a5d"
:agent-header "#d4956a" :agent-fg "#e0c8b0"
:system "#808080"
:input-prompt "#e87a5d" :input-fg "#e0c8b0"
:hint "#606060"
:status-bg "#141414" :status-fg "#d4956a"
:bg "#0a0a0a" :bg-panel "#141414" :bg-element "#1e1e1e"
:text-muted "#808080"
:dot-connected "#6cb85c" :dot-disconnected "#d94a3a"
:error "#d94a3a"
:tool-running "#e87a5d" :tool-done "#6cb85c" :tool-error "#d94a3a"
:separator "#3c3c3c" :accent "#e87a5d" :dim "#606060")
:sepia
(:user-fg "#c4a882" :user-bg "#1e1e1e" :user-border "#c4a882"
:agent-header "#b89870" :agent-fg "#d4c4a8"
:system "#808080"
:input-prompt "#c4a882" :input-fg "#d4c4a8"
:hint "#606060"
:status-bg "#141414" :status-fg "#b89870"
:bg "#0a0a0a" :bg-panel "#141414" :bg-element "#1e1e1e"
:text-muted "#808080"
:dot-connected "#7aac5c" :dot-disconnected "#c84a3a"
:error "#c84a3a"
:tool-running "#c4a882" :tool-done "#7aac5c" :tool-error "#c84a3a"
:separator "#3c3c3c" :accent "#c4a882" :dim "#606060")
:nord-warm
(:user-fg "#d4a574" :user-bg "#1e1e1e" :user-border "#d4a574"
:agent-header "#c49870" :agent-fg "#e0d0c0"
:system "#808080"
:input-prompt "#d08770" :input-fg "#e0d0c0"
:hint "#606060"
:status-bg "#141414" :status-fg "#c8a080"
:bg "#0a0a0a" :bg-panel "#141414" :bg-element "#1e1e1e"
:text-muted "#808080"
:dot-connected "#7cb860" :dot-disconnected "#d06050"
:error "#d06050"
:tool-running "#d08770" :tool-done "#7cb860" :tool-error "#d06050"
:separator "#3c3c3c" :accent "#d4a574" :dim "#606060")
:monokai-warm
(:user-fg "#e6b87d" :user-bg "#1e1e1e" :user-border "#e6b87d"
:agent-header "#d4a06a" :agent-fg "#d8c8b0"
:system "#808080"
:input-prompt "#e6b87d" :input-fg "#d8c8b0"
:hint "#606060"
:status-bg "#141414" :status-fg "#cc9966"
:bg "#0a0a0a" :bg-panel "#141414" :bg-element "#1e1e1e"
:text-muted "#808080"
:dot-connected "#7ab85c" :dot-disconnected "#d94a3a"
:error "#d94a3a"
:tool-running "#e6b87d" :tool-done "#7ab85c" :tool-error "#d94a3a"
:separator "#3c3c3c" :accent "#e6b87d" :dim "#606060")
:gruvbox-warm
(:user-fg "#d8a657" :user-bg "#1e1e1e" :user-border "#d8a657"
:agent-header "#c8a070" :agent-fg "#e0c8a8"
:system "#808080"
:input-prompt "#d8a657" :input-fg "#e0c8a8"
:hint "#606060"
:status-bg "#141414" :status-fg "#c8a070"
:bg "#0a0a0a" :bg-panel "#141414" :bg-element "#1e1e1e"
:text-muted "#808080"
:dot-connected "#7ab85c" :dot-disconnected "#d94a3a"
:error "#d94a3a"
:tool-running "#d8a657" :tool-done "#7ab85c" :tool-error "#d94a3a"
:separator "#3c3c3c" :accent "#d8a657" :dim "#606060")
:light-amber
(:user-fg "#cc6600" :user-bg "#f5f5f5" :user-border "#cc6600"
:agent-header "#8b6914" :agent-fg "#3a2a1a"
:system "#808080"
:input-prompt "#cc6600" :input-fg "#3a2a1a"
:hint "#a0a0a0"
:status-bg "#ebebeb" :status-fg "#3a2a1a"
:bg "#ffffff" :bg-panel "#f5f5f5" :bg-element "#ebebeb"
:text-muted "#808080"
:dot-connected "#2e8b57" :dot-disconnected "#cc3300"
:error "#cc3300"
:tool-running "#cc6600" :tool-done "#2e8b57" :tool-error "#cc3300"
:separator "#d4d4d4" :accent "#cc6600" :dim "#a0a0a0")
:catppuccin
(:user-fg "#fab387" :user-bg "#1e1e2e" :user-border "#fab387"
:agent-header "#cba6f7" :agent-fg "#cdd6f4"
:system "#808080"
:input-prompt "#fab387" :input-fg "#cdd6f4"
:hint "#6c7086"
:status-bg "#181825" :status-fg "#a6adc8"
:bg "#11111b" :bg-panel "#181825" :bg-element "#1e1e2e"
:text-muted "#6c7086"
:dot-connected "#a6e3a1" :dot-disconnected "#f38ba8"
:error "#f38ba8"
:tool-running "#fab387" :tool-done "#a6e3a1" :tool-error "#f38ba8"
:separator "#313244" :accent "#fab387" :dim "#585b70")
:tokyonight
(:user-fg "#ff9e64" :user-bg "#1a1b26" :user-border "#ff9e64"
:agent-header "#7aa2f7" :agent-fg "#a9b1d6"
:system "#808080"
:input-prompt "#ff9e64" :input-fg "#a9b1d6"
:hint "#565f89"
:status-bg "#16161e" :status-fg "#9aa5ce"
:bg "#0f0f18" :bg-panel "#16161e" :bg-element "#1a1b26"
:text-muted "#565f89"
:dot-connected "#9ece6a" :dot-disconnected "#db4b4b"
:error "#db4b4b"
:tool-running "#ff9e64" :tool-done "#9ece6a" :tool-error "#db4b4b"
:separator "#292e42" :accent "#ff9e64" :dim "#444b6a")
:dracula
(:user-fg "#ff9580" :user-bg "#1e1f2b" :user-border "#ff9580"
:agent-header "#bd93f9" :agent-fg "#f8f8f2"
:system "#808080"
:input-prompt "#ff9580" :input-fg "#f8f8f2"
:hint "#6272a4"
:status-bg "#191a24" :status-fg "#e0e0e0"
:bg "#0f101a" :bg-panel "#191a24" :bg-element "#1e1f2b"
:text-muted "#6272a4"
:dot-connected "#50fa7b" :dot-disconnected "#ff5555"
:error "#ff5555"
:tool-running "#ff9580" :tool-done "#50fa7b" :tool-error "#ff5555"
:separator "#34354a" :accent "#ff9580" :dim "#5a5b7a")
:gemini
(:user-fg "#87afff" :user-bg "#1a1a1a" :user-border "#87afff"
:agent-header "#d7afff" :agent-fg "#ffffff"
:system "#808080"
:input-prompt "#87afff" :input-fg "#ffffff"
:hint "#606060"
:status-bg "#141414" :status-fg "#afafaf"
:bg "#000000" :bg-panel "#141414" :bg-element "#1a1a1a"
:text-muted "#808080"
:dot-connected "#d7ffd7" :dot-disconnected "#ff87af"
:error "#ff87af"
:tool-running "#87afff" :tool-done "#d7ffd7" :tool-error "#ff87af"
:separator "#3a3a3a" :accent "#87afff" :dim "#5f5f5f")
:mono
(:user-fg "#e0e0e0" :user-bg "#1a1a1a" :user-border "#808080"
:agent-header "#c0c0c0" :agent-fg "#d0d0d0"
:system "#808080"
:input-prompt "#ffffff" :input-fg "#d0d0d0"
:hint "#606060"
:status-bg "#141414" :status-fg "#b0b0b0"
:bg "#0a0a0a" :bg-panel "#141414" :bg-element "#1a1a1a"
:text-muted "#808080"
:dot-connected "#a0a0a0" :dot-disconnected "#808080"
:error "#808080"
:tool-running "#e0e0e0" :tool-done "#a0a0a0" :tool-error "#808080"
:separator "#303030" :accent "#ffffff" :dim "#505050"))
"13 theme presets (amber, gold, terracotta, sepia, nord-warm,
monokai-warm, gruvbox-warm, light-amber, catppuccin, tokyonight, dracula,
gemini, mono).")
gemini, mono). Now with dark-neutral backgrounds and new :bg/:bg-panel/:bg-element/:text-muted slots.")
(defvar *tui-theme-current-name* :amber
"Name of the currently active theme preset.")
@@ -239,8 +284,8 @@ gemini, mono).")
:collapsed-gates nil ; v0.7.2
:search-mode nil :search-query "" ; v0.7.2
:search-matches nil :search-match-idx 0
:sidebar-visible nil ; v0.8.0
:sidebar-width 30 ; v0.8.0
:sidebar-mode :auto ; v0.8.0: :auto/:visible/:hidden
:sidebar-width 42 ; v0.8.0
:expand-tool-calls nil ; v0.8.0
:mcp-count 0 ; v0.8.0
:kill-ring nil ; v0.9.0