v0.8.0: tangle to XDG (~/.local/share/cl-tty/), remove stale memex .lisp files
This commit is contained in:
@@ -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))
|
||||
|
||||
Reference in New Issue
Block a user