Rename: cl-tty avoids naming collision with Quicklisp's cl-tui (naryl/cl-tui, a cl-charms-based ncurses library). Our project is pure escape-sequence CL. v0.9.0 adds: - Dialog base class: modal overlay with backdrop, centered panel, size variants (:small/:medium/:large), stack-based management - Dialog subclasses: alert, confirm, select-dialog, prompt-dialog - Toast notifications: transient, top-right corner, auto-dismiss, colored variants (info/success/warning/error) - 78 tests total, 100% passing ASDF: read-time package references (+fiveam:+) replaced with find-symbol so .asd loads without FiveAM pre-loaded
597 lines
22 KiB
Org Mode
597 lines
22 KiB
Org Mode
#+TITLE: cl-tty Roadmap
|
|
#+STARTUP: content
|
|
#+FILETAGS: :docs:roadmap:cl-tty:
|
|
|
|
* The Roadmap
|
|
|
|
Each phase is one minor release. Phases ship in dependency order — each depends on
|
|
the components from prior phases. The backend protocol ships first because
|
|
everything else builds on it.
|
|
|
|
** v0.0.1: Foundation — Backend Protocol
|
|
|
|
The abstraction layer that makes everything portable. Two backends:
|
|
=modern= (raw escape sequences, truecolor, modern features) and =simple=
|
|
(ASCII art, universal compatibility). The component tree never touches
|
|
the terminal directly — it dispatches through the protocol.
|
|
|
|
*** TODO Backend protocol definition
|
|
:PROPERTIES:
|
|
:ID: id-v000-protocol
|
|
:CREATED: [2026-05-10 Sat]
|
|
:END:
|
|
|
|
- Define =backend= abstract class with generic functions:
|
|
- =initialize-backend=, =shutdown-backend=, =suspend-backend=, =resume-backend=
|
|
- =backend-size=, =backend-write=, =backend-clear=
|
|
- =begin-sync=, =end-sync= — DECICM synchronized updates
|
|
- =draw-rect=, =draw-text=, =draw-border=, =draw-ellipsis=, =draw-link=
|
|
- =cursor-move=, =cursor-hide=, =cursor-show=, =cursor-style=
|
|
- =read-event=, =enable-mouse=, =enable-bracketed-paste=, =set-keyboard-mode=
|
|
- =capable-p= — query feature support
|
|
- Style plist structure: ~(:fg :error :bg :background-panel :bold t :italic nil ...)~
|
|
- ~100 lines
|
|
|
|
*** TODO Simple backend
|
|
:PROPERTIES:
|
|
:ID: id-v000-simple
|
|
:CREATED: [2026-05-10 Sat]
|
|
:END:
|
|
|
|
- =simple-backend= class — inherits =backend=
|
|
- Borders: ASCII (~+-|~), no rounded corners
|
|
- No color, no bold/italic — plain characters only
|
|
- No OSC 8 links, no mouse, no synchronized updates
|
|
- Works on any terminal, any SSH connection, piped output
|
|
- ~100 lines
|
|
|
|
*** TODO Modern backend
|
|
:PROPERTIES:
|
|
:ID: id-v000-modern
|
|
:CREATED: [2026-05-10 Sat]
|
|
:END:
|
|
|
|
- =modern-backend= class — inherits =backend=
|
|
- Truecolor 24-bit foreground/background
|
|
- Rounded, single, double border styles via Unicode box-drawing
|
|
- OSC 8 hyperlinks (clickable URLs)
|
|
- DECICM synchronized updates (flicker-free)
|
|
- SGR mouse tracking + kitty keyboard protocol
|
|
- Bracketed paste detection
|
|
- Bold, italic, underline, dim, blink, reverse, strikethrough
|
|
- Cursor style: =:bar=, =:block=, =:underline=, with blink option
|
|
- ~250 lines
|
|
|
|
*** TODO Terminal capability detection
|
|
:PROPERTIES:
|
|
:ID: id-v000-detection
|
|
:CREATED: [2026-05-10 Sat]
|
|
:END:
|
|
|
|
- =detect-backend= → returns =modern-backend= or =simple-backend=
|
|
- Check if stdout is a TTY (if not → =simple-backend=)
|
|
- Send DA1 (~ESC[c~) query, 100ms timeout
|
|
- Send DA3 (~ESC[?c~) for kitty/wezterm identification
|
|
- Query DECRPM (~ESC[?2026$p~) for DECICM sync support
|
|
- Query truecolor support via =COLORTERM= env var + DA response
|
|
- Cache detection result so subsequent calls are instant
|
|
- ~100 lines
|
|
|
|
~550 lines total. Dependencies: None (pure CL, no FFI, no external libs).
|
|
|
|
** v0.0.2: Layout Engine
|
|
the patch version (v0.X.Y).
|
|
|
|
** File Update Checklist
|
|
|
|
When a version ships:
|
|
1. ~ROADMAP.org~ — mark item DONE, update LOGBOOK timestamp
|
|
2. ~README.org~ — update Status line
|
|
3. ~cl-tty.asd~ — update version string
|
|
|
|
** v0.1.0: Layout Engine
|
|
|
|
Yoga Flexbox backend wrapped in a Common Lisp API. This is the foundation —
|
|
every component after v0.1.0 uses the layout engine for positioning.
|
|
|
|
*** TODO Yoga FFI binding
|
|
:PROPERTIES:
|
|
:ID: id-v010-yoga-ffi
|
|
:CREATED: [2026-05-10 Sat]
|
|
:END:
|
|
|
|
- Load the Yoga shared library via CFFI
|
|
- Define foreign types for ~YGNodeRef~, ~YGSize~, ~YGValue~, ~YGDirection~, ~YGFlexDirection~, ~YGAlign~, ~YGJustify~, ~YGWrap~, ~YGPositionType~, ~YGOverflow~, ~YGDisplay~, ~YGEdge~
|
|
- Bind core functions: ~node-new~, ~node-free~, ~node-style-set-*~, ~node-layout-get-*~, ~calculate-layout~
|
|
- ~100 lines CFFI
|
|
|
|
*** TODO Layout primitives
|
|
:PROPERTIES:
|
|
:ID: id-v010-layout-primitives
|
|
:CREATED: [2026-05-10 Sat]
|
|
:END:
|
|
|
|
- ~(make-layout-node)~ — wraps a ~YGNodeRef~ in a CLOS object
|
|
- ~(layout-node-set-dimension node width height)~ — sets width/height in points
|
|
- ~(layout-node-set-flex node &key grow shrink basis)~ — flex properties
|
|
- ~(layout-node-set-direction node :row | :column | :row-reverse | :column-reverse)~
|
|
- ~(layout-node-set-wrap node :nowrap | :wrap | :wrap-reverse)~
|
|
- ~(layout-node-set-align node :flex-start | :center | :flex-end | :stretch | :baseline)~
|
|
- ~(layout-node-set-justify node :flex-start | :center | :flex-end | :space-between | :space-around | :space-evenly)~
|
|
- ~(layout-node-set-padding node &key top right bottom left x y)~
|
|
- ~(layout-node-set-margin node &key top right bottom left x y)~
|
|
- ~(layout-node-set-gap node &key row column)~
|
|
- ~(layout-node-set-position node :relative | :absolute &key top right bottom left)~
|
|
- ~(layout-node-set-border node width)~
|
|
- ~(layout-node-add-child parent child)~ — builds the tree
|
|
- ~(layout-calculate root width height)~ — runs Yoga's calculateLayout, populates each node's computed x/y/w/h
|
|
- ~200 lines CL
|
|
|
|
*** TODO Layout composable API
|
|
:PROPERTIES:
|
|
:ID: id-v010-layout-composable
|
|
:CREATED: [2026-05-10 Sat]
|
|
:END:
|
|
|
|
Convenience macros to build layout trees from CL function calls:
|
|
|
|
- ~(vbox &key ... children ...)~ → column-direction container with children
|
|
- ~(hbox &key ... children ...)~ → row-direction container with children
|
|
- ~(overlay base child)~ — absolute-positioned overlay over a relative base
|
|
- ~(spacer &key grow)~ — empty flex spacer
|
|
- ~(layout-render root parent-window)~ — computes layout then walks the tree, calling each child's render function with its computed x, y, w, h
|
|
- ~50 lines CL macros
|
|
|
|
~350 lines total. Dependencies: Yoga shared library, CFFI, croatoan.
|
|
|
|
*** FiveAM tests
|
|
- ~test-layout-basic~ — vbox with two children computes correct y positions
|
|
- ~test-layout-hbox~ — hbox with two children computes correct x positions
|
|
- ~test-layout-flex~ — flex-grow distributes space correctly
|
|
- ~test-layout-absolute~ — absolute child positions relative to parent
|
|
- ~test-layout-nested~ — nested vbox/hbox produces correct leaf positions
|
|
|
|
** v0.2.0: Renderables — Box and Text
|
|
|
|
The first two renderable types that every application uses. A Box draws borders
|
|
and backgrounds. A Text renders strings with color and style. Together they
|
|
cover 80% of terminal UI.
|
|
|
|
*** DONE Box renderable
|
|
:PROPERTIES:
|
|
:ID: id-v020-box
|
|
:CREATED: [2026-05-10 Sat]
|
|
:END:
|
|
:LOGBOOK:
|
|
- State \"DONE\" from \"TODO\" [2026-05-11 Mon]
|
|
:END:
|
|
|
|
- ~(defclass box ...)~ — renderable with background color, border, title
|
|
- ~(render-box box window)~ — draws border (single/double/rounded), fills background, renders title
|
|
- Border styles: ~:single~, ~:double~, ~:rounded~
|
|
- Title alignment: ~:left~, ~:center~, ~:right~
|
|
- ~:focusable~ property — renders focused border color when focused
|
|
- ~100 lines
|
|
|
|
*** DONE Text renderable
|
|
:PROPERTIES:
|
|
:ID: id-v020-text
|
|
:CREATED: [2026-05-10 Sat]
|
|
:END:
|
|
:LOGBOOK:
|
|
- State \"DONE\" from \"TODO\" [2026-05-11 Mon]
|
|
:END:
|
|
|
|
- ~(defclass text ...)~ — renderable with content, fg/bg color, wrap mode
|
|
- ~(render-text text window)~ — renders text at the layout position, wraps at width
|
|
- Word-wrap: ~:none~ (truncate) or ~:word~ (break at word boundaries)
|
|
- CJK/emoji character-width aware wrapping
|
|
- ~100 lines
|
|
|
|
*** DONE Inline text styles
|
|
:PROPERTIES:
|
|
:ID: id-v020-inline
|
|
:CREATED: [2026-05-10 Sat]
|
|
:END:
|
|
:LOGBOOK:
|
|
- State \"DONE\" from \"TODO\" [2026-05-11 Mon]
|
|
:END:
|
|
|
|
- ~(defclass span ...)~ — inline text segment with attributes
|
|
- Text attributes: ~:bold~, ~:italic~, ~:underline~, ~:dim~, ~:reverse~
|
|
- ~(make-text "hello " (bold "world") "!")~ — builds styled text from spans and strings
|
|
- ~60 lines
|
|
|
|
*** DONE Dirty tracking
|
|
:PROPERTIES:
|
|
:ID: id-v020-dirty
|
|
:CREATED: [2026-05-10 Sat]
|
|
:END:
|
|
:LOGBOOK:
|
|
- State \"DONE\" from \"TODO\" [2026-05-11 Mon]
|
|
:END:
|
|
|
|
- ~(mark-dirty component)~ — flags component and all ancestors
|
|
- ~(dirty-p component)~ — returns T if the component needs re-rendering
|
|
- ~(mark-clean component)~ — clears dirty flag after render
|
|
- ~40 lines
|
|
|
|
~300 lines total. Dependencies: Phase 1 (layout engine).
|
|
|
|
** v0.3.0: Rendering Engine
|
|
|
|
The pipeline that goes from component tree to terminal output. Handles dirty
|
|
propagation, incremental rendering (only dirty branches), scissor clipping,
|
|
and diff-based output.
|
|
|
|
*** TODO Component tree → render commands
|
|
:PROPERTIES:
|
|
:ID: id-v030-pipeline
|
|
:CREATED: [2026-05-10 Sat]
|
|
:END:
|
|
|
|
- ~(render-screen root screen)~ — entry point: computes layout, walks dirty branches, collects render commands
|
|
- Render commands are lists: ~(:box x y w h bg border title)~, ~(:text x y str fg bg attrs)~
|
|
- Each component's ~render~ function returns a list of render commands
|
|
- ~100 lines
|
|
|
|
*** TODO Scissor clipping
|
|
:PROPERTIES:
|
|
:ID: id-v030-scissor
|
|
:CREATED: [2026-05-10 Sat]
|
|
:END:
|
|
|
|
- ~(with-scissor (window x y w h) &body body)~ — clips all render operations to a rectangle
|
|
- Pushes/pops scissor state so nested containers clip correctly
|
|
- ~50 lines
|
|
|
|
*** TODO Incremental diff output
|
|
:PROPERTIES:
|
|
:ID: id-v030-diff-output
|
|
:CREATED: [2026-05-10 Sat]
|
|
:END:
|
|
|
|
- ~*framebuffer*~ — a 2D array of (char, fg-color, bg-color, attrs) tuples
|
|
- ~(flush-framebuffer screen)~ — compares framebuffer to previous frame, writes only changed cells via croatoan
|
|
- ~(clear-dirty screen)~ — clears all dirty flags after a successful flush
|
|
- Croatoan compatibility: uses ~add-string~ for unchanged text, ~clear~ + ~add-string~ for changed regions
|
|
- ~150 lines
|
|
|
|
~300 lines total. Dependencies: Phase 2 (renderables + dirty tracking).
|
|
|
|
** v0.4.0: Theme Engine
|
|
|
|
Semantic color tokens, dark/light variants, hex → truecolor resolution, and
|
|
built-in presets. Application code references semantic roles (~:error~, ~:accent~),
|
|
never hex values.
|
|
|
|
*** TODO Semantic color tokens
|
|
:PROPERTIES:
|
|
:ID: id-v040-tokens
|
|
:CREATED: [2026-05-10 Sat]
|
|
:END:
|
|
|
|
- ~(defclass theme ...)~ — holds a mapping from semantic roles to hex colors
|
|
- 30+ semantic roles: ~:primary~, ~:secondary~, ~:accent~, ~:error~, ~:warning~, ~:success~, ~:info~, ~:text~, ~:text-muted~, ~:background~, ~:background-panel~, ~:background-element~, ~:border~, ~:border-active~, ~:diff-added~, ~:diff-removed~, ~:diff-context~, ~:markdown-heading~, ~:markdown-code~, ~:markdown-link~, ~:markdown-quote~, ~:syntax-keyword~, ~:syntax-function~, ~:syntax-string~, ~:syntax-number~, ~:syntax-comment~, ~:syntax-type~
|
|
- ~120 lines
|
|
|
|
*** TODO theme-color
|
|
:PROPERTIES:
|
|
:ID: id-v040-theme-color
|
|
:CREATED: [2026-05-10 Sat]
|
|
:END:
|
|
|
|
- ~(theme-color theme role)~ → returns the croatoan color pair number for the role
|
|
- ~(themed-add-string window x y str :color :error)~ — renders text with a theme semantic role
|
|
- Color pair caching: resolve hex → croatoan ~init-color~ once per (fg, bg) pair, reuse
|
|
- ~40 lines
|
|
|
|
*** TODO Built-in presets
|
|
:PROPERTIES:
|
|
:ID: id-v040-presets
|
|
:CREATED: [2026-05-10 Sat]
|
|
:END:
|
|
|
|
8 presets: default (gold), professional, minimal, nord, tokyonight, catppuccin, monokai, gruvbox
|
|
- Each preset is a plist: ~(:primary "#FFD700" :error "#BF616A" ...)~
|
|
- ~(theme-load :nord)~ — activates a preset, re-renders dirty
|
|
- Load from ~/.config/cl-tty/themes/<name>.lisp~ for custom themes
|
|
- ~80 lines
|
|
|
|
*** TODO Dark/light variants
|
|
:PROPERTIES:
|
|
:ID: id-v040-dark-light
|
|
:CREATED: [2026-05-10 Sat]
|
|
:END:
|
|
|
|
- Each preset defines both ~:dark~ and ~:light~ variants
|
|
- ~(theme-set-mode :dark | :light)~ — switches variant
|
|
- Auto-detect: read terminal background color (croatoan's background), pick closest variant
|
|
- ~50 lines
|
|
|
|
~290 lines total. Dependencies: Phase 2 (renderables), Croatoan's ~init-color~/~color-pair~.
|
|
|
|
** v0.5.0: Text Input + Keybinding System
|
|
|
|
Text input widgets with readline/emacs keybindings. A layered keybinding system
|
|
that routes keystrokes through global → local → input layers.
|
|
|
|
*** TODO TextInput — single-line input
|
|
:PROPERTIES:
|
|
:ID: id-v050-textinput
|
|
:CREATED: [2026-05-10 Sat]
|
|
:END:
|
|
|
|
- ~(defclass text-input ...)~ — single-line input with value, cursor, placeholder
|
|
- ~(render-text-input input window)~ — renders text left-aligned, placeholder when empty, blinking cursor
|
|
- Cursor movement: left/right, home, end
|
|
- Insert/delete at cursor position
|
|
- ~:on-submit~ callback — fires on Enter
|
|
- ~:max-length~ property — prevents input exceeding limit
|
|
- ~150 lines
|
|
|
|
*** TODO Textarea — multi-line input
|
|
:PROPERTIES:
|
|
:ID: id-v050-textarea
|
|
:CREATED: [2026-05-10 Sat]
|
|
:END:
|
|
|
|
- ~(defclass textarea ...)~ — multi-line input with value, cursor (row, column), selection
|
|
- ~(render-textarea area window)~ — renders visible lines, cursor, selection highlight
|
|
- Cursor: up/down, left/right, word-forward/backward, line/home/end, buffer/home/end
|
|
- Selection: Shift + navigation extends selection
|
|
- Undo/redo stack (configurable depth, default 100)
|
|
- ~:on-submit~ callback — fires on Enter
|
|
- ~200 lines
|
|
|
|
*** TODO Keybinding system
|
|
:PROPERTIES:
|
|
:ID: id-v050-keybindings
|
|
:CREATED: [2026-05-10 Sat]
|
|
:END:
|
|
|
|
- Layered keymaps: ~:global~ → ~:local~ → ~:input~ (input layer takes priority when text input is focused)
|
|
- ~(defkeymap :global '((:ctrl+p . command-palette) (:ctrl+c,ctrl+d . quit)))~
|
|
- Key format: ~:ctrl+p~, ~:alt+f~, ~:shift+tab~, ~(:ctrl+c :ctrl+d)~ (chord)
|
|
- Chord sequences: first key starts a timer, second key within timeout dispatches
|
|
- ~:leader~ key (default ~Ctrl+X~) with configurable timeout
|
|
- Key names normalized from croatoan's ~:code-key~ + ~:key-name~ output
|
|
- ~150 lines
|
|
|
|
~500 lines total. Dependencies: Phase 3 (rendering engine), Phase 4 (theme).
|
|
|
|
** v0.6.0: ScrollBox + TabBar
|
|
|
|
Container components. ScrollBox handles content larger than the viewport.
|
|
TabBar handles horizontal tab navigation.
|
|
|
|
*** TODO ScrollBox
|
|
:PROPERTIES:
|
|
:ID: id-v060-scrollbox
|
|
:CREATED: [2026-05-10 Sat]
|
|
:END:
|
|
|
|
- ~(defclass scroll-box ...)~ — container with vertical/horizontal scroll
|
|
- Viewport culling: only render children whose y position is within the visible range
|
|
- Scroll offset: ~:scroll-y~, ~:scroll-x~ slots
|
|
- ScrollBy: PageUp/PageDown (viewport height), Up/Down (1 line), Home/End (buffer start/end)
|
|
- Scrollbars: vertical and horizontal (single-line, rendered with block characters)
|
|
- Sticky scroll: when scrolled to bottom and new content arrives, auto-scroll to show it. When user scrolls up, stop auto-scrolling until they scroll back down.
|
|
- ~200 lines
|
|
|
|
*** TODO TabBar
|
|
:PROPERTIES:
|
|
:ID: id-v060-tabbar
|
|
:CREATED: [2026-05-10 Sat]
|
|
:END:
|
|
|
|
- ~(defclass tab-bar ...)~ — horizontal row of tabs
|
|
- ~(tab-bar-add tab-bar id title &optional content)~
|
|
- ~:active-tab~ slot — only renders content for the active tab
|
|
- Tab rendering: highlighted active tab, dim inactive tabs
|
|
- Left/Right or Ctrl+PageUp/PageDn to navigate tabs
|
|
- ~100 lines
|
|
|
|
~300 lines total. Dependencies: Phase 3 (rendering engine), Phase 4 (theme).
|
|
|
|
** v0.7.0: Select — Dropdown + Fuzzy Filter
|
|
|
|
A selection list component — the building block for command palettes, theme
|
|
pickers, agent selectors, file pickers.
|
|
|
|
*** TODO Select
|
|
:PROPERTIES:
|
|
:ID: id-v070-select
|
|
:CREATED: [2026-05-10 Sat]
|
|
:END:
|
|
|
|
- ~(defclass select ...)~ — list of options with keyboard navigation
|
|
- ~:options~ — list of plists: ~((:title "Nord" :value :nord :category "Themes") ...)~
|
|
- Categories: options can be grouped. Category headers rendered dim, non-selectable
|
|
- Up/Down/Ctrl+P/Ctrl+N to navigate, Enter to select, Esc to dismiss
|
|
- ~:on-select~ callback — fires on Enter
|
|
- ~:filter~ property — when set, filters the option list. Options whose title contains the filter (case-insensitive) are shown.
|
|
- Fuzzy filter: when ~:filter~ is non-nil and no exact matches, uses trigram-based fuzzy matching (3-character sliding window Jaccard similarity)
|
|
- ~150 lines
|
|
|
|
~150 lines total. Dependencies: Phase 5 (keybindings), Phase 4 (theme).
|
|
|
|
** v0.8.0: Markdown + Code + Diff Rendering
|
|
|
|
Content rendering components. Markdown for agent responses. Code for syntax
|
|
highlighting. Diff for file changes.
|
|
|
|
*** TODO Markdown
|
|
:PROPERTIES:
|
|
:ID: id-v080-markdown
|
|
:CREATED: [2026-05-10 Sat]
|
|
:END:
|
|
|
|
- ~(defclass markdown ...)~ — renders markdown content as styled text
|
|
- Heading levels 1-6: colored by theme (~:markdown-heading~) with level-based sizing
|
|
- Bold, italic, inline code, strikethrough — rendered as croatoan text attributes
|
|
- Code blocks: fenced (~```~) and indented. Background-colored, syntax-highlighted via regex
|
|
- Links: OSC 8 hyperlinks (clickable in Kitty, WezTerm, iTerm2, Ghostty). Format: ~\x1b]8;;url\x1b\\...link text...\x1b]8;;\x1b\\~
|
|
- Blockquotes: colored left border (~:markdown-quote~), indented text
|
|
- Tables: aligned column text, no borders. Column alignment from header separators
|
|
- Lists: ordered and unordered, with indentation
|
|
- All features degrade gracefully to plain text on terminals without attribute support
|
|
- ~200 lines
|
|
|
|
*** TODO Code
|
|
:PROPERTIES:
|
|
:ID: id-v080-code
|
|
:CREATED: [2026-05-10 Sat]
|
|
:END:
|
|
|
|
- ~(defclass code ...)~ — renders syntax-highlighted code
|
|
- ~:content~ — the code string
|
|
- ~:language~ — language identifier for syntax rules
|
|
- Line numbers (optional, via ~:line-numbers t~)
|
|
- Regex-based highlighting (no Tree-sitter dependency):
|
|
- Keywords: language-specific keyword lists
|
|
- Strings: single and double quoted
|
|
- Comments: line (~;//~, ~#~) and block (~/* */~)
|
|
- Numbers: integer and float literals
|
|
- Functions: word followed by ~(~
|
|
- Colors from theme: ~:syntax-keyword~, ~:syntax-function~, ~:syntax-string~, ~:syntax-number~, ~:syntax-comment~, ~:syntax-type~
|
|
- ~150 lines
|
|
|
|
*** TODO Diff
|
|
:PROPERTIES:
|
|
:ID: id-v080-diff
|
|
:CREATED: [2026-05-10 Sat]
|
|
:END:
|
|
|
|
- ~(defclass diff ...)~ — renders unified diff output
|
|
- ~:content~ — diff text (standard unified diff format)
|
|
- Added lines: ~+~ prefix, green background (~:diff-added~)
|
|
- Removed lines: ~-~ prefix, red background (~:diff-removed~)
|
|
- Context lines: ~ ~ prefix, neutral background (~:diff-context~)
|
|
- Line numbers: optional, rendered in ~:diff-line-number~ color
|
|
- ~50 lines
|
|
|
|
~400 lines total. Dependencies: Phase 4 (theme), Phase 2 (renderables).
|
|
|
|
** v0.9.0: Dialog System + Toast
|
|
|
|
Modal overlays and transient notifications.
|
|
|
|
*** TODO Dialog base
|
|
:PROPERTIES:
|
|
:ID: id-v090-dialog
|
|
:CREATED: [2026-05-10 Sat]
|
|
:END:
|
|
|
|
- ~(defclass dialog ...)~ — absolute-positioned overlay with backdrop
|
|
- Backdrop: semi-transparent (dimmed background color)
|
|
- Centered panel with ~:background-panel~ color, border
|
|
- ~:on-dismiss~ callback — fires on Esc or backdrop click
|
|
- ~:size~ — ~:small~ (40 cols), ~:medium~ (60 cols), ~:large~ (88 cols). Height computed from content.
|
|
- Stack-based: dialogs push/pop on a ~*dialog-stack*~
|
|
- Esc dismisses top dialog. Ctrl+C clears stack.
|
|
- ~100 lines
|
|
|
|
*** TODO Dialog sub-classes
|
|
:PROPERTIES:
|
|
:ID: id-v090-dialog-types
|
|
:CREATED: [2026-05-10 Sat]
|
|
:END:
|
|
|
|
- ~alert-dialog~ — title + message + OK button
|
|
- ~confirm-dialog~ — title + message + Yes/No/Cancel buttons
|
|
- ~select-dialog~ — wraps a Select component in a modal. Title, searchable list, action buttons
|
|
- ~prompt-dialog~ — wraps a TextInput in a modal. Title, input, OK/Cancel buttons
|
|
- ~60 lines
|
|
|
|
*** TODO Toast notifications
|
|
:PROPERTIES:
|
|
:ID: id-v090-toast
|
|
:CREATED: [2026-05-10 Sat]
|
|
:END:
|
|
|
|
- ~(toast title &key variant duration)~ — shows a transient notification
|
|
- Variants: ~:info~ (blue), ~:success~ (green), ~:warning~ (yellow), ~:error~ (red) — colored left border
|
|
- ~:duration~ — auto-dismiss after N milliseconds (default 5000)
|
|
- Position: top-right corner, max 60 cols wide
|
|
- Multiple toasts stack vertically
|
|
- ~60 lines
|
|
|
|
~220 lines total. Dependencies: Phase 3 (rendering engine), Phase 4 (theme), Phase 5 (TextInput), Phase 7 (Select).
|
|
|
|
** v0.10.0: Mouse Support
|
|
|
|
Mouse event propagation through the component tree.
|
|
|
|
*** TODO Mouse events
|
|
:PROPERTIES:
|
|
:ID: id-v100-mouse
|
|
:CREATED: [2026-05-10 Sat]
|
|
:END:
|
|
|
|
- Enable croatoan mouse mode: ~(setf (mouse-enabled-p window) t)~
|
|
- Parse ncurses mouse codes: button (left/right/middle), state (press/release/drag), x, y
|
|
- Ctrl/Shift/Meta modifiers from mouse event
|
|
- ~:on-mouse-down~, ~:on-mouse-up~, ~:on-mouse-move~, ~:on-mouse-scroll~ callbacks on components
|
|
- Hit-testing: walk the component tree from root, find the deepest component whose rect contains (x, y)
|
|
- Event propagation: component consumes event by returning T from callback; otherwise bubbles to parent
|
|
- Scroll wheel: mapped to PageUp/PageDown in ScrollBox
|
|
- Click on OSC 8 link: extract URL, open via ~xdg-open~
|
|
- ~100 lines
|
|
|
|
*** TODO Text selection + copy
|
|
:PROPERTIES:
|
|
:ID: id-v100-selection
|
|
:CREATED: [2026-05-10 Sat]
|
|
:END:
|
|
|
|
- Mouse drag: highlight text between drag start and current position
|
|
- ~(get-selection)~ — returns the selected text as a string
|
|
- Copy: pipe selection to ~xclip~ / ~wl-copy~ / ~pbcopy~
|
|
- ~50 lines
|
|
|
|
~150 lines total. Dependencies: Phase 3 (rendering engine).
|
|
|
|
** v0.11.0: Plugin / Slot System
|
|
|
|
Extensible named slots. Applications and plugins register content into named
|
|
slots. The component tree renders whatever is registered.
|
|
|
|
*** TODO Slot system
|
|
:PROPERTIES:
|
|
:ID: id-v110-slots
|
|
:CREATED: [2026-05-10 Sat]
|
|
:END:
|
|
|
|
- ~(defslot :sidebar-title &key order render-fn)~ — registers a rendering function for a slot
|
|
- ~(slot-render slot-name ...)~ — calls all registered render-fns for the slot in priority-ordered sequence
|
|
- Slot modes: ~:stack~ (render all, default), ~:replace~ (last registered wins), ~:single-winner~ (first matching wins)
|
|
- ~:order~ integer — sorting key for ~:stack~ mode (lower = renders first)
|
|
- Built-in slot naming convention: component name, then sub-slot: ~sidebar-title~, ~sidebar-content~, ~home-logo~, ~home-prompt~
|
|
- ~100 lines
|
|
|
|
~100 lines total. Dependencies: Phase 2 (renderables + layout).
|
|
|
|
* v1.0.0: Complete Framework
|
|
|
|
All 11 phases integrated and tested. Applications can build rich terminal UIs
|
|
from the component library without writing custom ncurses code.
|
|
|
|
* Neurosymbolic Phase Reference
|
|
|
|
| Phase | Component | Lines | Release |
|
|
|-------+------------------------------------+--------+---------|
|
|
| 1 | Layout engine (Yoga FFI + API) | ~350 | v0.1.0 |
|
|
| 2 | Renderables (Box, Text) + dirty | ~300 | v0.2.0 |
|
|
| 3 | Rendering engine (diff, scissor) | ~300 | v0.3.0 |
|
|
| 4 | Theme engine (tokens, presets) | ~290 | v0.4.0 |
|
|
| 5 | TextInput + Textarea + keybindings | ~500 | v0.5.0 |
|
|
| 6 | ScrollBox + TabBar | ~300 | v0.6.0 |
|
|
| 7 | Select (dropdown + fuzzy filter) | ~150 | v0.7.0 |
|
|
| 8 | Markdown + Code + Diff | ~400 | v0.8.0 |
|
|
| 9 | Dialog system + Toast | ~220 | v0.9.0 |
|
|
| 10 | Mouse support + selection | ~150 | v0.10.0 |
|
|
| 11 | Plugin / slot system | ~100 | v0.11.0 |
|
|
|-------+------------------------------------+--------+---------|
|
|
| Total | | ~3060 | |
|