[Top][All Lists]

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

Patch to avoid flicker in Isearch with lazy count

From: Augusto Stoffel
Subject: Patch to avoid flicker in Isearch with lazy count
Date: Wed, 27 Jan 2021 16:41:28 +0100
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/27.1 (gnu/linux)

Setting ‘lazy-highlight-initial-delay’ to 0 (which should be a
reasonable default on a modern machine) causes some flickering in the
search buffer, and a lot of flickering in the echo are when
‘isearch-lazy-count’ is on.

The attached patch addresses these problems.  It also makes the
desired effect of setting ‘lazy-highlight-initial-delay’ to 0 the
default, even though that variable is unchanged.

Flicker in the search buffer happens because the highlighting of
matches happens after typing just one letter, and there are
potentially many of those.  It is fixed by adding a new variable,
‘lazy-highlight-delay-max-chars’.  Lazy highlighting kicks in
immediately if the search string is longer than that number.  I set
the default value to 2, but maybe 1 is even better.

Flicker in the echo area happens even with the default value of
‘lazy-highlight-initial-delay’, if less pronouncedly, and is due to
too frequent updates to the echo area message.  This is solved by
keeping the lazy count in the echo area of out of date for the
fraction of a second where the lazy stuff is waiting to kick in.

Please let me know if this works well and can be merged.


>From aaef7a6438aaa74a5978e5e9d4b5e95910c2b15e Mon Sep 17 00:00:00 2001
From: Augusto Stoffel <arstoffel@gmail.com>
Date: Wed, 27 Jan 2021 16:09:38 +0100
Subject: [PATCH] Reduce flicker in Isearch mode

Lazy highlighting now happens immediately (only) if the search string
is longer than the value of the new custom variable
`lazy-highlight-delay-max-chars`.  Also avoid updating the lazy count
in the echo area too often.
* isearch.el (lazy-highlight-delay-max-chars): new defcustom
* isearch.el (isearch-lazy-highlight-with-timer): new function,
factors out a repeated snippet of code.
* isearch.el (isearch-lazy-highlight-new-loop,
isearch-lazy-highlight-update, isearch-lazy-highlight-buffer-update):
use the new `isearch-lazy-highlight-with-timer` function.
* isearch.el (isearch-lazy-highlight-new-loop): avoid a call to
`isearch-message` that is quickly succeed by a second echo area
update, thus causing flicker.
 lisp/isearch.el | 48 ++++++++++++++++++++++++++++++++----------------
 1 file changed, 32 insertions(+), 16 deletions(-)

diff --git a/lisp/isearch.el b/lisp/isearch.el
index a86678572c..ca0fd1434a 100644
--- a/lisp/isearch.el
+++ b/lisp/isearch.el
@@ -352,12 +352,22 @@ lazy-highlight-cleanup
   :group 'lazy-highlight)
 (defcustom lazy-highlight-initial-delay 0.25
-  "Seconds to wait before beginning to lazily highlight all matches."
+  "Seconds to wait before beginning to lazily highlight all matches.
+This setting only has effect if the current search string is at most
+`lazy-highlight-initial-delay' character long."
   :type 'number
   :group 'lazy-highlight)
+(defcustom lazy-highlight-delay-max-chars 2
+  "Size of a search string above which lazy highlight happens immediately."
+  :type 'number
+  :group 'lazy-highlight
+  :version "28.1")
 (defcustom lazy-highlight-interval 0 ; 0.0625
-  "Seconds between lazily highlighting successive matches."
+  "Seconds between lazily highlighting successive matches.
+This setting only has effect if the current search string is at most
+`lazy-highlight-initial-delay' character long."
   :type 'number
   :group 'lazy-highlight)
@@ -3357,7 +3367,7 @@ isearch-lazy-count-format
              (not isearch-error)
              (not isearch-suspended))
         (format format-string
-                (if isearch-forward
+                (if isearch-lazy-highlight-forward
                   (if (eq isearch-lazy-count-current 0)
@@ -3858,6 +3868,15 @@ lazy-highlight-cleanup
     (cancel-timer isearch-lazy-highlight-timer)
     (setq isearch-lazy-highlight-timer nil)))
+(defun isearch-lazy-highlight-with-timer (delay function)
+  "Arrange for FUNCTION to be called in idle time, possibly with DELAY.
+There is no delay if the current search string is longer than
+  (setq isearch-lazy-highlight-timer
+        (run-with-idle-timer
+         (if (> (length isearch-string) lazy-highlight-delay-max-chars) 0 
+         nil function)))
 (defun isearch-lazy-highlight-new-loop (&optional beg end)
   "Cleanup any previous `lazy-highlight' loop and begin a new one.
 BEG and END specify the bounds within which highlighting should occur.
@@ -3917,7 +3936,8 @@ isearch-lazy-highlight-new-loop
         (clrhash isearch-lazy-count-hash)
         (setq isearch-lazy-count-current nil
               isearch-lazy-count-total nil)
-        (isearch-message)))
+        ;; Delay updating the message if possible, to avoid flicker
+        (when (string-equal isearch-string "") (isearch-message))))
     (setq isearch-lazy-highlight-window-start-changed nil)
     (setq isearch-lazy-highlight-window-end-changed nil)
     (setq isearch-lazy-highlight-error isearch-error)
@@ -3961,9 +3981,8 @@ isearch-lazy-highlight-new-loop
                    (1- (length isearch-lazy-highlight-last-string)))
     (unless (equal isearch-string "")
-      (setq isearch-lazy-highlight-timer
-            (run-with-idle-timer lazy-highlight-initial-delay nil
-                                 'isearch-lazy-highlight-start))))
+      (isearch-lazy-highlight-with-timer lazy-highlight-initial-delay
+                                         'isearch-lazy-highlight-start)))
   ;; Update the current match number only in isearch-mode and
   ;; unless isearch-mode is used specially with isearch-message-function
   (when (and isearch-lazy-count isearch-mode (null isearch-message-function))
@@ -4101,12 +4120,10 @@ isearch-lazy-highlight-update
                  (if isearch-lazy-highlight-forward
                      (setq isearch-lazy-highlight-end (point-min))
                    (setq isearch-lazy-highlight-start (point-max)))
-                 (setq isearch-lazy-highlight-timer
-                       (run-at-time lazy-highlight-interval nil
-                                    'isearch-lazy-highlight-buffer-update)))
-             (setq isearch-lazy-highlight-timer
-                   (run-at-time lazy-highlight-interval nil
-                                'isearch-lazy-highlight-update)))))))))
+                 (isearch-lazy-highlight-with-timer
+                  lazy-highlight-interval 
+             (isearch-lazy-highlight-with-timer
+               lazy-highlight-interval 'isearch-lazy-highlight-update))))))))
 (defun isearch-lazy-highlight-buffer-update ()
   "Update highlighting of other matches in the full buffer."
@@ -4180,9 +4197,8 @@ isearch-lazy-highlight-buffer-update
                  (setq isearch-lazy-count-current
                        (gethash opoint isearch-lazy-count-hash 0))
-             (setq isearch-lazy-highlight-timer
-                   (run-at-time lazy-highlight-interval nil
-                                'isearch-lazy-highlight-buffer-update)))))))))
+             (isearch-lazy-highlight-with-timer
+              lazy-highlight-interval 
 (defun isearch-resume (string regexp word forward message case-fold)
   "Resume an incremental search.

reply via email to

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