Add --verbose flag for TUI event logging to ~/jcode.log
ober
0ebb7a856596924e1a263c0cd9f762c9aa70b660
--- a/src/jcode/ui/cli.ss +++ b/src/jcode/ui/cli.ss @@ -68,6 +68,7 @@ ((equal? (car args) "-d") (loop (cdr args) (cons '(--debug . #t) opts))) ((equal? (car args) "--tui") (loop (cdr args) (cons '(--tui . #t) opts))) ((equal? (car args) "--no-tui") (loop (cdr args) (cons '(--no-tui . #t) opts))) + ((equal? (car args) "--verbose") (loop (cdr args) (cons '(--verbose . #t) opts))) ((and (equal? (car args) "--model") (pair? (cdr args))) (loop (cddr args) (cons (cons '--model (cadr args)) opts))) ((and (equal? (car args) "-m") (pair? (cdr args))) @@ -104,6 +105,7 @@ OPTIONS: -p, --provider Provider to use (default: anthropic) --tui Launch terminal UI mode --no-tui Force line-mode REPL (default) + --verbose Log TUI events to ~/jcode.log COMMANDS: session list List all sessions --- a/src/jcode/ui/tui.ss +++ b/src/jcode/ui/tui.ss @@ -32,6 +32,35 @@ (def logger (make-logger "tui")) (def *version* "0.1.0") +;; ---- TUI verbose logging ---- +;; When --verbose is passed, logs to ~/jcode.log for debugging input/events. + +(def *tui-log-port* (make-parameter #f)) + +(def (tui-log fmt . args) + (let ((p (*tui-log-port*))) + (when p + (let ((msg (apply format fmt args))) + (display msg p) + (newline p) + (flush-output-port p))))) + +(def (open-tui-log!) + (let ((p (open-file-output-port + (string-append (getenv "HOME") "/jcode.log") + (file-options no-fail) + (buffer-mode line) + (make-transcoder (utf-8-codec))))) + (*tui-log-port* p) + (tui-log "---- jcode TUI log started ----"))) + +(def (close-tui-log!) + (let ((p (*tui-log-port*))) + (when p + (tui-log "---- jcode TUI log ended ----") + (close-port p) + (*tui-log-port* #f)))) + ;; ---- Spinner animation ---- (def *spinner-frames* '#("⠋" "⠙" "⠹" "⠸" "⠼" "⠴" "⠦" "⠧" "⠇" "⠏")) @@ -107,14 +136,20 @@ (session-init-db) (init-tools-for-tui) (apply-tui-overrides! args) + (when (member "--verbose" args) (open-tui-log!)) + (tui-log "tui-main: starting, args=~a" args) (with-tui - (tb-set-input-mode! (bitwise-ior TB_INPUT_ALT TB_INPUT_MOUSE)) - (tb-set-output-mode! TB_OUTPUT_TRUECOLOR) + (tui-log "tui-main: tb-init done") + (let ((in-mode (bitwise-ior TB_INPUT_ALT TB_INPUT_MOUSE))) + (tui-log "tui-main: setting input-mode=~a output-mode=~a" in-mode TB_OUTPUT_TRUECOLOR) + (tb-set-input-mode! in-mode) + (tb-set-output-mode! TB_OUTPUT_TRUECOLOR)) (set-theme! theme-dark) (let* ((w (tb-width)) (h (tb-height)) (state (make-fresh-state w h)) (session (session-create "New session"))) + (tui-log "tui-main: terminal ~ax~a, session=~a" w h (session-id session)) (app-state-session-id-set! state (session-id session)) ;; Welcome message (app-state-messages-set! state @@ -122,7 +157,9 @@ (reflow-all! state) (draw-all! state) (tb-present!) - (event-loop state)))) + (tui-log "tui-main: entering event loop") + (event-loop state) + (close-tui-log!)))) (def (init-tools-for-tui) ;; Import and init tools — same as cli.ss @@ -154,6 +191,8 @@ ((or (equal? (car args) "--debug") (equal? (car args) "-d")) (current-log-level 'debug) (loop (cdr args))) + ((equal? (car args) "--verbose") + (loop (cdr args))) ;; handled in tui-main before this (#t (loop (cdr args)))))) ;; ---- Event loop ---- @@ -170,12 +209,22 @@ ;; Poll for terminal events (50ms timeout) (let ((ev (tb-peek-event 50))) (when ev + (tui-log "event: type=~a key=~a ch=~a(~a) mod=~a w=~a h=~a" + (tui-event-type ev) (tui-event-key ev) + (tui-event-ch ev) + (if (> (tui-event-ch ev) 31) + (string (integer->char (tui-event-ch ev))) + "") + (tui-event-mod ev) + (tui-event-w ev) (tui-event-h ev)) (cond ((tui-event-resize? ev) + (tui-log " -> resize ~ax~a" (tui-event-w ev) (tui-event-h ev)) (handle-resize! state ev)) ((tui-event-key? ev) (handle-key! state ev)) ((tui-event-mouse? ev) + (tui-log " -> mouse key=~a x=~a y=~a" (tui-event-key ev) (tui-event-x ev) (tui-event-y ev)) (handle-mouse! state ev))))) ;; Redraw if dirty @@ -201,43 +250,59 @@ (def (handle-key! state ev) (let ((key (tui-event-key ev)) + (ch (tui-event-ch ev)) (mod (tui-event-mod ev))) + (tui-log " handle-key: key=~a ch=~a(~a) mod=~a busy?=~a" + key ch + (if (> ch 31) (string (integer->char ch)) "") + mod (app-state-agent-busy? state)) (cond ;; Global: Ctrl-B toggle sidebar ((= key TB_KEY_CTRL_B) + (tui-log " -> toggle-sidebar") (app-state-sidebar-visible?-set! state (not (app-state-sidebar-visible? state))) (reflow-all! state) (app-state-dirty?-set! state #t)) ;; Global: Ctrl-L redraw ((= key TB_KEY_CTRL_L) + (tui-log " -> redraw") (tb-clear!) (app-state-dirty?-set! state #t)) ;; Global: Ctrl-T cycle theme ((= key TB_KEY_CTRL_T) + (tui-log " -> cycle-theme") (cycle-theme!) (app-state-dirty?-set! state #t)) ;; Global: Page-up/down scroll ((= key TB_KEY_PGUP) + (tui-log " -> page-up") (app-state-scroll-offset-set! state (+ (app-state-scroll-offset state) (quotient (msg-area-height state) 2))) (app-state-dirty?-set! state #t)) ((= key TB_KEY_PGDN) + (tui-log " -> page-down") (app-state-scroll-offset-set! state (max 0 (- (app-state-scroll-offset state) (quotient (msg-area-height state) 2)))) (app-state-dirty?-set! state #t)) - ;; Ctrl-C during agent: cancel (TODO: actually cancel the agent) + ;; Ctrl-C during agent: cancel ((and (= key TB_KEY_CTRL_C) (app-state-agent-busy? state)) + (tui-log " -> cancel-agent") (app-state-agent-busy?-set! state #f) (app-state-dirty?-set! state #t)) ;; Input handling (#t - (unless (app-state-agent-busy? state) + (if (app-state-agent-busy? state) + (tui-log " -> ignored (agent busy)") (let ((action (input-handle-key! (app-state-input state) ev))) + (tui-log " -> input action=~a text=~s cursor=~a" + action + (input-state-text (app-state-input state)) + (input-state-cursor-pos (app-state-input state))) (case action ((submit) (handle-submit! state)) ((quit) (app-state-quit?-set! state #t)) @@ -265,13 +330,16 @@ (def (handle-submit! state) (let* ((inp (app-state-input state)) (text (input-submit! inp))) + (tui-log "submit: text=~s" text) (unless (string-empty? text) (cond ;; Slash command ((char=? (string-ref text 0) #\/) + (tui-log "submit: slash-command ~s" text) (handle-slash-command! state text)) ;; Normal message → agent (#t + (tui-log "submit: sending to agent") ;; Add user message (add-message! state (msg-block-user text)) ;; Auto-scroll to bottom