Subject: Re: bug#29321: Isearch hit count

From: Juri Linkov <[email-masked]>
Date: Mon, 29 Oct 2018 00:38:56 +0200

> First, when I hit `C-s ea' I see 1248/2520, but then another
> `C-s' shows 1249/2530 - the total has jumped by 10.
>
> I continue searching forward, and the numbering seems normal:
> 1250/2530, 1251/2530.  OK, so the initial total was off by 10.
>
> But at match #1251 I switch to `C-r', and the match number is
> 1241/2520: both the match number and the total are off by 10.
>
> On a small buffer I don't notice this problem.
>
> Do you see this too?  If not, maybe I patched mistakenly.

I see this too.  The problem was in too frequent updating
of the Isearch prompt - the loop updated it after every
max-at-a-time (default 20) matches, thus causing flickering
(that didn't update the final number).  Now changed to show
only the final number without showing intermediate numbers
(that are invalid during counting anyway).

Please try a new patch, it removes flickering:

diff --git a/lisp/isearch.el b/lisp/isearch.el
index 580b3ac40a..9127c4561a 100644
--- a/lisp/isearch.el
+++ b/lisp/isearch.el
@@ -316,6 +316,15 @@ isearch-lazy-highlight
   :group 'lazy-highlight
   :group 'isearch)
 
+(defcustom isearch-lazy-count nil
+  "Show match number in the Isearch prompt.
+When both this option and `isearch-lazy-highlight' are non-nil, show
+CURRENT/TOTAL, where CURRENT is the current match number and TOTAL is
+the total number of matches in the buffer (or its restriction)."
+  :type 'boolean
+  :group 'isearch
+  :version "27.1")
+
 ;;; Lazy highlight customization.
 
 (defgroup lazy-highlight nil
@@ -2802,7 +2811,16 @@ isearch-message-suffix
 	              (if isearch-error
 	                  (concat " [" isearch-error "]")
 	                "")
-	              (or isearch-message-suffix-add ""))
+	              (or isearch-message-suffix-add "")
+                      (if (and isearch-lazy-count isearch-lazy-count-current)
+                          (format " (%d of %d)"
+                                  (if isearch-forward
+                                      isearch-lazy-count-current
+                                    (- isearch-lazy-count-total
+                                       isearch-lazy-count-current
+                                       -1))
+                                  (or isearch-lazy-count-total "?"))
+                          ""))
               'face 'minibuffer-prompt))
 
 
@@ -3212,6 +3230,10 @@ 'isearch-lazy-highlight-word
 (defvar isearch-lazy-highlight-regexp-function nil)
 (defvar isearch-lazy-highlight-forward nil)
 (defvar isearch-lazy-highlight-error nil)
+(defvar isearch-lazy-count-current nil)
+(defvar isearch-lazy-count-total nil)
+(defvar isearch-lazy-count-start nil)
+(defvar isearch-lazy-count-hash (make-hash-table))
 
 (defun lazy-highlight-cleanup (&optional force procrastinate)
   "Stop lazy highlighting and remove extra highlighting from current buffer.
@@ -3235,33 +3257,35 @@ isearch-lazy-highlight-new-loop
 This is called when `isearch-update' is invoked (which can cause the
 search string to change or the window to scroll).  It is also used
 by other Emacs features."
+  (setq isearch-lazy-count-start
+        (or (not (equal isearch-string
+                        isearch-lazy-highlight-last-string))
+            (not (memq (selected-window)
+                       isearch-lazy-highlight-window-group))
+	    (not (eq isearch-lazy-highlight-case-fold-search
+		     isearch-case-fold-search))
+	    (not (eq isearch-lazy-highlight-regexp
+		     isearch-regexp))
+	    (not (eq isearch-lazy-highlight-regexp-function
+		     isearch-regexp-function))
+	    (not (eq isearch-lazy-highlight-lax-whitespace
+		     isearch-lax-whitespace))
+	    (not (eq isearch-lazy-highlight-regexp-lax-whitespace
+		     isearch-regexp-lax-whitespace))
+	    (not (eq isearch-forward
+		     isearch-lazy-highlight-forward))
+	    ;; In case we are recovering from an error.
+	    (not (equal isearch-error
+			isearch-lazy-highlight-error))))
   (when (and (null executing-kbd-macro)
              (sit-for 0)         ;make sure (window-start) is credible
-             (or (not (equal isearch-string
-                             isearch-lazy-highlight-last-string))
-                 (not (memq (selected-window)
-                            isearch-lazy-highlight-window-group))
-		 (not (eq isearch-lazy-highlight-case-fold-search
-			  isearch-case-fold-search))
-		 (not (eq isearch-lazy-highlight-regexp
-			  isearch-regexp))
-		 (not (eq isearch-lazy-highlight-regexp-function
-			  isearch-regexp-function))
-		 (not (eq isearch-lazy-highlight-lax-whitespace
-			  isearch-lax-whitespace))
-		 (not (eq isearch-lazy-highlight-regexp-lax-whitespace
-			  isearch-regexp-lax-whitespace))
-		 (not (or lazy-highlight-buffer
-			  (= (window-group-start)
+             (or isearch-lazy-count-start
+                 (not (or lazy-highlight-buffer
+		          (= (window-group-start)
 			     isearch-lazy-highlight-window-start)))
-		 (not (or lazy-highlight-buffer
-			  (= (window-group-end) ; Window may have been split/joined.
-			     isearch-lazy-highlight-window-end)))
-		 (not (eq isearch-forward
-			  isearch-lazy-highlight-forward))
-		 ;; In case we are recovering from an error.
-		 (not (equal isearch-error
-			     isearch-lazy-highlight-error))))
+	         (not (or lazy-highlight-buffer
+		          (= (window-group-end) ; Window may have been split/joined.
+			     isearch-lazy-highlight-window-end)))))
     ;; something important did indeed change
     (lazy-highlight-cleanup t (not (equal isearch-string ""))) ;stop old timer
     (setq isearch-lazy-highlight-error isearch-error)
@@ -3303,9 +3327,22 @@ isearch-lazy-highlight-new-loop
 		    (1- (length isearch-lazy-highlight-last-string)))
 		 (point-min))))
     (unless (equal isearch-string "")
+      (when (and isearch-lazy-count isearch-mode)
+        (when isearch-lazy-count-start
+          (clrhash isearch-lazy-count-hash)
+          (setq isearch-lazy-count-current nil
+                isearch-lazy-count-total nil)
+          (funcall (or isearch-message-function #'isearch-message) nil t)))
       (setq isearch-lazy-highlight-timer
             (run-with-idle-timer lazy-highlight-initial-delay nil
-                                 'isearch-lazy-highlight-start)))))
+                                 'isearch-lazy-highlight-start))))
+  (when (and isearch-lazy-count isearch-mode)
+    ;; Update isearch-lazy-count-current only when it was already set
+    ;; at the end of isearch-lazy-highlight-buffer-update
+    (when isearch-lazy-count-current
+      (setq isearch-lazy-count-current
+            (gethash isearch-other-end isearch-lazy-count-hash))
+      (funcall (or isearch-message-function #'isearch-message) nil t))))
 
 (defun isearch-lazy-highlight-search (string bound)
   "Search ahead for the next or previous match, for lazy highlighting.
@@ -3426,7 +3463,8 @@ isearch-lazy-highlight-update
 			(goto-char (min (or isearch-lazy-highlight-end-limit (point-max))
 					window-end)))))))
 	    (if nomore
-		(when isearch-lazy-highlight-buffer
+                (when (or isearch-lazy-highlight-buffer
+                          isearch-lazy-count-start)
 		  (if isearch-lazy-highlight-forward
 		      (setq isearch-lazy-highlight-end (point-min))
 		    (setq isearch-lazy-highlight-start (point-max)))
@@ -3475,8 +3513,13 @@ isearch-lazy-highlight-buffer-update
 			    (if (= mb (point-min))
 				(setq found nil)
 			      (forward-char -1)))
+                        (setq isearch-lazy-count-total (1+ (or isearch-lazy-count-total 0)))
+                        (puthash (if isearch-lazy-highlight-forward mb me)
+                                 isearch-lazy-count-total
+                                 isearch-lazy-count-hash)
 			;; Already highlighted by isearch-lazy-highlight-update
-			(unless (and (>= mb window-start) (<= me window-end))
+                        (unless (or (and (>= mb window-start) (<= me window-end))
+                                    (not isearch-lazy-highlight-buffer))
 			  ;; non-zero-length match
 			  (isearch-lazy-highlight-match mb me)))
 		      ;; Remember the current position of point for
@@ -3490,7 +3533,11 @@ isearch-lazy-highlight-buffer-update
 		(if (not found)
 		    (setq looping nil
 			  nomore  t))))
-	    (unless nomore
+	    (if nomore
+	        (when (and isearch-lazy-count isearch-mode)
+                  (setq isearch-lazy-count-current
+                        (gethash isearch-other-end isearch-lazy-count-hash))
+                  (funcall (or isearch-message-function #'isearch-message) nil t))
 	      (setq isearch-lazy-highlight-timer
 		    (run-at-time lazy-highlight-interval nil
 				 'isearch-lazy-highlight-buffer-update)))))))))