reorg: tangle to XDG, remove stale lisp files, fix tui input

- Changed all 50 org file :tangle targets from ../lisp/ to
  ~/.local/share/passepartout/lisp/ (XDG data dir)
- Removed 49 generated .lisp files from project lisp/ directory
- Removed tests/system-integration-tests.lisp (generated)
- Removed lisp/*.fasl (compiled, stale)
- Updated core-manifest.org to tangle .asd to XDG root
- Remapped quicklisp symlink: local-projects/passepartout → XDG

TUI fixes in channel-tui-main.org:
- Removed with-raw-terminal (stty raw breaks fd 0 reads in this SBCL)
- Use cat subprocess + pipe for keyboard input (via :input :interactive)
- Blocking read-char on pipe with with-timeout 0.1s for daemon processing
- Key events queued via drain-queue alongside daemon messages
- Full dialog key routing (Escape, Up/Down, Enter, filters, Backspace)
- SIGWINCH resize handling
- Post-handshake backend-size re-query
- Daemon version in status bar (was v0.5.0 hardcoded)
- Handshake version stored in state, no add-msg
- :daemon-version and :size-queried in state plist
- view-status uses draw-rect for background
- Test section gated with #+passepartout-tests
This commit is contained in:
2026-05-14 12:34:06 -04:00
parent 0ad9d3bdb5
commit b9a4318ef8
100 changed files with 109 additions and 12282 deletions

View File

@@ -1,5 +1,5 @@
#+TITLE: Passepartout TUI — Controller
#+PROPERTY: header-args:lisp :tangle ../lisp/channel-tui-main.lisp
#+PROPERTY: header-args:lisp :tangle /home/user/.local/share/passepartout/lisp/channel-tui-main.lisp
* Controller
@@ -31,7 +31,7 @@ Event handlers + daemon I/O + main loop.
render/input event loop at ~30fps.
** Event Handlers
#+BEGIN_SRC lisp :tangle ../lisp/channel-tui-main.lisp
#+BEGIN_SRC lisp :tangle /home/user/.local/share/passepartout/lisp/channel-tui-main.lisp
(in-package :passepartout.channel-tui)
(defun on-key (ch)
@@ -712,7 +712,7 @@ Event handlers + daemon I/O + main loop.
#+END_SRC
** Daemon Communication
#+BEGIN_SRC lisp :tangle ../lisp/channel-tui-main.lisp
#+BEGIN_SRC lisp :tangle /home/user/.local/share/passepartout/lisp/channel-tui-main.lisp
(defun send-daemon (msg)
(let ((s (st :stream)))
(when (and s (open-stream-p s))
@@ -766,7 +766,7 @@ Event handlers + daemon I/O + main loop.
#+END_SRC
** Connection
#+BEGIN_SRC lisp :tangle ../lisp/channel-tui-main.lisp
#+BEGIN_SRC lisp :tangle /home/user/.local/share/passepartout/lisp/channel-tui-main.lisp
(defun connect-daemon (&optional (host "127.0.0.1") (port 9105))
(add-msg :system "* Connecting to daemon... *")
(loop for attempt from 1 to 3
@@ -798,7 +798,7 @@ Event handlers + daemon I/O + main loop.
#+END_SRC
** Main Loop
#+BEGIN_SRC lisp :tangle ../lisp/channel-tui-main.lisp
#+BEGIN_SRC lisp :tangle /home/user/.local/share/passepartout/lisp/channel-tui-main.lisp
;; v0.8.0 — Global keymap
(eval-when (:load-toplevel :execute)
@@ -906,10 +906,18 @@ Event handlers + daemon I/O + main loop.
(format nil "* Swank ~d M-x slime-connect *" swank-port)))
(error ()
(add-msg :system "* Swank unavailable *"))))
(cl-tty.input:with-raw-terminal
(cl-tty.backend:with-terminal (be w h)
(let ((tty (sb-sys:make-fd-stream 0 :input t :buffering :none)))
;; Initial render
(cl-tty.backend:with-terminal (be w h)
;; Disable echo only — keep canonical mode (line input). stty raw
;; breaks read on fd 0 in this SBCL environment, but -echo alone
;; works. A cat subprocess inherits the terminal and provides
;; bytes through a pipe that SBCL reads reliably.
(uiop:run-program '("stty" "-echo") :output nil :ignore-error-status t)
(let* ((cat-proc (uiop:launch-program '("cat")
:output :stream
:input :interactive
:stderr nil))
(tty-in (uiop:process-info-output cat-proc)))
;; Log backend info and terminal dimensions
(cl-tty.backend:backend-clear be)
(view-status be w h)
(view-chat be w h)
@@ -926,34 +934,36 @@ Event handlers + daemon I/O + main loop.
(st :busy) nil)
(add-msg :system "* Connection lost — type /reconnect to retry *"))))
;; Check for terminal resize (SIGWINCH sets this flag)
;; Keyboard reader: block on cat pipe with 0.1s timeout.
(handler-case
(sb-ext:with-timeout 0.1
(let ((raw-ch (read-char tty-in nil nil)))
(when raw-ch
(let ((code (char-code raw-ch)))
(queue-event
(list :type :key
:payload (list :code code
:ch (cond
((= code 13) :enter)
((= code 10) :enter)
((= code 27) :escape)
((= code 9) :tab)
((or (= code 127) (= code 8)) :backspace)
((and (>= code 1) (<= code 26))
(intern
(string-upcase
(format nil "CTRL-~a"
(code-char (+ #x60 code))))
:keyword))
(t code)))))))))
(sb-ext:timeout ()))
;; Check for terminal resize (SIGWINCH sets this flag)
(when (boundp 'cl-tty.input::*terminal-resized-p*)
(when cl-tty.input::*terminal-resized-p*
(setf cl-tty.input::*terminal-resized-p* nil)
(multiple-value-setq (w h) (cl-tty.backend:backend-size be))
(setf (st :dirty) (list t t t))))
;; Read key input from fd 0 (blocking via listen + read-char)
(let ((raw-ch (when (listen tty) (read-char tty nil nil))))
(when raw-ch
(let ((code (char-code raw-ch)))
(let ((ch (cond
((= code 13) :enter)
((= code 10) :enter)
((= code 27) :escape)
((= code 9) :tab)
((or (= code 127) (= code 8)) :backspace)
((and (>= code 1) (<= code 26))
(intern (string-upcase (format nil "CTRL-~a"
(code-char (+ #x60 code))))
:keyword))
(t raw-ch))))
(case ch
(:CTRL-Q (setf (st :running) nil))
(:CTRL-P (command-palette-show-commands))
(:CTRL-B (setf (st :sidebar-visible) (not (st :sidebar-visible)))
(setf (st :dirty) (list t t nil)))
(:CTRL-L (setf (st :dirty) (list t t t)))
(t (on-key ch)))))))
(when (or (first (st :dirty)) (second (st :dirty)) (third (st :dirty)))
(when (or (first (st :dirty)) (second (st :dirty)) (third (st :dirty)))
(cl-tty.backend:backend-clear be)
(view-status be w h)
(view-chat be w h)
@@ -995,13 +1005,13 @@ Event handlers + daemon I/O + main loop.
(t (theme-color :agent-fg)))
nil :bold sel-p)
(incf y-off)))))))
(sleep 0.1))))
(close tty))
(disconnect-daemon)))
(sleep 0.1)))
(uiop:terminate-process cat-proc))
(progn (disconnect-daemon))))
#+END_SRC
* Test Suite
#+BEGIN_SRC lisp :tangle ../lisp/channel-tui-main.lisp
#+BEGIN_SRC lisp :tangle /home/user/.local/share/passepartout/lisp/channel-tui-main.lisp
(eval-when (:compile-toplevel :load-toplevel :execute)
(ql:quickload :fiveam :silent t))