v0.10.1: architectural cleanup — full-frame redraw, explicit bg everywhere, :bg-input fallback

- redraw: always draws all three views (status/chat/input) when any
  dirty flag is set. Dirty flags only gate frame rendering, not
  which parts render. Fixes disappearing input/history.
- Added :bg-input to all 13 presets with #2e2e2e (dark) / #d4d4d4
  (light-amber). theme-load fills missing keys from current preset
  defaults for backward compatibility.
- Removed unused *sidebar-panels* defvar and obsolete contract docs.
- Renamed dim-bg → dim-fg (foreground color, not background).
- All draw-text calls in sidebar and dialog minibuffer now pass
  explicit bg-panel, preventing background leaks.
- render-styled (markdown renderer) passes explicit (theme-color :bg).
- Fix h shadowing in view-chat scroll loop (h → mh).
This commit is contained in:
2026-05-16 09:03:59 -04:00
parent 0a0478f502
commit 2189745f40
3 changed files with 112 additions and 114 deletions

View File

@@ -42,13 +42,14 @@ All state mutation flows through event handlers in the controller.
:bg "#0a0a0a" :bg-panel "#141414" :bg-element "#1e1e1e"
:text-muted "#808080"
:dot-connected "#7fd88f" :dot-disconnected "#e06c75"
:bg-input "#2e2e2e"
: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-*,
:hint, :status-bg/fg, :bg-input, :dot-connected/disconnected, :error, :tool-*,
:separator, :accent, :dim.")
(defvar *tui-theme-presets*
@@ -60,6 +61,7 @@ semantic text colors for context. Keys: :bg (deepest), :bg-panel, :bg-element,
:hint "#606060"
:status-bg "#141414" :status-fg "#e8e8e8"
:bg "#0a0a0a" :bg-panel "#141414" :bg-element "#1e1e1e"
:bg-input "#2e2e2e"
:text-muted "#808080"
:dot-connected "#7fd88f" :dot-disconnected "#e06c75"
:error "#e06c75"
@@ -73,6 +75,7 @@ semantic text colors for context. Keys: :bg (deepest), :bg-panel, :bg-element,
:hint "#606060"
:status-bg "#141414" :status-fg "#ffd700"
:bg "#0a0a0a" :bg-panel "#141414" :bg-element "#1e1e1e"
:bg-input "#2e2e2e"
:text-muted "#808080"
:dot-connected "#7fd88f" :dot-disconnected "#e06c75"
:error "#e06c75"
@@ -86,6 +89,7 @@ semantic text colors for context. Keys: :bg (deepest), :bg-panel, :bg-element,
:hint "#606060"
:status-bg "#141414" :status-fg "#d4956a"
:bg "#0a0a0a" :bg-panel "#141414" :bg-element "#1e1e1e"
:bg-input "#2e2e2e"
:text-muted "#808080"
:dot-connected "#6cb85c" :dot-disconnected "#d94a3a"
:error "#d94a3a"
@@ -99,6 +103,7 @@ semantic text colors for context. Keys: :bg (deepest), :bg-panel, :bg-element,
:hint "#606060"
:status-bg "#141414" :status-fg "#b89870"
:bg "#0a0a0a" :bg-panel "#141414" :bg-element "#1e1e1e"
:bg-input "#2e2e2e"
:text-muted "#808080"
:dot-connected "#7aac5c" :dot-disconnected "#c84a3a"
:error "#c84a3a"
@@ -112,6 +117,7 @@ semantic text colors for context. Keys: :bg (deepest), :bg-panel, :bg-element,
:hint "#606060"
:status-bg "#141414" :status-fg "#c8a080"
:bg "#0a0a0a" :bg-panel "#141414" :bg-element "#1e1e1e"
:bg-input "#2e2e2e"
:text-muted "#808080"
:dot-connected "#7cb860" :dot-disconnected "#d06050"
:error "#d06050"
@@ -125,6 +131,7 @@ semantic text colors for context. Keys: :bg (deepest), :bg-panel, :bg-element,
:hint "#606060"
:status-bg "#141414" :status-fg "#cc9966"
:bg "#0a0a0a" :bg-panel "#141414" :bg-element "#1e1e1e"
:bg-input "#2e2e2e"
:text-muted "#808080"
:dot-connected "#7ab85c" :dot-disconnected "#d94a3a"
:error "#d94a3a"
@@ -138,6 +145,7 @@ semantic text colors for context. Keys: :bg (deepest), :bg-panel, :bg-element,
:hint "#606060"
:status-bg "#141414" :status-fg "#c8a070"
:bg "#0a0a0a" :bg-panel "#141414" :bg-element "#1e1e1e"
:bg-input "#2e2e2e"
:text-muted "#808080"
:dot-connected "#7ab85c" :dot-disconnected "#d94a3a"
:error "#d94a3a"
@@ -150,7 +158,8 @@ semantic text colors for context. Keys: :bg (deepest), :bg-panel, :bg-element,
:input-prompt "#cc6600" :input-fg "#3a2a1a"
:hint "#a0a0a0"
:status-bg "#ebebeb" :status-fg "#3a2a1a"
:bg "#ffffff" :bg-panel "#f5f5f5" :bg-element "#ebebeb"
:bg "#ffffff" :bg-panel "#f5f5f5" :bg-element "#ebebeb"
:bg-input "#d4d4d4"
:text-muted "#808080"
:dot-connected "#2e8b57" :dot-disconnected "#cc3300"
:error "#cc3300"
@@ -163,7 +172,8 @@ semantic text colors for context. Keys: :bg (deepest), :bg-panel, :bg-element,
:input-prompt "#fab387" :input-fg "#cdd6f4"
:hint "#6c7086"
:status-bg "#181825" :status-fg "#a6adc8"
:bg "#11111b" :bg-panel "#181825" :bg-element "#1e1e2e"
:bg "#11111b" :bg-panel "#181825" :bg-element "#1e1e2e"
:bg-input "#2e2e2e"
:text-muted "#6c7086"
:dot-connected "#a6e3a1" :dot-disconnected "#f38ba8"
:error "#f38ba8"
@@ -176,7 +186,8 @@ semantic text colors for context. Keys: :bg (deepest), :bg-panel, :bg-element,
:input-prompt "#ff9e64" :input-fg "#a9b1d6"
:hint "#565f89"
:status-bg "#16161e" :status-fg "#9aa5ce"
:bg "#0f0f18" :bg-panel "#16161e" :bg-element "#1a1b26"
:bg "#0f0f18" :bg-panel "#16161e" :bg-element "#1a1b26"
:bg-input "#2e2e2e"
:text-muted "#565f89"
:dot-connected "#9ece6a" :dot-disconnected "#db4b4b"
:error "#db4b4b"
@@ -189,7 +200,8 @@ semantic text colors for context. Keys: :bg (deepest), :bg-panel, :bg-element,
:input-prompt "#ff9580" :input-fg "#f8f8f2"
:hint "#6272a4"
:status-bg "#191a24" :status-fg "#e0e0e0"
:bg "#0f101a" :bg-panel "#191a24" :bg-element "#1e1f2b"
:bg "#0f101a" :bg-panel "#191a24" :bg-element "#1e1f2b"
:bg-input "#2e2e2e"
:text-muted "#6272a4"
:dot-connected "#50fa7b" :dot-disconnected "#ff5555"
:error "#ff5555"
@@ -202,7 +214,8 @@ semantic text colors for context. Keys: :bg (deepest), :bg-panel, :bg-element,
:input-prompt "#87afff" :input-fg "#ffffff"
:hint "#606060"
:status-bg "#141414" :status-fg "#afafaf"
:bg "#000000" :bg-panel "#141414" :bg-element "#1a1a1a"
:bg "#000000" :bg-panel "#141414" :bg-element "#1a1a1a"
:bg-input "#2e2e2e"
:text-muted "#808080"
:dot-connected "#d7ffd7" :dot-disconnected "#ff87af"
:error "#ff87af"
@@ -215,7 +228,8 @@ semantic text colors for context. Keys: :bg (deepest), :bg-panel, :bg-element,
:input-prompt "#ffffff" :input-fg "#d0d0d0"
:hint "#606060"
:status-bg "#141414" :status-fg "#b0b0b0"
:bg "#0a0a0a" :bg-panel "#141414" :bg-element "#1a1a1a"
:bg "#0a0a0a" :bg-panel "#141414" :bg-element "#1a1a1a"
:bg-input "#2e2e2e"
:text-muted "#808080"
:dot-connected "#a0a0a0" :dot-disconnected "#808080"
:error "#808080"
@@ -223,7 +237,7 @@ semantic text colors for context. Keys: :bg (deepest), :bg-panel, :bg-element,
: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). Now with dark-neutral backgrounds and new :bg/:bg-panel/:bg-element/:text-muted slots.")
gemini, mono). Keys: :bg/:bg-panel/:bg-element/:bg-input/:text-muted.")
(defvar *tui-theme-current-name* :amber
"Name of the currently active theme preset.")
@@ -240,11 +254,19 @@ gemini, mono). Now with dark-neutral backgrounds and new :bg/:bg-panel/:bg-eleme
t))
(defun theme-load ()
"Load persisted theme from disk. Called at startup."
"Load persisted theme from disk. Called at startup.
Adds any missing keys with defaults to handle saved themes from older versions."
(let ((path (merge-pathnames ".cache/passepartout/theme.lisp"
(user-homedir-pathname))))
(when (uiop:file-exists-p path)
(ignore-errors (load path)))))
(ignore-errors (load path)))
;; Fill in any missing keys from the default preset
(let ((defaults (getf *tui-theme-presets* *tui-theme-current-name*)))
(when defaults
(dolist (key '(:bg-input :bg-element :text-muted))
(unless (getf *tui-theme* key)
(let ((val (getf defaults key)))
(when val (setf (getf *tui-theme* key) val)))))))))
(defun theme-switch (name)
"Switch to a named theme preset. Returns the preset name or nil if not found."
@@ -298,18 +320,6 @@ gemini, mono). Now with dark-neutral backgrounds and new :bg/:bg-panel/:bg-eleme
:dirty (list nil nil nil))))
#+END_SRC
** Sidebar panel definitions
#+BEGIN_SRC lisp :tangle /home/user/.local/share/passepartout/lisp/channel-tui-state.lisp
(defvar *sidebar-panels*
'((:id :gate-trace :title "Gate Trace" :width 28)
(:id :focus :title "Focus" :width 28)
(:id :rules :title "Rules" :width 28)
(:id :context :title "Context" :width 28)
(:id :cost :title "Cost" :width 28)
(:id :files :title "Files" :width 28))
"Sidebar panel definitions for cl-tty slot registrations.")
#+END_SRC
** Helpers
#+BEGIN_SRC lisp :tangle /home/user/.local/share/passepartout/lisp/channel-tui-state.lisp
(defun now ()