emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

master b6d4e81a487: track-changes.el: Add a workaround for bug#70541


From: Stefan Monnier
Subject: master b6d4e81a487: track-changes.el: Add a workaround for bug#70541
Date: Fri, 3 May 2024 13:23:11 -0400 (EDT)

branch: master
commit b6d4e81a487ce40f5ea6520c53a88a1c2e7359a9
Author: Stefan Monnier <monnier@iro.umontreal.ca>
Commit: Stefan Monnier <monnier@iro.umontreal.ca>

    track-changes.el: Add a workaround for bug#70541
    
    * lisp/emacs-lisp/track-changes.el (track-changes-inconsistent-state-p):
     New function.
    * lisp/progmodes/eglot.el (eglot--track-changes-signal): Use it.
---
 lisp/emacs-lisp/track-changes.el | 11 +++++++++++
 lisp/progmodes/eglot.el          | 28 ++++++++++++++++++++--------
 2 files changed, 31 insertions(+), 8 deletions(-)

diff --git a/lisp/emacs-lisp/track-changes.el b/lisp/emacs-lisp/track-changes.el
index ac7a99f3c3c..368e637387c 100644
--- a/lisp/emacs-lisp/track-changes.el
+++ b/lisp/emacs-lisp/track-changes.el
@@ -367,6 +367,17 @@ and re-enable the TRACKER corresponding to ID."
       ;; as to avoid nested invocations.
       (cl-pushnew id track-changes--clean-trackers))))
 
+(defun track-changes-inconsistent-state-p ()
+  "Return whether the current buffer is in an inconsistent state.
+Ideally `before/after-change-functions' should be called for each and every
+buffer change, but some packages make transient changes without
+running those hooks.
+This function tries to detect those situations so clients can decide
+to postpone their work to a later time when the buffer is hopefully
+returned to a consistent state."
+  (or (equal track-changes--buffer-size (buffer-size))
+      inhibit-modification-hooks))
+
 ;;;; Auxiliary functions.
 
 (defun track-changes--clean-state ()
diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el
index 407707d4122..c210de39c65 100644
--- a/lisp/progmodes/eglot.el
+++ b/lisp/progmodes/eglot.el
@@ -2694,14 +2694,26 @@ Records BEG, END and PRE-CHANGE-LENGTH locally."
    ;; who check it as a boolean.
    (t (setq eglot--recent-changes :pending)))
   (when eglot--change-idle-timer (cancel-timer eglot--change-idle-timer))
-  (let ((buf (current-buffer)))
-    (setq eglot--change-idle-timer
-          (run-with-idle-timer
-           eglot-send-changes-idle-time
-           nil (lambda () (eglot--when-live-buffer buf
-                            (when eglot--managed-mode
-                              (run-hooks 'eglot--document-changed-hook)
-                              (setq eglot--change-idle-timer nil))))))))
+  (setq eglot--change-idle-timer
+        (run-with-idle-timer
+         eglot-send-changes-idle-time nil
+         (lambda (buf)
+           (eglot--when-live-buffer buf
+             (when eglot--managed-mode
+               (if (and (fboundp 'track-changes-inconsistent-state-p)
+                        (track-changes-inconsistent-state-p))
+                   ;; Not a good time (e.g. in the middle of Quail
+                   ;; thingy, bug#70541), let's reschedule.
+                   ;; Ideally, we'd `run-with-idle-timer' to call
+                   ;; ourselves again but it's kind of a pain to do that
+                   ;; right (because we first have to wait for the
+                   ;; current idle period to end), so we just do
+                   ;; nothing and wait for the next buffer change to
+                   ;; reschedule us.
+                   nil
+                 (run-hooks 'eglot--document-changed-hook)
+                 (setq eglot--change-idle-timer nil))))
+           (current-buffer)))))
 
 (defvar-local eglot-workspace-configuration ()
   "Configure LSP servers specifically for a given project.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]