Commit Graph

116 Commits

Author SHA1 Message Date
1637c3352c fix: read-raw-byte checks poll result before unix-read
The original code called unix-simple-poll then unconditionally
called unix-read, ignoring the poll result. When poll returned
nil (no data), unix-read would block indefinitely. Fixed by
checking poll result: only read if poll says data is ready.
2026-05-14 08:53:16 -04:00
07cea571ef fix: add backend-clear method for raw 2D arrays
Same pattern as the draw-text array fix. Application code may call
backend-clear with a framebuffer array instead of a backend instance.
The array method clears all cells to default blank state.
2026-05-13 16:29:50 -04:00
3bc6df6fd0 fix: read-raw-byte alien type mismatch and timeout ms conversion
- Replace make-alien unsigned-char buffer with make-array + vector-sap
  to avoid SBCL alien type mismatch between signed-char and unsigned-char
- Convert timeout seconds to fixnum milliseconds for unix-simple-poll
  (was passing float 0.1, broke on fixnum-typed sb-unix:to-msec)
- Both fixes make read-raw-byte work on SBCL 2.5.2.debian
2026-05-13 16:15:09 -04:00
22886c1794 fix: add draw-text method for raw 2D arrays
Application code (passepartout TUI) calls draw-text with a framebuffer
(2D array) as the first argument, but draw-text only had methods for
framebuffer-backend CLOS instances. Added a method on array that sets
cells directly on the framebuffer array, matching make-framebuffer's
return type.
2026-05-13 16:06:05 -04:00
66e86734cb literate: add with-terminal, suspend-backend, resume-backend to org source
with-terminal macro was only in tangled .lisp (not .org). suspend-backend
and resume-backend generics + simple-backend methods + tests were also
in hand-edited .lisp only. All three added to org/backend-protocol.org
with proper prose, following the literate programming discipline.

Also added suspend/resume assertions to simple-backend-lifecycle test suite.
2026-05-13 13:14:24 -04:00
c30917056c Merge pull request 'v1.1.0: SGR Mouse Event Parsing' (#9) from feature/v0.11.0-slots into main
Reviewed-on: http://10.10.10.201:3001/amr/cl-tty/pulls/9
2026-05-12 18:43:20 -04:00
Hermes Agent
d4aba6ef06 docs: add v1.1.0 SGR mouse parsing to ROADMAP.org 2026-05-12 22:22:06 +00:00
Hermes Agent
b3b191529a feat: SGR mouse event parsing in read-event
- Add %read-digits to read multi-digit parameters from raw terminal bytes
- Add %parse-sgr-mouse to decode ESC[<Cb;Cx;CyM/m SGR mouse sequences
  into mouse-event structs with :press/:release type and :left/:middle/
  :right/:scroll-up/:scroll-down/:drag button classification
- Modified parse-csi-sequence to detect the < marker (0x3C) and
  delegate to %parse-sgr-mouse instead of treating it as key input
- Coordinates converted from 1-based (terminal protocol) to 0-based
  (framebuffer convention)
- All 12 test suites pass at 100% (461 checks, no regressions)
- Org source (text-input.org) updated as the source of truth
v1.1.0
2026-05-12 22:14:03 +00:00
07c29290d4 Merge pull request 'v1.0.0 — Stable release + TUI support' (#8) from feature/v0.11.0-slots into main
Reviewed-on: http://10.10.10.201:3001/amr/cl-tty/pulls/8
2026-05-12 16:34:48 -04:00
Hermes Agent
38ee561625 v1.0.0: TUI support — resize events, with-terminal macro v1.0.0 2026-05-12 20:32:37 +00:00
Hermes Agent
84e8482fec v1.0.0: TUI support — resize events, with-terminal macro
- read-event now checks *terminal-resized-p* and returns :resize on SIGWINCH
- Added with-terminal convenience macro (detect → init → body → shutdown)
- Exported *terminal-resized-p* from cl-tty.input package
- Exported with-terminal from cl-tty.backend package
- Updated text-input.org with resize event integration and refactored tests
- Tests: 461 checks, 100% pass (93 input suite, +2 new test cases)
2026-05-12 20:28:55 +00:00
Hermes Agent
3cbcfd2d75 v1.0.0 release
Bug fixes:
- Fix OSC8 format strings (backslash escape layering) in modern-backend.org
  - Test format string had single backslash instead of double, causing
    unclosed CL string that cascaded through 3 subsequent test forms
  - Implementation format string had leading escaped quote (not a string
    opener) and triple-backslash ending (also not a string terminator)
- Fix missing closing parens in border-char-rounded and border-char-double tests
- Fix ASDF input-tests pathname (file lives in tests/, not src/components/)

New features:
- Implement suspend-backend / resume-backend protocol methods
  - modern-backend: exit/enter alt screen, re-enable mouse/kitty/bracketed-paste
  - simple-backend: no-ops (no terminal state to preserve)

Infrastructure:
- Update test suite to cover suspend/resume (backend + modern-backend suites)
- 454 checks, 100% pass across 14 test suites
2026-05-12 20:00:27 +00:00
Hermes Agent
9c879e7a97 fix: validate slot mode on first defslot call
Add assert to reject invalid mode keywords on first registration
instead of silently storing them and only crashing later in
slot-render's ecase. Valid modes: :stack, :replace, :single-winner.
2026-05-12 19:33:18 +00:00
Hermes Agent
352f27e260 fix: osc8-link doubled backslashes in format string
The osc8-link implementation and its test both had doubled
backslashes (\\ -> \\) in their format strings, producing two
literal backslashes at runtime instead of the single backslash
needed for the OSC 8 string terminator (ST = ESC \).

Fix: change \\ to \\ in both the implementation and test format
strings. The tangled .lisp files now have correct escaped
backslashes (\) producing one backslash in the runtime string.

Additionally clean up a patch artifact that left a stray backslash
before the opening quote.
2026-05-12 19:26:00 +00:00
Hermes Agent
6cd045ff59 implement: slot modes (:stack, :replace, :single-winner)
Add :mode parameter to defslot with three behaviors:
- :stack (default) — accumulate all registrations, render in order
- :replace — each registration replaces previous entries
- :single-winner — first registration wins, rest ignored

Mode is set on first defslot call and frozen for subsequent calls
to prevent conflicting mode specifications from different plugins.

Store slot data as plist (:mode <keyword> :entries <list>) instead
of bare entries list.

Add 5 new tests covering mode-specific behavior. All 9 slot tests
pass. All 13 suites pass at 100%.
2026-05-12 19:17:24 +00:00
Hermes Agent
a9670a5cd7 literate: add org sources for orphan test files, update README
- Create org/integration-tests.org (15 blocks, per-test prose)
- Add Markdown tests section to org/markdown-renderer.org (11 test blocks)
- Delete deprecated src/components/input-tests.lisp stub
- Update README.org: tree diagram, literate programming section,
  development commands, remove stale test counts

All 13 test suites pass at 100%. Zero .lisp files without org origin.
2026-05-12 19:01:22 +00:00
Hermes Agent
29f99a576d literate: restructure all 19 org files with per-function blocks and prose
Every function, defclass, defstruct, defgeneric, defmethod, defmacro,
defvar, and defparameter in every org file now has its own #+BEGIN_SRC
block with literate prose above it explaining the design reasoning.

Block counts before → after:
  package.org:           1 → 7
  container-package.org: 1 → 1 (prose expanded)
  dirty.org:             4 → 6
  render.org:           10 → 25
  theme.org:             6 → 19
  box-renderable.org:    9 → 29
  scrollbox.org:         8 → 26
  tabbar.org:            5 → 10
  backend-protocol.org:  8 → 66
  modern-backend.org:   17 → 53
  detection.org:         4 → 6
  layout-engine.org:     9 → 36
  framebuffer.org:       8 → 37
  markdown-renderer.org:13 → 38
  dialog.org:           17 → 23 (merged dual structure)
  mouse.org:             4 → 25
  select.org:           12 → 30
  slot.org:              4 → 12
  text-input.org:       11 → 53

Total: ~153 blocks → ~502 blocks

Bugs fixed during restructuring:
- render.org: stray π character typo (backenπd → backend)
- modern-backend.org: sgr-attr missing closing paren + #+END_SRC
- detection.org: invalid #\Esc character reference
- select.org: extra closing paren in select-visible-options

All 13 test suites pass at 100%.
2026-05-12 18:55:07 +00:00
Hermes Agent
927f786716 remove: old scrollbox-tabbar.org (all prose distributed to per-module orgs)
The combined org file had no unique content — all prose and code were
already in scrollbox.org, tabbar.org, and container-package.org. The
old file's code blocks had the pre-bugfix render/draw-scrollbars
versions and all had :tangle no.

Also update README.org and ARCHITECTURE.org references from
scrollbox-tabbar.org to the individual org files.
2026-05-12 18:08:02 +00:00
Hermes Agent
668966380e prose: split scrollbox-tabbar.org prose into per-module org files
Distribute the literate prose from the old combined scrollbox-tabbar.org
into three individual module org files:

- scrollbox.org: ScrollBox class, render, scrollbars, bug fixes,
  plus the combined test suite (tangles scrollbox-tabbar-tests.lisp)
- tabbar.org: TabBar class, navigation, keyboard handler, render
- container-package.org: Package definition and exports

The old scrollbox-tabbar.org is retained as a documentation archive
with all code blocks set to :tangle no and a redirecting note.

Fixes the draw-scrollbars code block to use the post-bugfix version
(with layout-node origin offset ox/oy), matching the working code.
All 13 test suites pass at 100%.
2026-05-12 18:06:07 +00:00
Hermes Agent
a061d60898 split: scrollbox-tabbar.org into scrollbox.org, tabbar.org, container-package.org
- Create org/scrollbox.org (tangles scrollbox.lisp)
- Create org/tabbar.org (tangles tabbar.lisp)
- Create org/container-package.org (tangles container-package.lisp)
- Disable :tangle in old scrollbox-tabbar.org (kept for prose docs)
- Fix missing paren in render method (was depth=1 at EOF)
- All 483 tests pass, 14 suites, 100%
2026-05-12 18:00:06 +00:00
Hermes Agent
d5caaf296d fix: restore original text-input.lisp in org to fix handle-text-input
The tangled handle-text-input used (key-event-text event) for character
insertion, but the test suite creates key events with :code not :text.
Restored the original handle-text-input which uses
(code-char (key-event-code event)) — matching the test expectations.
2026-05-12 17:52:43 +00:00
Hermes Agent
0fb5309133 literate: convert org/markdown-renderer.org from doc-only to tangle source
Now tangles to markdown.lisp + markdown-package.lisp.
Deleted hand-written originals and regenerated — GREEN.
2026-05-12 17:25:52 +00:00
Hermes Agent
d3bc6c748a literate: convert org/layout-engine.org from doc-only to tangle source
Now tangles to layout.lisp + layout/tests.lisp.
Deleted hand-written originals and regenerated — GREEN.
2026-05-12 17:18:27 +00:00
Hermes Agent
f50d0e61d1 literate: convert org/box-renderable.org from doc-only to tangle source
Now tangles to box.lisp + text.lisp + box-tests.lisp.
Deleted hand-written originals and regenerated — GREEN.
2026-05-12 17:16:26 +00:00
Hermes Agent
c77c6b9d02 literate: convert org/modern-backend.org from doc-only to tangle source
Now tangles to modern.lisp + modern-tests.lisp.
Deleted hand-written originals and regenerated from org — GREEN.
2026-05-12 17:14:37 +00:00
Hermes Agent
dfd828c914 literate: convert org/backend-protocol.org from doc-only to tangle source
Now tangles to: package.lisp, classes.lisp, simple.lisp, tests.lisp
All 4 .lisp files deleted and regenerated from org alone — verified GREEN
2026-05-12 17:08:54 +00:00
Hermes Agent
ce7e9fbab0 literate: create org/render.org, org/theme.org, org/package.org
Follows the literate programming workflow:
  Overview → Contract → Tests → Implement → Tangle → Test (GREEN)

render.org covers render.lisp + render-tests.lisp (component protocol,
render dispatch, dirty propagation)
theme.org covers theme.lisp + theme-tests.lisp (theme class, presets,
color resolution)
package.org covers package.lisp (cl-tty.box defpackage)
2026-05-12 17:05:47 +00:00
Hermes Agent
ba5cb360db literate: create org/dirty.org as proof of literate programming workflow
org/dirty.org is now the source of truth for dirty.lisp and
dirty-tests.lisp. The process:
  Overview → Contract → Tests → Implement → Tangle → Test (GREEN)

Hand-written .lisp files were deleted and regenerated from org alone
to prove the pipeline works.
2026-05-12 17:03:15 +00:00
Hermes Agent
47094c48e5 restructure: move backend/ and layout/ into src/; convert README to org syntax; fix demo package conflict and alien-sap ioctl; update ROADMAP with v0.15.0; remove stale files
- Move backend/ and layout/ directories into src/
- Update all path references in ASD, scripts, docs
- Convert README.org from Markdown syntax to proper Org-mode
- Fix demo.lisp use-package conflict (both backend and input export #:read-event)
- Fix modern-backend TIOCGWINSZ ioctl alien type (alien-sap wrapper)
- Add v0.15.0 section to ROADMAP, update line count to 5760
- Add known gaps (suspend/resume-backend, slot modes) to v1.0.0 checklist
- Remove docs/plans/, debug-layout.lisp, system-index.txt, ci-watchdog.sh
- Move tangle.py to Hermes skill (org-babel-tangle)
- Add .gitignore for fasl files
2026-05-12 16:57:19 +00:00
Hermes Agent
5f07c1fd76 fix: tangle.py write-once-then-append logic (was always-appending, triplicating files); confirm-dialog option plist comparison; mouse-event button type (or keyword null) 2026-05-12 15:51:44 +00:00
Hermes Agent
a812955329 docs: mark v1.0.0 Org/Lisp sync verified — all 483+57+17 checks pass on fresh tangle 2026-05-12 15:42:49 +00:00
Hermes Agent
ca90d6b945 chore: org tangle sync — regenerate .lisp from .org sources (zero functional changes, file sizes identical) 2026-05-12 15:42:40 +00:00
Hermes Agent
60866a80c1 docs: update README tangle instructions to use Python script 2026-05-12 15:22:42 +00:00
Hermes Agent
5930e17b57 fix: org tangle — fix END_SRC boundaries in mouse.org/slot.org (prose inside code blocks), replace emacs tangle with Python script that handles all blocks 2026-05-12 15:22:29 +00:00
Hermes Agent
4bb9160f8d docs: update test counts to 483/13 in README and ROADMAP 2026-05-12 14:42:00 +00:00
Hermes Agent
d5a767350f fix: word-wrap never incremented current-len (all text treated as single line); scrollbox wrong offset origin; integration test fixes 2026-05-12 14:41:16 +00:00
Hermes Agent
00db3c61a5 fix: dialog draw-border arg, markdown/slot nil guards, +integration test suite 2026-05-12 14:30:31 +00:00
Hermes Agent
6e73c3bb19 fix: redundant compute-layout per child, framebuffer diff size test, test file cleanup 2026-05-12 14:19:48 +00:00
Hermes Agent
a153746111 fix: demo arrow keys on Widgets tab move cursor instead of switching tabs; +12 keybinding dispatch tests 2026-05-12 14:12:53 +00:00
Hermes Agent
baa27f766f fix: cursor movement marks dirty in text-input and textarea (regression from cursor rendering fix) 2026-05-12 14:07:17 +00:00
Hermes Agent
b0ede26bff fix: demo uses backend-size instead of hardcoded 80x24 2026-05-12 14:04:51 +00:00
Hermes Agent
b38436038b fix: scrollbar position offset, dialog size clamp to terminal dimensions 2026-05-12 14:03:12 +00:00
Hermes Agent
df5ceabd3b fix: distribute-sizes rounding remainder, render-screen uses backend-size 2026-05-12 14:00:59 +00:00
Hermes Agent
80abb23197 fix: query-terminal stream, enable-mouse/bracketed-paste methods, simple-backend draw-ellipsis position 2026-05-12 13:53:38 +00:00
Hermes Agent
e198e8b5da fix: text-input cursor now rendered as solid block at cursor position 2026-05-12 13:50:55 +00:00
Hermes Agent
26ec1dfbe8 fix: backend-size (TIOCGWINSZ), kitty keyboard enable, Wayland clipboard, SIGWINCH handler 2026-05-12 13:49:23 +00:00
Hermes Agent
bb1717a43d fix: draw-border renders titles in modern and simple backends (title, title-align respected) 2026-05-12 13:46:42 +00:00
Hermes Agent
b21daa99b8 fix: input timeout bugs — read-raw-byte, SS3, parse-csi-params all use sub-second timeouts now (get-internal-real-time replaces get-universal-time which truncated to integer seconds) 2026-05-12 13:42:39 +00:00
Hermes Agent
30fdb1def8 Fix verify-api.py: use correct API names throughout
Previous version had 14 failing checks due to wrong function names:
- Theme: load-preset with :keyword mode, not nonexistent load-default-*-preset
- Select: setf select-filter + select-filtered-options with 1 arg
- Dialog: push-dialog/pop-dialog + dialog-title on car of *dialog-stack*
- Mouse: make-box has no :x/:y initargs, use default constructor
- Framebuffer: draw-text on framebuffer-backend, not draw-text-on-fb
- Dirty: dirty-p, not component-dirty-p
- Theme functions in cl-tty.box package, not cl-tty.rendering

Also add ci-watchdog.sh for 15-min polling CI.
All 29 checks now pass.
2026-05-12 11:41:15 +00:00
Hermes Agent
5213bdeae5 CI test 4: recreated webhook with explicit events 2026-05-12 11:39:13 +00:00