From ab479f9c2722dbe3f9639b6b4f3a99e1f5bb6092 Mon Sep 17 00:00:00 2001 From: Akib Azmain Turja Date: Tue, 17 Oct 2023 19:50:30 +0600 Subject: [PATCH] Fix input processing & auto line mode * eat.el (eat--process-input-queue): Set 'eat--process-input-queue-timer' to 'nil'. * eat.el (eat--auto-line-mode-pending-toggles): New variable. * eat.el (eat--line-mode-enter-auto-1): Don't take any argument. * eat.el (eat--line-mode-exit-auto-1): Don't take any argument. Don't call 'eat-line-mode'. * eat.el (eat--line-mode-enter-auto, eat--line-mode-exit-auto): Queue the toggle in 'eat--auto-line-mode-pending-toggles' instead of starting a timer. * eat.el (eat--line-mode-do-toggles): New function. * eat.el (eat--process-output-queue): Let-bind 'eat--auto-line-mode-pending-toggles' to nil. Call 'eat--line-mode-do-toggles'. --- eat.el | 101 +++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 63 insertions(+), 38 deletions(-) diff --git a/eat.el b/eat.el index 660b377..bd0ac27 100644 --- a/eat.el +++ b/eat.el @@ -5002,6 +5002,11 @@ return \"eat-color\", otherwise return \"eat-mono\"." (defvar eat--auto-line-mode-prev-mode nil "The input mode active before line mode.") +(defvar eat--auto-line-mode-pending-toggles nil + "Automatic line mode toggles left to do. + +Don't change the toplevel value of this, let-bind instead.") + (defun eat-reset () "Perform a terminal reset." (interactive) @@ -5147,47 +5152,64 @@ If HOST isn't the host Emacs is running on, don't do anything." (defvar eat--semi-char-mode) (defvar eat--char-mode) -(defun eat--line-mode-enter-auto-1 (buffer) - "Enter line mode in BUFFER." - (with-current-buffer buffer - (unless (or eat--inhibit-auto-line-mode eat--line-mode) - (unless eat--line-mode - (setq eat--auto-line-mode-prev-mode - (cond (eat--semi-char-mode 'semi-char) - (eat--char-mode 'char) - (t 'emacs))) - (eat-line-mode) - ;; We're entering automatically, so we should be able to exit it - ;; automatically. - (setq eat--inhibit-auto-line-mode nil))))) +(defun eat--line-mode-enter-auto-1 () + "Enter line mode." + (unless (or eat--inhibit-auto-line-mode eat--line-mode) + (unless eat--line-mode + (setq eat--auto-line-mode-prev-mode + (cond (eat--semi-char-mode 'semi-char) + (eat--char-mode 'char) + (t 'emacs))) + (eat-line-mode) + ;; We're entering automatically, so we should be able to exit it + ;; automatically. + (setq eat--inhibit-auto-line-mode nil)))) (defun eat--line-mode-enter-auto () - "Enter line mode." - (run-with-idle-timer 0 nil #'eat--line-mode-enter-auto-1 - (current-buffer))) + "Arrange that line mode will be enabled eventually." + (push 'enter eat--auto-line-mode-pending-toggles)) -(defun eat--line-mode-exit-auto-1 (buffer) - "Exit line mode in BUFFER." - (with-current-buffer buffer - (when (and (not eat--inhibit-auto-line-mode) - eat--auto-line-mode-prev-mode) - (pcase eat--auto-line-mode-prev-mode - ('emacs (eat-emacs-mode)) - ('semi-char (eat-semi-char-mode)) - ('char (eat-char-mode))) - (setq eat--auto-line-mode-prev-mode nil) - (when (/= (eat-term-end eat-terminal) (point-max)) - (eat-line-send)) - ;; Toggle line mode _after_ we exit from - ;; `eat-term-process-output'. - (run-with-idle-timer 0 nil #'eat-line-mode) - (eat--line-mode -1) - (setq buffer-undo-list nil)))) +(defun eat--line-mode-exit-auto-1 () + "Exit line mode." + (when (and (not eat--inhibit-auto-line-mode) + eat--auto-line-mode-prev-mode) + (pcase eat--auto-line-mode-prev-mode + ('emacs (eat-emacs-mode)) + ('semi-char (eat-semi-char-mode)) + ('char (eat-char-mode))) + (setq eat--auto-line-mode-prev-mode nil) + (when (/= (eat-term-end eat-terminal) (point-max)) + (eat-line-send)) + ;; Toggle line mode _after_ we exit from + ;; `eat-term-process-output'. + (eat--line-mode -1) + (setq buffer-undo-list nil))) (defun eat--line-mode-exit-auto () - "Exit line mode." - (run-with-idle-timer 0 nil #'eat--line-mode-exit-auto-1 - (current-buffer))) + "Arrange that line mode will be disabled eventually." + (push 'exit eat--auto-line-mode-pending-toggles)) + +(defun eat--line-mode-do-toggles () + "Do the pending line mode toggle." + (let* ((inhibit-quit t) + (actions (nreverse eat--auto-line-mode-pending-toggles)) + (toggle nil)) + (while (setq toggle (pop actions)) + (pcase-exhaustive toggle + ('enter (eat--line-mode-enter-auto-1)) + ('exit (eat--line-mode-exit-auto-1))) + ;; Don't do extra unnecessary toggles. + (let ((loop t)) + (while loop + (setq loop nil) + (while (eq toggle (car actions)) + (pop actions)) + (while (and (car actions) (cadr actions) + (not (eq (car actions) (cadr actions)))) + (pop actions) + (pop actions) + (setq loop t))))) + (setq eat--auto-line-mode-pending-toggles nil))) (defun eat--post-prompt () "Put a mark in the marginal area and enter line mode." @@ -6772,14 +6794,16 @@ OS's." (dolist (str chunks) (eat--send-string proc str))))))) (when eat--process-input-queue-timer - (cancel-timer eat--process-input-queue-timer))))) + (cancel-timer eat--process-input-queue-timer)) + (setq eat--process-input-queue-timer nil)))) (defun eat--process-output-queue (buffer) "Process the output queue on BUFFER." (when (buffer-live-p buffer) (with-current-buffer buffer (let ((inhibit-quit t) ; Don't disturb! - (sync-windows (eat--synchronize-scroll-windows))) + (sync-windows (eat--synchronize-scroll-windows)) + (eat--auto-line-mode-pending-toggles nil)) (save-restriction (widen) (let ((inhibit-read-only t) @@ -6814,6 +6838,7 @@ OS's." `( read-only t field eat-terminal ,@(when eat--line-mode '(front-sticky t rear-nonsticky t)))))) + (eat--line-mode-do-toggles) (funcall eat--synchronize-scroll-function sync-windows)) (run-hooks 'eat-update-hook))))