v0.15.0: Critical input/rendering fixes, subagent-reviewed #7
Reference in New Issue
Block a user
Delete Branch "feature/v0.11.0-slots"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
12 commits across ~3 review cycles. Every fix was reviewed by a subagent.
Critical
High
Medium
Other
Running the demo
./demo.sh
Root cause: normalize-box and slot :initforms used quoted literal lists ('(...)) that were destructively modified by (setf (getf ...)). Each call to normalize-box with a non-nil spec corrupted the shared default list, causing all subsequent nodes with no explicit padding to inherit the previous node's padding values. Fix: replace all '(...) quoted literals with (list ...) constructor calls — in normalize-box (3 paths) and in slot initforms for both padding and margin. All 11 test suites now pass: 358/358 checks, 0 failures.CRITICAL: case b → cond in %read-event (input.lisp:280) case with (and ...) predicate clauses treats keys as eql-compared atoms — all range clauses were dead code. Every Ctrl+letter and printable ASCII fell through to :unknown. text-input/textarea widgets were non-functional with real terminal input. No test coverage of %read-event masked this. HIGH: Theme resolution wired (backend/modern.lisp, theme.lisp) sgr-fg/sgr-bg now fall back to *theme-colors* hash for semantic keywords (:accent, :text-muted, :background-element). *theme-colors* exported from cl-tty.backend. load-preset populates it from preset hex values. Previously all themed render output was invisible. HIGH: SGR mouse parser wired (input.lisp:210-215) parse-sgr-mouse was defined but never called. Now %read-escape-sequence detects ESC[< prefix and routes to parse-sgr-mouse. Mouse drags, releases, and scroll events now parse correctly. MEDIUM: Rendering stubs replaced - scrollbox: delegates to (render child backend) with position offset via unwind-protect (was debug string 'child at ~D') - text-input: draws value/placeholder at layout position - textarea: draws visible lines at layout position MEDIUM: hit-test uses component-layout-node (mouse.lisp:18-31) Was checking nonexistent x/y/width/height slots. Now reads layout-node-x/y/w/h via component-layout-node generic. MEDIUM: test runner exit code (run-all-tests.lisp, cl-tty.asd) run-all-tests.lisp exits 1 if any suite fails. asdf:test-system exits 1 on failure. Renamed :cl-tty-tests to :cl-tty/test (ASDF convention). MEDIUM: draw-border respects x/y on simple-backend (simple.lisp:42-53) Was writing to cursor position only. Now uses newlines+spaces to reach specified coordinates (no escape sequences needed). LOW: TabBar truncation off-by-one fixed (tabbar.lisp:47) >= changed to > to avoid cutting tabs 2 chars early. LOW: Scrollbar coordinates absolute (scrollbox.lisp:61-73) Scrollbar drawn at viewport-relative (0,0). Now adds layout node x/y offset for correct terminal positioning. LOW: backend-write calls finish-output (modern.lisp:169) LOW: load-preset no longer flips theme-mode (theme.lisp:43-45) Mode toggle caused load-preset to load wrong variant on second call. All backported to org source files (org/text-input.org, org/scrollbox-tabbar.org) so tangling produces matching .lisp. 392 tests pass, exit code 0.Demo (demo.lisp): - Full interactive demo with 3 tabs: Home, Widgets, Console - Uses read-event/SGR mouse paths (exercises real terminal input) - Demonstrates text-input, textarea, backend drawing, tab navigation - Event log console shows keyboard and mouse events in real time - Proper terminal cleanup via shutdown-backend + unwind-protect README.org: - Complete rewrite with getting-started guide, architecture overview - API reference for all components with signatures and examples - Event loop pattern, layout system, rendering pipeline docs - Backend features table, development guide, project structure Bug fixes: - read-raw-byte (input.lisp:89-109): use sb-sys:with-pinned-objects + vector-sap for proper sb-posix:read buffer handling (SBCL type error with plain (unsigned-byte 8) arrays) - input-package.lisp: export textarea-lines (was missing from package) Version bump: v0.14.0 → v0.15.0 392 tests pass.demo.lisp: - Removed ignore-errors wrapper: run-demo now returns normally, followed by (uiop:quit 0) at top level — fixes exit code always 1 bug - Manual set-raw-mode/unwind-protect/restore-terminal-state instead of with-raw-terminal macro (safer in edge cases) - Graceful fallback when raw mode fails: continues in pipe-safe mode so the demo renders frames even without terminal control - Simplified tab rendering, fixed textarea-lines display The demo runs correctly in both interactive and pipe-safe modes. In a real terminal: raw mode, keyboard/mouse event loop. In pipe-safe mode: spins rendering frames (read-event returns nil). Verified running: frames render correctly with borders, tabs, content, status bar, and event counter.