]> git.eshelyaron.com Git - emacs.git/commitdiff
track-changes.el: Add a workaround for bug#70541
authorStefan Monnier <monnier@iro.umontreal.ca>
Fri, 3 May 2024 17:23:00 +0000 (13:23 -0400)
committerEshel Yaron <me@eshelyaron.com>
Mon, 6 May 2024 16:37:45 +0000 (18:37 +0200)
* lisp/emacs-lisp/track-changes.el (track-changes-inconsistent-state-p):
 New function.
* lisp/progmodes/eglot.el (eglot--track-changes-signal): Use it.

(cherry picked from commit b6d4e81a487ce40f5ea6520c53a88a1c2e7359a9)

lisp/emacs-lisp/track-changes.el
lisp/progmodes/eglot.el

index ac7a99f3c3cbdccb2317220067c882143b506e01..368e637387c42d011ee537eed4a2421f4706ffb9 100644 (file)
@@ -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 ()
index 592dc4a768e62eac177eab03a8f0742022b970cc..406e7cf91a2fba646f7777693c1419b5074609ad 100644 (file)
@@ -2695,14 +2695,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.