Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 67 additions & 5 deletions ai-code-backends-infra.el
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@
(defvar vterm-shell)
(defvar vterm-environment)
(defvar vterm-kill-buffer-on-exit)
(defvar vterm-copy-mode)
(defvar eat-terminal)
(defvar eat--semi-char-mode)

;;; Customization

Expand Down Expand Up @@ -145,6 +148,12 @@ being sent for the response completion.")
(defvar-local ai-code-backends-infra--multiline-input-sequence nil
"Terminal sequence sent for multiline input in the current session buffer.")

(defvar-local ai-code-backends-infra--terminal-active-cursor-type nil
"Cursor type to restore when returning to terminal interaction mode.")

(defvar-local ai-code-backends-infra--navigation-cursor-active nil
"Non-nil when Emacs temporarily owns the cursor for output navigation.")

(defvar ai-code-cli-args-history nil
"History list for CLI args prompts.")

Expand Down Expand Up @@ -240,7 +249,9 @@ The timer is reset only after meaningful output is observed."
(defun ai-code-backends-infra--vterm-smart-renderer (orig-fun process input)
"Smart rendering filter for optimized vterm display updates.
Activity tracking for notifications is handled separately by
`ai-code-backends-infra--vterm-notification-tracker'."
`ai-code-backends-infra--vterm-notification-tracker'.
Deferred rendering is suspended while `vterm-copy-mode' is active so that
scrolling and copying are not disrupted by timer-driven redraws."
(if (or (not ai-code-backends-infra-vterm-anti-flicker)
(not (ai-code-backends-infra--session-buffer-p (process-buffer process))))
(funcall orig-fun process input)
Expand All @@ -253,7 +264,8 @@ Activity tracking for notifications is handled separately by
(escape-density (if (> input-length 0) (/ (float escape-count) input-length) 0)))
(if (or complex-redraw-detected
(and (> escape-density 0.3) (>= clear-count 2))
ai-code-backends-infra--vterm-render-queue)
ai-code-backends-infra--vterm-render-queue
(bound-and-true-p vterm-copy-mode))
(progn
(setq ai-code-backends-infra--vterm-render-queue
(concat ai-code-backends-infra--vterm-render-queue input))
Expand All @@ -264,15 +276,29 @@ Activity tracking for notifications is handled separately by
(lambda (buf)
(when (buffer-live-p buf)
(with-current-buffer buf
(when ai-code-backends-infra--vterm-render-queue
;; Clear timer reference regardless of whether we render.
(setq ai-code-backends-infra--vterm-render-timer nil)
(when (and ai-code-backends-infra--vterm-render-queue
(not (bound-and-true-p vterm-copy-mode)))
(let ((inhibit-redisplay t)
(data ai-code-backends-infra--vterm-render-queue))
(setq ai-code-backends-infra--vterm-render-queue nil
ai-code-backends-infra--vterm-render-timer nil)
(setq ai-code-backends-infra--vterm-render-queue nil)
(funcall orig-fun (get-buffer-process buf) data))))))
(current-buffer))))
(funcall orig-fun process input))))))

(defun ai-code-backends-infra--vterm-flush-on-copy-mode-exit ()
"Flush any pending render queue when exiting `vterm-copy-mode'.
Added buffer-locally to `vterm-copy-mode-hook' so that terminal output
queued while copy mode was active is rendered immediately when the user
returns to normal terminal interaction."
(unless (bound-and-true-p vterm-copy-mode)
(when ai-code-backends-infra--vterm-render-queue
(when-let ((proc (get-buffer-process (current-buffer))))
(let ((data ai-code-backends-infra--vterm-render-queue))
(setq ai-code-backends-infra--vterm-render-queue nil)
(vterm--filter proc data))))))

(defun ai-code-backends-infra--configure-vterm-buffer ()
"Configure vterm for enhanced performance."
(setq-local vterm-scroll-to-bottom-on-output nil)
Expand All @@ -289,6 +315,11 @@ Activity tracking for notifications is handled separately by
(set-process-query-on-exit-flag proc nil)
(when (fboundp 'process-put)
(process-put proc 'read-output-max 4096)))
;; Flush queued render output when the user exits vterm-copy-mode.
(add-hook 'vterm-copy-mode-hook
#'ai-code-backends-infra--vterm-flush-on-copy-mode-exit nil t)
;; Hand cursor ownership to Emacs while browsing frozen terminal output.
(ai-code-backends-infra--install-navigation-cursor-sync)
;; Install vterm filter advices globally (only once)
(unless ai-code-backends-infra--vterm-advices-installed
;; Always install notification tracker for session buffers
Expand Down Expand Up @@ -320,6 +351,36 @@ Activity tracking for notifications is handled separately by
(or ai-code-backends-infra--session-terminal-backend
ai-code-backends-infra-terminal-backend))

(defun ai-code-backends-infra--terminal-navigation-mode-p ()
"Return non-nil when the current terminal buffer is in navigation mode."
(pcase (ai-code-backends-infra--current-terminal-backend)
('vterm (bound-and-true-p vterm-copy-mode))
('eat (and (bound-and-true-p eat-terminal)
(or buffer-read-only
(not (bound-and-true-p eat--semi-char-mode)))))
(_ nil)))

(defun ai-code-backends-infra--sync-terminal-cursor ()
"Hand cursor ownership between the terminal and Emacs navigation modes."
(if (ai-code-backends-infra--terminal-navigation-mode-p)
(unless ai-code-backends-infra--navigation-cursor-active
(setq ai-code-backends-infra--terminal-active-cursor-type cursor-type
ai-code-backends-infra--navigation-cursor-active t
cursor-type t))
(when ai-code-backends-infra--navigation-cursor-active
(setq cursor-type ai-code-backends-infra--terminal-active-cursor-type
ai-code-backends-infra--navigation-cursor-active nil))))

(defun ai-code-backends-infra--install-navigation-cursor-sync ()
"Install buffer-local hooks for cursor handoff in terminal navigation modes."
(pcase (ai-code-backends-infra--current-terminal-backend)
('vterm
(add-hook 'vterm-copy-mode-hook
#'ai-code-backends-infra--sync-terminal-cursor nil t))
('eat
(add-hook 'post-command-hook
#'ai-code-backends-infra--sync-terminal-cursor nil t))))

(defun ai-code-backends-infra--terminal-dispatch (vterm-fn eat-fn)
"Run VTERM-FN or EAT-FN based on selected terminal backend."
(pcase (ai-code-backends-infra--current-terminal-backend)
Expand Down Expand Up @@ -925,6 +986,7 @@ ENV-VARS is a list of environment variables."
(local-set-key (kbd "@") #'ai-code--session-handle-at-input))
(when (fboundp 'ai-code--session-handle-hash-input)
(local-set-key (kbd "#") #'ai-code--session-handle-hash-input))
(ai-code-backends-infra--install-navigation-cursor-sync)
(setq-local process-environment (append env-vars process-environment))
(eat-exec buffer buffer-name program nil args)
;; Add process filter to track activity for notifications
Expand Down
Loading
Loading