unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
From: Juri Linkov <juri@linkov.net>
To: Drew Adams <drew.adams@oracle.com>
Cc: Eli Zaretskii <eliz@gnu.org>,
	"40808@debbugs.gnu.org" <40808@debbugs.gnu.org>,
	"abdullah@net-c.com" <abdullah@net-c.com>
Subject: bug#40808: 27.0.91; inaccuracy in isearch-lazy-count
Date: Thu, 07 Jul 2022 20:09:07 +0300	[thread overview]
Message-ID: <868rp4hmto.fsf@mail.linkov.net> (raw)
In-Reply-To: <SJ0PR10MB5488E6222EEAEF23FB32275DF3159@SJ0PR10MB5488.namprd10.prod.outlook.com> (Drew Adams's message of "Mon, 12 Jul 2021 01:58:14 +0000")

[-- Attachment #1: Type: text/plain, Size: 957 bytes --]

> What's the status of this bug?  Apart from the request
> by Juri for changes to be made to Org mode, is the code
> Juri prescribed for this bug fix going to be applied,
> or has it been applied?
>
> Is fixing this bug (e.g. with Juri's code) somehow
> dependent on also fixing some Org-mode code?

Fortunately, the isearch fix doesn't depend on org-mode.
So here is the complete implementation that was made possible
thanks to the suggestions in
https://lists.gnu.org/archive/html/emacs-devel/2022-06/msg01208.html

For example, searching for the word "nongnu" in etc/ORG-NEWS
when all outlines are collapsed with isearch-lazy-count=t
will show such prompts:

search-invisible = t      1/4 I-search:
search-invisible = open   1/2 (invisible 2) I-search:
search-invisible = nil    0/0 (invisible 4) I-search:

where such numbers as "1/2" show the matches that can be visited by isearch,
and "(invisible 2)" are the rest of matches unreachable by isearch.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: lazy-count-invisible.patch --]
[-- Type: text/x-diff, Size: 7164 bytes --]

diff --git a/lisp/isearch.el b/lisp/isearch.el
index db7b53c014..945dce029a 100644
--- a/lisp/isearch.el
+++ b/lisp/isearch.el
@@ -466,6 +466,12 @@ lazy-count-suffix-format
   :group 'lazy-count
   :version "27.1")
 
+(defvar lazy-count-invisible-format " (invisible %s)"
+  "Format of the number of invisible matches for the prompt.
+When invisible matches exist, their number is appended
+after the total number of matches.  Display nothing when
+this variable is nil.")
+
 \f
 ;; Define isearch help map.
 
@@ -1277,6 +1283,7 @@ isearch-mode
 
 	isearch-lazy-count-current nil
 	isearch-lazy-count-total nil
+	isearch-lazy-count-invisible nil
 
 	;; Save the original value of `minibuffer-message-timeout', and
 	;; set it to nil so that isearch's messages don't get timed out.
@@ -3529,7 +3536,12 @@ isearch-lazy-count-format
                     (- isearch-lazy-count-total
                        isearch-lazy-count-current
                        -1)))
-                (or isearch-lazy-count-total "?"))
+                (if (and isearch-lazy-count-invisible
+                         lazy-count-invisible-format)
+                    (concat (format "%s" (or isearch-lazy-count-total "?"))
+                            (format lazy-count-invisible-format
+                                    isearch-lazy-count-invisible))
+                  (or isearch-lazy-count-total "?")))
       "")))
 
 \f
@@ -3780,10 +3792,11 @@ isearch-range-invisible
     (save-excursion
       (goto-char beg)
       (let (;; can-be-opened keeps track if we can open some overlays.
-	    (can-be-opened (eq search-invisible 'open))
+	    (can-be-opened (memq search-invisible '(open can-be-opened)))
 	    ;; the list of overlays that could be opened
 	    (crt-overlays nil))
-	(when (and can-be-opened isearch-hide-immediately)
+	(when (and can-be-opened isearch-hide-immediately
+                   (not (eq search-invisible 'can-be-opened)))
 	  (isearch-close-unnecessary-overlays beg end))
 	;; If the following character is currently invisible,
 	;; skip all characters with that same `invisible' property value.
@@ -3822,9 +3835,10 @@ isearch-range-invisible
 	(if (>= (point) end)
 	    (if (and can-be-opened (consp crt-overlays))
 		(progn
-		  (setq isearch-opened-overlays
-			(append isearch-opened-overlays crt-overlays))
-		  (mapc 'isearch-open-overlay-temporary crt-overlays)
+		  (unless (eq search-invisible 'can-be-opened)
+                    (setq isearch-opened-overlays
+			  (append isearch-opened-overlays crt-overlays))
+		    (mapc 'isearch-open-overlay-temporary crt-overlays))
 		  nil)
 	      (setq isearch-hidden t)))))))
 
@@ -4008,6 +4022,7 @@ isearch-lazy-highlight-forward
 (defvar isearch-lazy-highlight-error nil)
 (defvar isearch-lazy-count-current nil)
 (defvar isearch-lazy-count-total nil)
+(defvar isearch-lazy-count-invisible nil)
 (defvar isearch-lazy-count-hash (make-hash-table))
 (defvar lazy-count-update-hook nil
   "Hook run after new lazy count results are computed.")
@@ -4086,7 +4101,8 @@ isearch-lazy-highlight-new-loop
         ;; Reset old counter before going to count new numbers
         (clrhash isearch-lazy-count-hash)
         (setq isearch-lazy-count-current nil
-              isearch-lazy-count-total nil)
+              isearch-lazy-count-total nil
+              isearch-lazy-count-invisible nil)
         ;; Delay updating the message if possible, to avoid flicker
         (when (string-equal isearch-string "")
           (when (and isearch-mode (null isearch-message-function))
@@ -4166,11 +4182,13 @@ isearch-lazy-highlight-search
 	    (isearch-regexp-lax-whitespace
 	     isearch-lazy-highlight-regexp-lax-whitespace)
 	    (isearch-forward isearch-lazy-highlight-forward)
-	    ;; Don't match invisible text unless it can be opened
-	    ;; or when counting matches and user can visit hidden matches
-	    (search-invisible (or (eq search-invisible 'open)
-				  (and isearch-lazy-count search-invisible)))
-	    (retry t)
+            ;; Count all invisible matches, but highlight only
+            ;; according to search-invisible without opening overlays.
+	    (search-invisible (or isearch-lazy-count
+                                  (if (eq search-invisible 'open)
+                                      'can-be-opened
+                                    search-invisible)))
+            (retry t)
 	    (success nil))
 	;; Use a loop like in `isearch-search'.
 	(while retry
@@ -4186,15 +4204,23 @@ isearch-lazy-highlight-search
     (error nil)))
 
 (defun isearch-lazy-highlight-match (mb me)
-  (let ((ov (make-overlay mb me)))
-    (push ov isearch-lazy-highlight-overlays)
-    ;; 1000 is higher than ediff's 100+,
-    ;; but lower than isearch main overlay's 1001
-    (overlay-put ov 'priority 1000)
-    (overlay-put ov 'face 'lazy-highlight)
-    (unless (or (eq isearch-lazy-highlight 'all-windows)
-                isearch-lazy-highlight-buffer)
-      (overlay-put ov 'window (selected-window)))))
+  (unless (and isearch-lazy-count
+               ;; Recheck the match that possibly was intended
+               ;; for counting only, but not for highlighting
+               (not (let ((search-invisible
+                           (if (eq search-invisible 'open)
+                               'can-be-opened
+                             search-invisible)))
+                      (funcall isearch-filter-predicate mb me))))
+    (let ((ov (make-overlay mb me)))
+      (push ov isearch-lazy-highlight-overlays)
+      ;; 1000 is higher than ediff's 100+,
+      ;; but lower than isearch main overlay's 1001
+      (overlay-put ov 'priority 1000)
+      (overlay-put ov 'face 'lazy-highlight)
+      (unless (or (eq isearch-lazy-highlight 'all-windows)
+                  isearch-lazy-highlight-buffer)
+        (overlay-put ov 'window (selected-window))))))
 
 (defun isearch-lazy-highlight-start ()
   "Start a new lazy-highlight updating loop."
@@ -4328,11 +4354,19 @@ isearch-lazy-highlight-buffer-update
 				(setq found nil)
 			      (forward-char -1)))
 			(when isearch-lazy-count
-			  (setq isearch-lazy-count-total
-				(1+ (or isearch-lazy-count-total 0)))
-			  (puthash (if isearch-lazy-highlight-forward me mb)
-				   isearch-lazy-count-total
-				   isearch-lazy-count-hash))
+                          ;; Count as invisible when can't open overlay
+			  (if (not (let ((search-invisible
+                                          (if (eq search-invisible 'open)
+                                              'can-be-opened
+                                            search-invisible)))
+                                     (funcall isearch-filter-predicate mb me)))
+			      (setq isearch-lazy-count-invisible
+				    (1+ (or isearch-lazy-count-invisible 0)))
+			    (setq isearch-lazy-count-total
+				  (1+ (or isearch-lazy-count-total 0)))
+			    (puthash (if isearch-lazy-highlight-forward me mb)
+				     isearch-lazy-count-total
+				     isearch-lazy-count-hash)))
 			;; Don't highlight the match when this loop is used
 			;; only to count matches or when matches were already
 			;; highlighted within the current window boundaries

  reply	other threads:[~2022-07-07 17:09 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-07-12  1:58 bug#40808: 27.0.91; inaccuracy in isearch-lazy-count Drew Adams
2022-07-07 17:09 ` Juri Linkov [this message]
2022-07-08 17:48   ` Juri Linkov
2022-12-10 17:51   ` Juri Linkov
2022-12-12 17:44     ` Juri Linkov
2022-12-28 18:54       ` Juri Linkov
  -- strict thread matches above, loose matches on Subject: below --
2020-04-24  6:42 Abdullah Asad
2020-04-25 20:53 ` Juri Linkov
2020-04-28 18:46   ` Abdullah Asad
2020-04-28 19:19     ` Eli Zaretskii
2020-04-28 23:54       ` Juri Linkov
2020-04-29  7:11         ` Eli Zaretskii
2020-04-29 20:56           ` Juri Linkov
2020-04-30 20:18             ` Juri Linkov
2020-05-01  5:58               ` Eli Zaretskii
2020-05-03 22:33                 ` Juri Linkov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=868rp4hmto.fsf@mail.linkov.net \
    --to=juri@linkov.net \
    --cc=40808@debbugs.gnu.org \
    --cc=abdullah@net-c.com \
    --cc=drew.adams@oracle.com \
    --cc=eliz@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).