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:
@@ -789,7 +789,11 @@ Returns T on success, nil on failure. Does NOT wait or retry."
|
||||
(:ctrl+p (lambda (e) (declare (ignore e))
|
||||
(unified-menu-show)))
|
||||
(:ctrl+b (lambda (e) (declare (ignore e))
|
||||
(setf (st :sidebar-visible) (not (st :sidebar-visible)))
|
||||
(setf (st :sidebar-mode)
|
||||
(case (st :sidebar-mode)
|
||||
(:auto :visible)
|
||||
(:visible :hidden)
|
||||
(:hidden :auto)))
|
||||
(setf (st :dirty) (list t t nil))))
|
||||
(:ppage (lambda (e) (declare (ignore e))
|
||||
(let ((max-offset (max 0 (- (length (st :messages)) 1))))
|
||||
@@ -929,7 +933,11 @@ Returns T on success, nil on failure. Does NOT wait or retry."
|
||||
(case ch
|
||||
(:CTRL-Q (setf (st :running) nil))
|
||||
(:CTRL-P (unified-menu-show))
|
||||
(:CTRL-B (setf (st :sidebar-visible) (not (st :sidebar-visible)))
|
||||
(:CTRL-B (setf (st :sidebar-mode)
|
||||
(case (st :sidebar-mode)
|
||||
(:auto :visible)
|
||||
(:visible :hidden)
|
||||
(:hidden :auto)))
|
||||
(setf (st :dirty) (list t t t)))
|
||||
(:CTRL-L (setf (st :dirty) (list t t t)))
|
||||
(t (if (st :dialog-stack)
|
||||
@@ -1010,70 +1018,62 @@ Returns T on success, nil on failure. Does NOT wait or retry."
|
||||
h (or (and (numberp h) (> h 0) h) 24))
|
||||
(when (and (or (first (st :dirty)) (second (st :dirty)) (third (st :dirty)))
|
||||
(null (st :dialog-stack)))
|
||||
(let* ((sidebar-w (if (and (st :sidebar-visible) (>= w 60))
|
||||
(or (st :sidebar-width) 30) 0))
|
||||
(chat-w (- w sidebar-w)))
|
||||
(cl-tty.backend:begin-sync be)
|
||||
(cl-tty.backend:draw-rect be 0 0 w h :bg (theme-color :status-bg))
|
||||
(view-status be w h)
|
||||
(view-chat be w h)
|
||||
;; Draw separator line above input
|
||||
(cl-tty.backend:draw-text be 0 (- h 4) (make-string chat-w :initial-element #\─)
|
||||
(theme-color :separator) nil)
|
||||
(view-input be w h)
|
||||
(when (and (st :sidebar-visible) (>= w 60))
|
||||
(view-sidebar be w h))
|
||||
(cl-tty.backend:end-sync be)
|
||||
(setf (st :dirty) (list nil nil nil))))
|
||||
(cl-tty.backend:begin-sync be)
|
||||
(cl-tty.backend:draw-rect be 0 0 w h :bg (theme-color :bg))
|
||||
(view-status be w h)
|
||||
(view-chat be w h)
|
||||
(view-input be w h)
|
||||
(when (sidebar-visible-p w)
|
||||
(view-sidebar be w h))
|
||||
(cl-tty.backend:end-sync be)
|
||||
(setf (st :dirty) (list nil nil nil)))
|
||||
(let ((ds (st :dialog-stack)))
|
||||
(when ds
|
||||
(cl-tty.backend:begin-sync be)
|
||||
(let* ((sidebar-w (if (and (st :sidebar-visible) (>= w 60))
|
||||
(or (st :sidebar-width) 30) 0))
|
||||
(chat-w (- w sidebar-w))
|
||||
(dlg (car ds))
|
||||
(sel (cl-tty.dialog:dialog-content dlg))
|
||||
(filtered (cl-tty.select:select-filtered-options sel))
|
||||
(sel-idx (cl-tty.select:select-selected-index sel))
|
||||
(cnt (length filtered))
|
||||
(filter (cl-tty.select:select-filter sel))
|
||||
(mh (min 15 (+ 1 cnt))) ;; +1 for title
|
||||
(top (max 0 (- h 4 mh))))
|
||||
;; Clear the minibuffer area
|
||||
(dotimes (r (min (- h 3 top) h))
|
||||
(cl-tty.backend:draw-rect be 0 (+ top r) chat-w 1
|
||||
:bg (theme-color :status-bg)))
|
||||
;; Top border line with title
|
||||
(cl-tty.backend:draw-text be 0 top
|
||||
(make-string chat-w :initial-element #\─)
|
||||
(theme-color :separator) nil)
|
||||
(cl-tty.backend:draw-text be 1 top
|
||||
(cl-tty.dialog:dialog-title dlg)
|
||||
(theme-color :accent) nil)
|
||||
;; Options
|
||||
(let ((y-off 1))
|
||||
(dolist (item filtered)
|
||||
(let* ((display-idx (first item))
|
||||
(option (third item))
|
||||
(title (getf option :title))
|
||||
(cat (getf option :category))
|
||||
(sel-p (eql display-idx sel-idx))
|
||||
(text (if cat (format nil " ~a" title)
|
||||
(format nil " ~:[ ~;▸~] ~a" sel-p title)))
|
||||
(row (+ top y-off)))
|
||||
(when (>= row (1- h)) (return))
|
||||
(cl-tty.backend:draw-text be 1 row text
|
||||
(cond (cat (theme-color :dim))
|
||||
(sel-p (theme-color :accent))
|
||||
(t (theme-color :agent-fg)))
|
||||
nil :bold sel-p)
|
||||
(incf y-off))))
|
||||
;; Filter prompt at h-3
|
||||
(cl-tty.backend:draw-rect be 0 (- h 3) chat-w 1
|
||||
:bg (theme-color :status-bg))
|
||||
(cl-tty.backend:draw-text be 0 (- h 3)
|
||||
(format nil "> ~a" (or filter ""))
|
||||
(theme-color :input-prompt) nil))
|
||||
(cl-tty.backend:begin-sync be)
|
||||
(let* ((chat-w (- w (if (sidebar-visible-p w) (or (st :sidebar-width) 42) 0)))
|
||||
(dlg (car ds))
|
||||
(sel (cl-tty.dialog:dialog-content dlg))
|
||||
(filtered (cl-tty.select:select-filtered-options sel))
|
||||
(sel-idx (cl-tty.select:select-selected-index sel))
|
||||
(cnt (length filtered))
|
||||
(filter (cl-tty.select:select-filter sel))
|
||||
(mh (min 15 (+ 1 cnt)))
|
||||
(top (max 0 (- h 4 mh)))
|
||||
(bg-p (theme-color :bg-panel))
|
||||
(sep-c (theme-color :separator)))
|
||||
;; Fill minibuffer area with panel bg
|
||||
(dotimes (r (min (- h 3 top) h))
|
||||
(cl-tty.backend:draw-rect be 0 (+ top r) chat-w 1 :bg bg-p))
|
||||
;; Top separator
|
||||
(cl-tty.backend:draw-text be 0 top
|
||||
(make-string chat-w :initial-element #\─)
|
||||
sep-c nil)
|
||||
(cl-tty.backend:draw-text be 1 top
|
||||
(cl-tty.dialog:dialog-title dlg)
|
||||
(theme-color :accent) nil)
|
||||
;; Options
|
||||
(let ((y-off 1))
|
||||
(dolist (item filtered)
|
||||
(let* ((display-idx (first item))
|
||||
(option (third item))
|
||||
(title (getf option :title))
|
||||
(cat (getf option :category))
|
||||
(sel-p (eql display-idx sel-idx))
|
||||
(text (if cat (format nil " ~a" title)
|
||||
(format nil " ~a~a" (if sel-p "▸ " " ") title)))
|
||||
(row (+ top y-off)))
|
||||
(when (>= row (1- h)) (return))
|
||||
(cl-tty.backend:draw-text be 1 row text
|
||||
(cond (cat (theme-color :text-muted))
|
||||
(sel-p (theme-color :accent))
|
||||
(t (theme-color :agent-fg)))
|
||||
nil :bold sel-p)
|
||||
(incf y-off))))
|
||||
;; Filter prompt
|
||||
(cl-tty.backend:draw-rect be 0 (- h 3) chat-w 1 :bg bg-p)
|
||||
(cl-tty.backend:draw-text be 0 (- h 3)
|
||||
(format nil "> ~a" (or filter ""))
|
||||
(theme-color :input-prompt) nil))
|
||||
(cl-tty.backend:end-sync be))
|
||||
(sleep 0.1)))
|
||||
(progn (disconnect-daemon)))))
|
||||
@@ -1254,11 +1254,11 @@ Returns T on success, nil on failure. Does NOT wait or retry."
|
||||
(fiveam:is (eq nil (st :busy))))
|
||||
|
||||
(fiveam:test test-theme
|
||||
"Contract view: *tui-theme* provides warm color mappings."
|
||||
(fiveam:is (string= "#FFB347" (getf *tui-theme* :user-fg)))
|
||||
(fiveam:is (string= "#E8D5B7" (getf *tui-theme* :agent-fg)))
|
||||
(fiveam:is (string= "#C8A87C" (getf *tui-theme* :system)))
|
||||
(fiveam:is (string= "#E8D5B7" (getf *tui-theme* :input-fg)))
|
||||
"Contract view: *tui-theme* provides color mappings."
|
||||
(fiveam:is (string= "#fab283" (getf *tui-theme* :user-fg)))
|
||||
(fiveam:is (string= "#e8e8e8" (getf *tui-theme* :agent-fg)))
|
||||
(fiveam:is (string= "#808080" (getf *tui-theme* :system)))
|
||||
(fiveam:is (string= "#e8e8e8" (getf *tui-theme* :input-fg)))
|
||||
(fiveam:is (string= "#FFFFFF" (theme-color :unknown-role))))
|
||||
|
||||
(fiveam:test test-on-key-ctrl-u-clears
|
||||
|
||||
Reference in New Issue
Block a user