From: Stefan Monnier Date: Fri, 3 May 2024 17:23:00 +0000 (-0400) Subject: track-changes.el: Add a workaround for bug#70541 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=8c41ad56b10e52362de4b5fa278828601f7ccfbc;p=emacs.git 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. (cherry picked from commit b6d4e81a487ce40f5ea6520c53a88a1c2e7359a9) --- 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 592dc4a768e..406e7cf91a2 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el @@ -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.