diff --git a/org/channel-tui-main.org b/org/channel-tui-main.org index d69a3a6..c41c28a 100644 --- a/org/channel-tui-main.org +++ b/org/channel-tui-main.org @@ -1067,7 +1067,10 @@ Returns T on success, nil on failure. Does NOT wait or retry." (format nil "> ~a" (or filter "")) (theme-color :input-prompt) bg-p)) (cl-tty.backend:end-sync be)) - (sleep 0.1))) + (sleep 0.1) + ;; Show terminal cursor at input position every frame + (unless (st :dialog-stack) + (passepartout.channel-tui:position-cursor be w h)))) (progn (disconnect-daemon))))) #+END_SRC diff --git a/org/channel-tui-state.org b/org/channel-tui-state.org index a5a3585..5642452 100644 --- a/org/channel-tui-state.org +++ b/org/channel-tui-state.org @@ -23,6 +23,7 @@ All state mutation flows through event handlers in the controller. (:export :tui-main :st :add-msg :now :input-string :queue-event :drain-queue :init-state :view-status :view-chat :view-input :redraw + :position-cursor :input-panel-top :on-key :on-daemon-msg :send-daemon :connect-daemon :disconnect-daemon diff --git a/org/channel-tui-view.org b/org/channel-tui-view.org index a4bcb07..367f47d 100644 --- a/org/channel-tui-view.org +++ b/org/channel-tui-view.org @@ -326,6 +326,22 @@ Returns a list of strings, one per line." (view-sidebar fb w h)) (cl-tty.backend:end-sync fb) (setf (st :dirty) (list nil nil nil)))) + +(defun position-cursor (fb w h) + "Position terminal cursor at the input insertion point. +Terminal handles the blinking — we just set position and style once per frame." + (let* ((sw (if (sidebar-visible-p w) (or (st :sidebar-width) 42) 0)) + (cw (- w sw)) + (hpad 2) + (text (input-string)) + (pos (or (st :cursor-pos) 0)) + (prompt-w (- cw (* 2 hpad) 2)) + (display-start (max 0 (- pos (1- prompt-w)))) + (cx (+ hpad 2 (- pos display-start))) + (cy (- h 6))) + (cl-tty.backend:cursor-move fb cx cy) + (cl-tty.backend:cursor-style fb :block :blink t) + (cl-tty.backend:cursor-show fb))) #+END_SRC * Implementation — v0.7.0 additions