v0.8.0: tangle to XDG (~/.local/share/cl-tty/), remove stale memex .lisp files

This commit is contained in:
2026-05-18 13:04:10 -04:00
parent e3415cee73
commit af572d5a8c
67 changed files with 518 additions and 6301 deletions

View File

@@ -178,7 +178,7 @@ start avoids package redefinition churn. The current system does not yet call
raw mode from within the input module; consumers manage raw mode themselves
via ~sb-posix~ directly.
#+BEGIN_SRC lisp :tangle ../src/components/input-package.lisp
#+BEGIN_SRC lisp :tangle ~/.local/share/cl-tty/src/components/input-package.lisp
(defpackage :cl-tty.input
(:use :cl :cl-tty.backend :cl-tty.box :cl-tty.layout)
(:export
@@ -243,7 +243,7 @@ textarea line splitting — a blank document has one empty line.
This is the first block tangling to input.lisp, so it includes the
~in-package~ form that all subsequent blocks share.
#+BEGIN_SRC lisp :tangle ../src/components/input.lisp
#+BEGIN_SRC lisp :tangle ~/.local/share/cl-tty/src/components/input.lisp
(in-package #:cl-tty.input)
(defun %split-string (string separator)
@@ -262,12 +262,12 @@ application's main loop. Widget ~render~ methods use them to draw themselves.
Defining them here rather than in the rendering module keeps the dependency
clean — input widgets depend on rendering, not the other way around.
#+BEGIN_SRC lisp :tangle ../src/components/input.lisp
#+BEGIN_SRC lisp :tangle ~/.local/share/cl-tty/src/components/input.lisp
(defvar *current-backend* nil
"The active backend used for rendering.")
#+END_SRC
#+BEGIN_SRC lisp :tangle ../src/components/input.lisp
#+BEGIN_SRC lisp :tangle ~/.local/share/cl-tty/src/components/input.lisp
(defvar *current-theme* nil
"The active theme used for semantic color resolution.")
#+END_SRC
@@ -299,7 +299,7 @@ or lowercase, but ~code~ preserves the actual code point. The
~handle-text-input~ function uses ~code-char~ on the code slot to get the
true character for insertion.
#+BEGIN_SRC lisp :tangle ../src/components/input.lisp
#+BEGIN_SRC lisp :tangle ~/.local/share/cl-tty/src/components/input.lisp
(defstruct key-event
(key nil :type (or keyword null))
(ctrl nil :type boolean)
@@ -323,7 +323,7 @@ field is :press, :release, or :drag, determined by whether the button
code includes the motion bit (bit 5). Coordinates are 1-indexed from
the terminal; no adjustment is performed here.
#+BEGIN_SRC lisp :tangle ../src/components/input.lisp
#+BEGIN_SRC lisp :tangle ~/.local/share/cl-tty/src/components/input.lisp
(defstruct mouse-event
(type nil :type (or keyword null))
(button nil :type (or keyword null))
@@ -342,7 +342,7 @@ the modern xterm format, as opposed to the single-letter terminators used
by VT100-style sequences (~ESC[H~ = Home, ~ESC[F~ = End). Modern terminal
emulators emit the tilde form for most keys; we handle both.
#+BEGIN_SRC lisp :tangle ../src/components/input.lisp
#+BEGIN_SRC lisp :tangle ~/.local/share/cl-tty/src/components/input.lisp
(defparameter *csi-tilde-table*
'((1 . :home) (2 . :insert) (3 . :delete) (4 . :end)
(5 . :page-up) (6 . :page-down)
@@ -363,7 +363,7 @@ emitted by most terminal emulators in "normal" (non-application) cursor
key mode. The ~:back-tab~ mapping for Z handles Shift+Tab, which some
emulators report as ~ESC[Z~.
#+BEGIN_SRC lisp :tangle ../src/components/input.lisp
#+BEGIN_SRC lisp :tangle ~/.local/share/cl-tty/src/components/input.lisp
(defparameter *csi-key-table*
'((#\A . :up) (#\B . :down) (#\C . :right) (#\D . :left)
(#\F . :end) (#\H . :home)
@@ -391,7 +391,7 @@ Modifier encoding follows the xterm convention: Shift=1, Alt=2, Ctrl=4.
The extended parameter vector carries the raw parameter bytes for
sequences where modifiers appear in a non-standard position.
#+BEGIN_SRC lisp :tangle ../src/components/input.lisp
#+BEGIN_SRC lisp :tangle ~/.local/share/cl-tty/src/components/input.lisp
(defun parse-csi-params (params terminator extended)
(let* ((key (if (find terminator '(#\~ #\u))
(cdr (assoc (first params) *csi-tilde-table*))
@@ -440,7 +440,7 @@ and read directly into the backing storage. This avoids alien allocation
and manual ~free-alien~ while keeping the GC from moving the buffer
during the ~unix-read~ syscall.
#+BEGIN_SRC lisp :tangle ../src/components/input.lisp
#+BEGIN_SRC lisp :tangle ~/.local/share/cl-tty/src/components/input.lisp
(defun read-raw-byte (&key timeout)
(let* ((buf (make-array 1 :element-type '(unsigned-byte 8)))
(fd 0)
@@ -481,7 +481,7 @@ The SS3 path handles shifted cursor keys that some emulators report as
~ESC O A~ through ~ESC O D~ (shifted up/down/right/left). These use a
different byte prefix from the CSI form ~ESC [ A~ through ~ESC [ D~.
#+BEGIN_SRC lisp :tangle ../src/components/input.lisp
#+BEGIN_SRC lisp :tangle ~/.local/share/cl-tty/src/components/input.lisp
(defun %read-escape-sequence ()
(flet ((read-next (&optional (timeout nil))
(let ((b (read-raw-byte :timeout timeout)))
@@ -536,7 +536,7 @@ non-digit byte, handling an optional list of initial bytes that were
already consumed by the caller. Returns the parsed integer and the
terminator byte.
#+BEGIN_SRC lisp :tangle ../src/components/input.lisp
#+BEGIN_SRC lisp :tangle ~/.local/share/cl-tty/src/components/input.lisp
(defun %read-digits (&optional (initial-bytes nil))
"Read bytes until a non-digit is encountered.
Returns (values number terminator-byte)."
@@ -564,7 +564,7 @@ a ~mouse-event~ struct with proper button and type classification.
Coordinates are converted from 1-based (terminal protocol) to 0-based
(framebuffer convention) by subtracting 1 from both x and y.
#+BEGIN_SRC lisp :tangle ../src/components/input.lisp
#+BEGIN_SRC lisp :tangle ~/.local/share/cl-tty/src/components/input.lisp
(defun %parse-sgr-mouse ()
"Parse SGR mouse escape sequence: ESC [ < Cb ; Cx ; Cy M/m
Returns a mouse-event struct."
@@ -609,7 +609,7 @@ the modifier appears after the primary parameter in an extended format
(e.g., ~ESC [ 1 ; 5 A~ where 5 encodes Ctrl+Shift). This array is passed
to ~parse-csi-params~ for modifier extraction.
#+BEGIN_SRC lisp :tangle ../src/components/input.lisp
#+BEGIN_SRC lisp :tangle ~/.local/share/cl-tty/src/components/input.lisp
(defun parse-csi-sequence ()
(flet ((read-param (next-fn) (let ((acc nil))
(loop for b = (funcall next-fn)
@@ -655,7 +655,7 @@ Overlong sequences (e.g., encoding ASCII in 2+ bytes) are rejected because
the range checks on the leading byte exclude them: a 2-byte sequence with
b0=0xC0 would have ~(= #xc2 b0 #xdf)~ fail since 0xC0 < 0xC2.
#+BEGIN_SRC lisp :tangle ../src/components/input.lisp
#+BEGIN_SRC lisp :tangle ~/.local/share/cl-tty/src/components/input.lisp
(defun utf8-decode (bytes)
(case (length bytes)
(2 (let ((b0 (first bytes)) (b1 (second bytes)))
@@ -703,7 +703,7 @@ streamed in real time from the terminal; if we're too aggressive, we
might cut off a multi-byte character during a slow paste or network
connection. The 500ms gives the terminal ample time to deliver all bytes.
#+BEGIN_SRC lisp :tangle ../src/components/input.lisp
#+BEGIN_SRC lisp :tangle ~/.local/share/cl-tty/src/components/input.lisp
(defun %read-event (&key timeout)
(multiple-value-bind (b reason) (read-raw-byte :timeout timeout)
(unless b (return-from %read-event (if (eq reason :eof) :eof nil)))
@@ -754,11 +754,11 @@ call and, if set, query the new terminal dimensions and redraw. The
flag is not automatically cleared — the consumer must set it to ~nil~
after handling the resize.
#+BEGIN_SRC lisp :tangle ../src/components/input.lisp
#+BEGIN_SRC lisp :tangle ~/.local/share/cl-tty/src/components/input.lisp
(defvar *terminal-resized-p* nil)
#+END_SRC
#+BEGIN_SRC lisp :tangle ../src/components/input.lisp
#+BEGIN_SRC lisp :tangle ~/.local/share/cl-tty/src/components/input.lisp
#+sbcl
(eval-when (:load-toplevel :execute)
(require :sb-posix)
@@ -775,7 +775,7 @@ input). SBCL's ~SB-POSIX:WITH-RAW-TERMINAL~ is not available in all builds
(e.g. Debian-packaged SBCL 2.5.x). This implementation uses ~stty~ for
portability.
#+BEGIN_SRC lisp :tangle ../src/components/input.lisp
#+BEGIN_SRC lisp :tangle ~/.local/share/cl-tty/src/components/input.lisp
(defun %raw-mode-on ()
(uiop:run-program '("stty" "raw" "-echo" "-echoe" "-echok" "-onlcr")
:output nil :error-output nil :ignore-error-status t))
@@ -806,7 +806,7 @@ This method is deliberately simple: it's a thin wrapper that adapts the
~%read-event~ API to the backend protocol's ~read-event~ generic function.
All the complexity lives in ~%read-event~ and its callees.
#+BEGIN_SRC lisp :tangle ../src/components/input.lisp
#+BEGIN_SRC lisp :tangle ~/.local/share/cl-tty/src/components/input.lisp
(defmethod read-event ((b cl-tty.backend:backend) &key timeout)
;; Check for pending terminal resize before reading input.
;; The SIGWINCH handler sets *terminal-resized-p* asynchronously.
@@ -851,7 +851,7 @@ shift out when full) keeps memory bounded.
This is the first block tangling to textarea.lisp, so it includes the
~in-package~ form.
#+BEGIN_SRC lisp :tangle ../src/components/textarea.lisp
#+BEGIN_SRC lisp :tangle ~/.local/share/cl-tty/src/components/textarea.lisp
(in-package #:cl-tty.input)
(defclass textarea (dirty-mixin)
@@ -878,7 +878,7 @@ The constructor is a separate function rather than a ~:constructor~
option on ~defclass~ because it needs to normalize the value argument
~(or value "")~ — a pattern that would clutter the class definition.
#+BEGIN_SRC lisp :tangle ../src/components/textarea.lisp
#+BEGIN_SRC lisp :tangle ~/.local/share/cl-tty/src/components/textarea.lisp
(defun make-textarea (&key value on-submit)
(make-instance 'textarea
:value (or value "")
@@ -895,13 +895,13 @@ line, which is the correct representation of a blank document.
~textarea-line-count~ is a simple wrapper for the number of lines.
It's used by cursor movement functions to clamp the cursor row.
#+BEGIN_SRC lisp :tangle ../src/components/textarea.lisp
#+BEGIN_SRC lisp :tangle ~/.local/share/cl-tty/src/components/textarea.lisp
(defun textarea-lines (ta)
"Split value into lines."
(%split-string (textarea-value ta) #\Newline))
#+END_SRC
#+BEGIN_SRC lisp :tangle ../src/components/textarea.lisp
#+BEGIN_SRC lisp :tangle ~/.local/share/cl-tty/src/components/textarea.lisp
(defun textarea-line-count (ta)
"Number of lines in value."
(length (textarea-lines ta)))
@@ -919,7 +919,7 @@ that change line structure (newline, backspace joining lines). It
also marks the widget dirty, ensuring the renderer picks up the
cursor position change.
#+BEGIN_SRC lisp :tangle ../src/components/textarea.lisp
#+BEGIN_SRC lisp :tangle ~/.local/share/cl-tty/src/components/textarea.lisp
(defun textarea-ensure-cursor (ta)
"Clamp cursor to valid range."
(let ((lines (textarea-lines ta)))
@@ -942,7 +942,7 @@ the textarea code work with different representations — ~textarea-lines~
returns a list, but the insertion/backspace code operates on vectors
for efficient element replacement.
#+BEGIN_SRC lisp :tangle ../src/components/textarea.lisp
#+BEGIN_SRC lisp :tangle ~/.local/share/cl-tty/src/components/textarea.lisp
(defun %join-lines (lines)
"Join a sequence of strings with newlines."
(with-output-to-string (s)
@@ -969,7 +969,7 @@ within the current line. The algorithm:
The function updates ~cursor-col~ by 1 after insertion and marks the
widget dirty.
#+BEGIN_SRC lisp :tangle ../src/components/textarea.lisp
#+BEGIN_SRC lisp :tangle ~/.local/share/cl-tty/src/components/textarea.lisp
(defun textarea-insert-char (ta char)
"Insert CHAR at the cursor position."
(textarea-push-undo ta)
@@ -1010,7 +1010,7 @@ Algorithm:
6. If the cursor row is beyond the last line, simply append a newline.
7. Mark dirty.
#+BEGIN_SRC lisp :tangle ../src/components/textarea.lisp
#+BEGIN_SRC lisp :tangle ~/.local/share/cl-tty/src/components/textarea.lisp
(defun textarea-newline (ta)
"Insert a newline at the cursor."
(textarea-push-undo ta)
@@ -1056,7 +1056,7 @@ line, removing the newline character between them.
All paths push undo state before modifying the value.
#+BEGIN_SRC lisp :tangle ../src/components/textarea.lisp
#+BEGIN_SRC lisp :tangle ~/.local/share/cl-tty/src/components/textarea.lisp
(defun textarea-backspace (ta)
"Delete character before cursor."
(textarea-push-undo ta)
@@ -1106,13 +1106,13 @@ on a long line and moves up to a shorter 5-character line, the column
clamps to 5. This matches how most editors handle column preservation
— the column "remembers" its position but is constrained by line length.
#+BEGIN_SRC lisp :tangle ../src/components/textarea.lisp
#+BEGIN_SRC lisp :tangle ~/.local/share/cl-tty/src/components/textarea.lisp
(defun textarea-move-up (ta)
(decf (textarea-cursor-row ta))
(textarea-ensure-cursor ta))
#+END_SRC
#+BEGIN_SRC lisp :tangle ../src/components/textarea.lisp
#+BEGIN_SRC lisp :tangle ~/.local/share/cl-tty/src/components/textarea.lisp
(defun textarea-move-down (ta)
(incf (textarea-cursor-row ta))
(textarea-ensure-cursor ta))
@@ -1143,7 +1143,7 @@ discarded because the edit graph has branched. Implementing a full tree
undo would be significantly more complex and is unnecessary for a TUI
textarea.
#+BEGIN_SRC lisp :tangle ../src/components/textarea.lisp
#+BEGIN_SRC lisp :tangle ~/.local/share/cl-tty/src/components/textarea.lisp
(defun textarea-push-undo (ta)
"Save current value on undo stack."
(let ((stack (textarea-undo-stack ta)))
@@ -1155,7 +1155,7 @@ textarea.
(setf (fill-pointer (textarea-redo-stack ta)) 0)))
#+END_SRC
#+BEGIN_SRC lisp :tangle ../src/components/textarea.lisp
#+BEGIN_SRC lisp :tangle ~/.local/share/cl-tty/src/components/textarea.lisp
(defun textarea-undo (ta)
(let ((stack (textarea-undo-stack ta)))
(when (plusp (length stack))
@@ -1166,7 +1166,7 @@ textarea.
(mark-dirty ta)))))
#+END_SRC
#+BEGIN_SRC lisp :tangle ../src/components/textarea.lisp
#+BEGIN_SRC lisp :tangle ~/.local/share/cl-tty/src/components/textarea.lisp
(defun textarea-redo (ta)
(let ((stack (textarea-redo-stack ta)))
(when (plusp (length stack))
@@ -1203,7 +1203,7 @@ rather than looking at ~key-event-key~. This is because ~key-event-key~
is always an uppercase keyword (~:a~ for both 'a' and 'A'), but the
code preserves the actual character.
#+BEGIN_SRC lisp :tangle ../src/components/textarea.lisp
#+BEGIN_SRC lisp :tangle ~/.local/share/cl-tty/src/components/textarea.lisp
(defun handle-textarea-input (ta event)
"Process a key-event on a textarea widget."
(cond
@@ -1277,7 +1277,7 @@ Cursor rendering is handled by the focus/selection rendering layer,
not by this method. This keeps the render method simple — it just
paints text.
#+BEGIN_SRC lisp :tangle ../src/components/textarea.lisp
#+BEGIN_SRC lisp :tangle ~/.local/share/cl-tty/src/components/textarea.lisp
(defmethod render ((ta textarea) (backend t))
"Render textarea lines at layout position."
(let* ((ln (textarea-layout-node ta))
@@ -1321,7 +1321,7 @@ tracking. Slots:
This is the first block tangling to text-input.lisp, so it includes the
~in-package~ form.
#+BEGIN_SRC lisp :tangle ../src/components/text-input.lisp
#+BEGIN_SRC lisp :tangle ~/.local/share/cl-tty/src/components/text-input.lisp
(in-package #:cl-tty.input)
(defclass text-input (dirty-mixin)
@@ -1350,7 +1350,7 @@ The ~(or value "")~ pattern ensures the value is always a string,
even if the caller passes nil. This eliminates a class of nil-pointer
errors in string operations downstream.
#+BEGIN_SRC lisp :tangle ../src/components/text-input.lisp
#+BEGIN_SRC lisp :tangle ~/.local/share/cl-tty/src/components/text-input.lisp
(defun make-text-input (&key value cursor placeholder max-length on-submit)
(make-instance 'text-input
:value (or value "")
@@ -1376,7 +1376,7 @@ This is a pure insert — it does not replace the character at the cursor;
it shifts subsequent characters right. For overwrite behavior, the caller
would need a different function.
#+BEGIN_SRC lisp :tangle ../src/components/text-input.lisp
#+BEGIN_SRC lisp :tangle ~/.local/share/cl-tty/src/components/text-input.lisp
(defun text-input-insert (input char)
(let* ((val (text-input-value input))
(pos (text-input-cursor input))
@@ -1396,7 +1396,7 @@ The algorithm concatenates the prefix (up to one before cursor) with
the suffix (from cursor onward), effectively removing the character
at cursor-1. The cursor is decremented by 1.
#+BEGIN_SRC lisp :tangle ../src/components/text-input.lisp
#+BEGIN_SRC lisp :tangle ~/.local/share/cl-tty/src/components/text-input.lisp
(defun text-input-backspace (input)
(let* ((val (text-input-value input)) (pos (text-input-cursor input)))
(when (zerop pos) (return-from text-input-backspace))
@@ -1417,7 +1417,7 @@ moving the cursor position.
This contrasts with backspace, which removes the character before
cursor and decrements the cursor.
#+BEGIN_SRC lisp :tangle ../src/components/text-input.lisp
#+BEGIN_SRC lisp :tangle ~/.local/share/cl-tty/src/components/text-input.lisp
(defun text-input-delete (input)
(let* ((val (text-input-value input)) (pos (text-input-cursor input)))
(when (>= pos (length val)) (return-from text-input-delete))
@@ -1434,13 +1434,13 @@ one character position, clamped to [0, length]. Left movement stops at
Each movement function marks the widget dirty so the renderer redraws
the cursor position.
#+BEGIN_SRC lisp :tangle ../src/components/text-input.lisp
#+BEGIN_SRC lisp :tangle ~/.local/share/cl-tty/src/components/text-input.lisp
(defun text-input-move-left (input)
(when (plusp (text-input-cursor input)) (decf (text-input-cursor input)))
(mark-dirty input))
#+END_SRC
#+BEGIN_SRC lisp :tangle ../src/components/text-input.lisp
#+BEGIN_SRC lisp :tangle ~/.local/share/cl-tty/src/components/text-input.lisp
(defun text-input-move-right (input)
(when (< (text-input-cursor input) (length (text-input-value input))) (incf (text-input-cursor input)))
(mark-dirty input))
@@ -1454,13 +1454,13 @@ the cursor position.
These are the programmatic equivalents of the Home and End keys and
are also used by the Ctrl+A and Ctrl+E keybindings.
#+BEGIN_SRC lisp :tangle ../src/components/text-input.lisp
#+BEGIN_SRC lisp :tangle ~/.local/share/cl-tty/src/components/text-input.lisp
(defun text-input-move-home (input)
(setf (text-input-cursor input) 0)
(mark-dirty input))
#+END_SRC
#+BEGIN_SRC lisp :tangle ../src/components/text-input.lisp
#+BEGIN_SRC lisp :tangle ~/.local/share/cl-tty/src/components/text-input.lisp
(defun text-input-move-end (input)
(setf (text-input-cursor input) (length (text-input-value input)))
(mark-dirty input))
@@ -1485,7 +1485,7 @@ A "word" here is defined as a run of non-space characters. This matches
the shell/Emacs convention for Ctrl+W rather than an English word boundary
(which would involve punctuation handling).
#+BEGIN_SRC lisp :tangle ../src/components/text-input.lisp
#+BEGIN_SRC lisp :tangle ~/.local/share/cl-tty/src/components/text-input.lisp
(defun text-input-delete-word-before (input)
(let* ((val (text-input-value input)) (pos (text-input-cursor input)))
(when (zerop pos) (return-from text-input-delete-word-before))
@@ -1523,7 +1523,7 @@ visible characters (letters, digits, punctuation, symbols) are
inserted. Control characters and spaces are handled by their specific
key bindings.
#+BEGIN_SRC lisp :tangle ../src/components/text-input.lisp
#+BEGIN_SRC lisp :tangle ~/.local/share/cl-tty/src/components/text-input.lisp
(defun handle-text-input (input event)
(cond
((key-event-ctrl event)
@@ -1569,7 +1569,7 @@ The cursor is a solid block ("█") drawn at the cursor column offset
from the text start. If the cursor is beyond the truncated display
width, it's clamped to the last visible position.
#+BEGIN_SRC lisp :tangle ../src/components/text-input.lisp
#+BEGIN_SRC lisp :tangle ~/.local/share/cl-tty/src/components/text-input.lisp
(defmethod render ((in text-input) (backend t))
(let* ((ln (text-input-layout-node in))
(x (if ln (layout-node-x ln) 0)) (y (if ln (layout-node-y ln) 0))
@@ -1608,7 +1608,7 @@ polymorphism is handled by the dispatch function.
This is the first block tangling to keybindings.lisp, so it includes
the ~in-package~ form.
#+BEGIN_SRC lisp :tangle ../src/components/keybindings.lisp
#+BEGIN_SRC lisp :tangle ~/.local/share/cl-tty/src/components/keybindings.lisp
(in-package #:cl-tty.input)
(defstruct keymap
@@ -1628,11 +1628,11 @@ chord support (e.g., ~(:ctrl+x :ctrl+s)~). Currently only single-key
specs work; the timeout and list-of-lists spec syntax are placeholders
for the eventual chord implementation.
#+BEGIN_SRC lisp :tangle ../src/components/keybindings.lisp
#+BEGIN_SRC lisp :tangle ~/.local/share/cl-tty/src/components/keybindings.lisp
(defparameter *keymaps* (make-hash-table :test #'equal))
#+END_SRC
#+BEGIN_SRC lisp :tangle ../src/components/keybindings.lisp
#+BEGIN_SRC lisp :tangle ~/.local/share/cl-tty/src/components/keybindings.lisp
(defparameter *chord-timeout* 0.5)
#+END_SRC
@@ -1657,7 +1657,7 @@ The modifier matching uses ~string=?~ on the modifier part because
on the keyword would make them different specifiers, which is unexpected
for users writing ~:ctrl+p~ in their keymaps.
#+BEGIN_SRC lisp :tangle ../src/components/keybindings.lisp
#+BEGIN_SRC lisp :tangle ~/.local/share/cl-tty/src/components/keybindings.lisp
(defun key-match-p (spec event)
"T if SPEC matches EVENT. Spec is :ctrl+p (modifier+key keyword)
or (:ctrl+p) for single-spec in a list, or (:ctrl+x :ctrl+s) for chords."
@@ -1716,7 +1716,7 @@ Chords ~((:ctrl+x :ctrl+s))~ are not yet supported; only single
key specs work. The ~*chord-timeout*~ variable and list-of-lists syntax
are reserved for future implementation.
#+BEGIN_SRC lisp :tangle ../src/components/keybindings.lisp
#+BEGIN_SRC lisp :tangle ~/.local/share/cl-tty/src/components/keybindings.lisp
(defun dispatch-key-event (event &key component)
(labels ((try-keymap (km)
(when km
@@ -1738,7 +1738,7 @@ are reserved for future implementation.
~defkeymap~ is a convenience macro that registers a keymap in the global
~*keymaps*~ hash table. Syntax:
#+BEGIN_SRC lisp :tangle ../src/components/keybindings.lisp
#+BEGIN_SRC lisp :tangle ~/.local/share/cl-tty/src/components/keybindings.lisp
(defmacro defkeymap (name &body bindings)
`(setf (gethash ',name *keymaps*)
(make-keymap :name ',name
@@ -1759,7 +1759,7 @@ This generic function allows the dispatch system to query any object for
its keymap, enabling per-component keybinding customization without
requiring components to inherit from a specific base class.
#+BEGIN_SRC lisp :tangle ../src/components/keybindings.lisp
#+BEGIN_SRC lisp :tangle ~/.local/share/cl-tty/src/components/keybindings.lisp
;;; --- Component protocol integration ---
(defgeneric component-keymap (component)
(:method ((c t)) nil))
@@ -1780,7 +1780,7 @@ The test suite is tangled to ~../tests/input-tests.lisp~ and covers:
key-spec matching with all modifiers, list-form specs, return values,
empty keymap, local-over-global, multiple bindings, defkeymap macro)
#+BEGIN_SRC lisp :tangle ../tests/input-tests.lisp
#+BEGIN_SRC lisp :tangle ~/.local/share/cl-tty/tests/input-tests.lisp
(defpackage :cl-tty-input-test
(:use :cl :fiveam :cl-tty.backend :cl-tty.box :cl-tty.layout :cl-tty.input)
(:export #:run-tests))