[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[nongnu] elpa/spell-fu 484b6bdf04 53/86: Fix disabling spell-fu-mode sto
From: |
ELPA Syncer |
Subject: |
[nongnu] elpa/spell-fu 484b6bdf04 53/86: Fix disabling spell-fu-mode stopping the idle timer in other buffers |
Date: |
Thu, 7 Jul 2022 12:03:43 -0400 (EDT) |
branch: elpa/spell-fu
commit 484b6bdf0454898fc28e36f58db3432cad5e1071
Author: Campbell Barton <ideasman42@gmail.com>
Commit: Campbell Barton <ideasman42@gmail.com>
Fix disabling spell-fu-mode stopping the idle timer in other buffers
---
changelog.rst | 2 +
spell-fu.el | 122 +++++++++++++++++++++++++++++++++++++++++++++++++---------
2 files changed, 106 insertions(+), 18 deletions(-)
diff --git a/changelog.rst b/changelog.rst
index 07252c50cd..54c3e6ef4d 100644
--- a/changelog.rst
+++ b/changelog.rst
@@ -4,6 +4,8 @@ Change Log
##########
- In development.
+ - Idle timers now update buffers that have lost focus.
+ - Fix for disabling ``spell-fu-mode`` preventing other buffers that have
``spell-fu-mode`` enabled from updating.
- Changes to the face are now treated as word separators.
This fixes spell checking in situations where characters are escaped for
example ``"test\nterm"``,
diff --git a/spell-fu.el b/spell-fu.el
index 7b52c21dfa..467883e80a 100644
--- a/spell-fu.el
+++ b/spell-fu.el
@@ -702,8 +702,6 @@ Argument POINT-END the end position of WORD."
;; ---------------------------------------------------------------------------
;; Timer Style (spell-fu-idle-delay over zero)
-(defvar spell-fu--idle-timer nil)
-
(defun spell-fu--idle-remove-overlays (&optional point-start point-end)
"Remove `spell-fu-pending' overlays from current buffer.
If optional arguments POINT-START and POINT-END exist remove overlays from
@@ -759,8 +757,7 @@ when checking the entire buffer for example."
(defun spell-fu--idle-handle-pending-ranges ()
"Spell check the on-screen overlay ranges."
- (when (bound-and-true-p spell-fu-mode)
- (spell-fu--idle-handle-pending-ranges-impl (window-start) (window-end))))
+ (spell-fu--idle-handle-pending-ranges-impl (window-start) (window-end)))
(defun spell-fu--idle-font-lock-region-pending (point-start point-end)
"Track the range to spell check, adding POINT-START & POINT-END to the
queue."
@@ -770,17 +767,107 @@ when checking the entire buffer for example."
(overlay-put item-ov 'spell-fu-pending t)
(overlay-put item-ov 'evaporate 't)))
-(defun spell-fu--idle-timer-enable ()
- "Add the global idle timer."
- (unless spell-fu--idle-timer
- (setq spell-fu--idle-timer
- (run-with-idle-timer spell-fu-idle-delay t
#'spell-fu--idle-handle-pending-ranges))))
+;; ---------------------------------------------------------------------------
+;; Internal Timer Management
+;;
+;; This works as follows:
+;;
+;; - The timer is kept active as long as the local mode is enabled.
+;; - Entering a buffer runs the buffer local `window-state-change-hook'
+;; immediately which checks if the mode is enabled,
+;; set up the global timer if it is.
+;; - Switching any other buffer wont run this hook,
+;; rely on the idle timer it's self running, which detects the active mode,
+;; canceling it's self if the mode isn't active.
+;;
+;; This is a reliable way of using a global,
+;; repeating idle timer that is effectively buffer local.
+;;
+
+;; Global idle timer (repeating), keep active while the buffer-local mode is
enabled.
+(defvar spell-fu--global-timer nil)
+;; When t, the timer will update buffers in all other visible windows.
+(defvar spell-fu--dirty-flush-all nil)
+;; When true, the buffer should be updated when inactive.
+(defvar-local spell-fu--dirty nil)
+
+(defun spell-fu--time-callback-or-disable ()
+ "Callback that run the repeat timer."
-(defun spell-fu--idle-timer-disable ()
- "Remove the global idle timer."
- (when spell-fu--idle-timer
- (cancel-timer spell-fu--idle-timer)
- (setq spell-fu--idle-timer nil)))
+ ;; Ensure all other buffers are highlighted on request.
+ (let ((is-mode-active (bound-and-true-p spell-fu-mode)))
+ ;; When this buffer is not in the mode, flush all other buffers.
+ (cond
+ (is-mode-active
+ ;; Don't update in the window loop to ensure we always
+ ;; update the current buffer in the current context.
+ (setq spell-fu--dirty nil))
+ (t
+ ;; If the timer ran when in another buffer,
+ ;; a previous buffer may need a final refresh, ensure this happens.
+ (setq spell-fu--dirty-flush-all t)))
+
+ (when spell-fu--dirty-flush-all
+ ;; Run the mode callback for all other buffers in the queue.
+ (dolist (frame (frame-list))
+ (dolist (win (window-list frame -1))
+ (let ((buf (window-buffer win)))
+ (when
+ (and
+ (buffer-local-value 'spell-fu-mode buf)
+ (buffer-local-value 'spell-fu--dirty buf))
+ (with-selected-frame frame
+ (with-selected-window win
+ (with-current-buffer buf
+ (setq spell-fu--dirty nil)
+ (spell-fu--idle-handle-pending-ranges)))))))))
+ ;; Always keep the current buffer dirty
+ ;; so navigating away from this buffer will refresh it.
+ (when is-mode-active
+ (setq spell-fu--dirty t))
+
+ (cond
+ (is-mode-active
+ (spell-fu--idle-handle-pending-ranges))
+ (t ;; Cancel the timer until the current buffer uses this mode again.
+ (spell-fu--time-ensure nil)))))
+
+(defun spell-fu--time-ensure (state)
+ "Ensure the timer is enabled when STATE is non-nil, otherwise disable."
+ (cond
+ (state
+ (unless spell-fu--global-timer
+ (setq spell-fu--global-timer
+ (run-with-idle-timer spell-fu-idle-delay :repeat
'spell-fu--time-callback-or-disable))))
+ (t
+ (when spell-fu--global-timer
+ (cancel-timer spell-fu--global-timer)
+ (setq spell-fu--global-timer nil)))))
+
+(defun spell-fu--time-reset ()
+ "Run this when the buffer changes."
+ ;; Ensure changing windows doesn't leave other buffers with stale highlight.
+ (cond
+ ((bound-and-true-p spell-fu-mode)
+ (setq spell-fu--dirty-flush-all t)
+ (setq spell-fu--dirty t)
+ (spell-fu--time-ensure t))
+ (t
+ (spell-fu--time-ensure nil))))
+
+(defun spell-fu--time-buffer-local-enable ()
+ "Ensure buffer local state is enabled."
+ ;; Needed in case focus changes before the idle timer runs.
+ (setq spell-fu--dirty-flush-all t)
+ (setq spell-fu--dirty t)
+ (spell-fu--time-ensure t)
+ (add-hook 'window-state-change-hook #'spell-fu--time-reset nil t))
+
+(defun spell-fu--time-buffer-local-disable ()
+ "Ensure buffer local state is disabled."
+ (kill-local-variable 'spell-fu--dirty)
+ (spell-fu--time-ensure nil)
+ (remove-hook 'window-state-change-hook #'spell-fu--time-reset t))
(defun spell-fu--idle-enable ()
"Enable the idle style of updating."
@@ -790,15 +877,14 @@ when checking the entire buffer for example."
;; running before font-faces have been set.
(spell-fu--with-add-hook-depth-override 100
(jit-lock-register #'spell-fu--idle-font-lock-region-pending))
- (spell-fu--idle-timer-enable))
+ (spell-fu--time-buffer-local-enable))
(defun spell-fu--idle-disable ()
"Disable the idle style of updating."
(jit-lock-unregister #'spell-fu--idle-font-lock-region-pending)
(spell-fu--remove-overlays)
- (spell-fu--idle-timer-disable)
- (spell-fu--idle-remove-overlays))
-
+ (spell-fu--idle-remove-overlays)
+ (spell-fu--time-buffer-local-disable))
;; ---------------------------------------------------------------------------
;; Public Functions
- [nongnu] elpa/spell-fu 41a133d119 52/86: Fix #16: Fails to spellcheck when whitespace-mode splits a word, (continued)
- [nongnu] elpa/spell-fu 41a133d119 52/86: Fix #16: Fails to spellcheck when whitespace-mode splits a word, ELPA Syncer, 2022/07/07
- [nongnu] elpa/spell-fu 7c2542e109 73/86: Merge branch 'multiple-dictionaries' into 'master', ELPA Syncer, 2022/07/07
- [nongnu] elpa/spell-fu 50be652a6e 77/86: Fix overlay faces masking other faces (when checking faces-at-point), ELPA Syncer, 2022/07/07
- [nongnu] elpa/spell-fu cbe5cd84c3 86/86: Correct URL, ELPA Syncer, 2022/07/07
- [nongnu] elpa/spell-fu 41a7ebcbab 23/86: Cleanup: replace cl-letf with advice macro, ELPA Syncer, 2022/07/07
- [nongnu] elpa/spell-fu 251e63eacc 29/86: readme: update, clarify TODO, ELPA Syncer, 2022/07/07
- [nongnu] elpa/spell-fu ad139f6fac 40/86: Cleanup: quiet checkdoc warning, ELPA Syncer, 2022/07/07
- [nongnu] elpa/spell-fu 2caa9fc6f0 44/86: Update changelog, ELPA Syncer, 2022/07/07
- [nongnu] elpa/spell-fu f38bebefea 62/86: Cleanup: replace 'if' with 'cond', ELPA Syncer, 2022/07/07
- [nongnu] elpa/spell-fu 9587fa4b99 17/86: Add missing args (quiet checkdoc warnings), ELPA Syncer, 2022/07/07
- [nongnu] elpa/spell-fu 484b6bdf04 53/86: Fix disabling spell-fu-mode stopping the idle timer in other buffers,
ELPA Syncer <=
- [nongnu] elpa/spell-fu 3230ff96f1 65/86: Cleanup: modified word ordering, ELPA Syncer, 2022/07/07
- [nongnu] elpa/spell-fu 96f72c35b1 38/86: Update spell-fu.el, correct package url., ELPA Syncer, 2022/07/07
- [nongnu] elpa/spell-fu ac9c1581c8 45/86: readme: move details into top level section, ELPA Syncer, 2022/07/07
- [nongnu] elpa/spell-fu 646f40ba06 54/86: Cleanup: use 'when' instead of 'if', ELPA Syncer, 2022/07/07
- [nongnu] elpa/spell-fu d4e3deedee 56/86: Have a better excludes list for org-mode. In particular `org-src`., ELPA Syncer, 2022/07/07
- [nongnu] elpa/spell-fu 4e7ad5c5ef 61/86: Cleanup: docstrings, ELPA Syncer, 2022/07/07
- [nongnu] elpa/spell-fu a17b2f90ae 70/86: Re-order definitions, ELPA Syncer, 2022/07/07
- [nongnu] elpa/spell-fu e7cfe54d4e 75/86: changelog: note that multiple dictionaries are now supported, ELPA Syncer, 2022/07/07
- [nongnu] elpa/spell-fu e94d01cdc8 35/86: Fix for attempting to use wave style in the terminal, ELPA Syncer, 2022/07/07
- [nongnu] elpa/spell-fu 8185467b24 82/86: Cleanup: remove redundant 'format', ELPA Syncer, 2022/07/07