unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
From: Jai Flack <jflack@disroot.org>
To: Stefan Monnier <monnier@iro.umontreal.ca>
Cc: Augusto Stoffel <arstoffel@gmail.com>,
	 Philip Kaludercic <philipk@posteo.net>,
	 emacs-devel@gnu.org
Subject: Overlay count for isearch (Was: [NonGNU] New package: ctrlf and Questions)
Date: Wed, 16 Mar 2022 21:37:03 +1000	[thread overview]
Message-ID: <87czim3z8g.fsf_-_@disroot.org> (raw)
In-Reply-To: <jwvczj90xkk.fsf-monnier+emacs@gnu.org> (Stefan Monnier's message of "Sat, 26 Feb 2022 23:02:02 -0500")

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: 0001-New-setting-for-an-in-buffer-display-of-isearch-matc.patch --]
[-- Type: text/x-diff, Size: 10572 bytes --]

From d3a741f1b782b31f0ba62b5b173b84fbfddf677c Mon Sep 17 00:00:00 2001
From: Jai Flack <jflack@disroot.org>
Date: Wed, 16 Mar 2022 20:38:05 +1000
Subject: [PATCH] New setting for an in-buffer display of isearch match numbers

Exposes this behaviour through 'isearch-lazy-count-at-match' and
'isearch-lazy-count-at-match-format'. It relies on
'isearch-lazy-count' and 'isearch-lazy-highlight' behaviour for
counting.

* lisp/isearch.el (isearch-lazy-count-at-match): New variable
(lazy-count-at-match): New face
(isearch-show-lazy-count-at-match-format): New variable
(isearch-done): Call 'isearch-show-lazy-count-at-match-cleanup' when
appropriate
(isearch-message): Call 'isearch-show-lazy-count-at-match' when
appropriate
(isearch-message-prefix): Update call to 'isearch-lazy-count-format'
(isearch-message-suffix): Update call to 'isearch-lazy-count-format'
(isearch-lazy-count-format): Now accepts format strings instead of
SUFFIX-P
(isearch-lazy-count-at-match-overlay): New variable
(isearch-show-lazy-count-at-match): New function
(isearch-show-lazy-count-at-match-cleanup): New function
* doc/emacs/search.texi (Search Customizations): Document the
behaviour
---
 doc/emacs/search.texi |  10 +++
 etc/NEWS              |   7 +++
 lisp/isearch.el       | 138 +++++++++++++++++++++++++++++++-----------
 3 files changed, 119 insertions(+), 36 deletions(-)

diff --git a/doc/emacs/search.texi b/doc/emacs/search.texi
index f2d82324e9..9994e45535 100644
--- a/doc/emacs/search.texi
+++ b/doc/emacs/search.texi
@@ -2128,6 +2128,16 @@ Search Customizations
 @vindex lazy-count-suffix-format
 These two variables determine the format of showing the current and
 the total number of matches for @code{isearch-lazy-count}.
+
+@item isearch-lazy-count-at-match
+@vindex isearch-lazy-count-at-match
+Show the current match number and total number of matches just after
+the currently matched line.
+
+@item lazy-count-at-match-format
+@vindex lazy-count-at-match-format
+Determines the format for showing the current and the total number of
+matches for @code{isearch-lazy-count-at-match}.
 @end table
 
 @vindex search-nonincremental-instead
diff --git a/etc/NEWS b/etc/NEWS
index f4d8756950..292526d272 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -579,6 +579,13 @@ command accepts the Unicode name of an Emoji (for example, "smiling
 face" or "heart with arrow"), like 'C-x 8 e e', with minibuffer
 completion, and adds the Emoji into the search string.
 
++++
+*** New user options 'isearch-lazy-count-at-match'
+When non-nil, shows the current match numbers just after the current
+matches line. Format can be controlled with
+'isearch-lazy-count-at-match-format'. Requires 'isearch-lazy-count'
+and 'isearch-lazy-highlight' to be non-nil in order to work.
+
 ** New minor mode 'glyphless-display-mode'.
 This allows an easy way to toggle seeing all glyphless characters in
 the current buffer.
diff --git a/lisp/isearch.el b/lisp/isearch.el
index 8970216398..8abbc56275 100644
--- a/lisp/isearch.el
+++ b/lisp/isearch.el
@@ -362,6 +362,16 @@ isearch-lazy-count
   :group 'isearch
   :version "27.1")
 
+(defcustom isearch-lazy-count-at-match nil
+  "Show match numbers near the current matched search.
+When this option, `isearch-lazy-count' and
+`isearch-lazy-highlight' are non-nil, show the match numbers (see
+`isearch-lazy-count') at the end of the current matches line."
+  :type 'boolean
+  :group 'lazy-count
+  :group 'isearch
+  :version "29.1")
+
 ;;; Lazy highlight customization.
 
 (defgroup lazy-highlight nil
@@ -465,6 +475,23 @@ lazy-count-suffix-format
   :group 'lazy-count
   :version "27.1")
 
+;;; Lazy count at match customization.
+
+(defface lazy-count-at-match
+  '((t (:inherit isearch)))
+  "Face for the lazy count shown at current match."
+  :group 'lazy-count)
+
+(defcustom isearch-lazy-count-at-match-format " %s/%s"
+  "Format of the current/total number of matches for the in-buffer
+display.
+
+See `isearch-lazy-count-at-match'."
+  :type 'boolean
+  :group 'lazy-count
+  :group 'isearch
+  :version "29.1")
+
 \f
 ;; Define isearch help map.
 
@@ -1431,6 +1458,8 @@ isearch-done
   (setq minibuffer-message-timeout isearch-original-minibuffer-message-timeout)
   (isearch-dehighlight)
   (lazy-highlight-cleanup lazy-highlight-cleanup)
+  (when isearch-lazy-count-at-match
+    (isearch-show-lazy-count-at-match-cleanup))
   (setq isearch-lazy-highlight-last-string nil)
   (let ((found-start (window-group-start))
 	(found-point (point)))
@@ -3386,7 +3415,10 @@ isearch-message
 	     (isearch-message-prefix ellipsis isearch-nonincremental)
 	     m
 	     (isearch-message-suffix c-q-hack)))
-    (if c-q-hack m (let ((message-log-max nil)) (message "%s" m)))))
+    (if c-q-hack m (let ((message-log-max nil)) (message "%s" m))))
+  ;; Update the in-buffer count too
+  (when isearch-lazy-count-at-match
+    (isearch-show-lazy-count-at-match)))
 
 (defun isearch--describe-regexp-mode (regexp-function &optional space-before)
   "Make a string for describing REGEXP-FUNCTION.
@@ -3477,41 +3509,39 @@ isearch-message-prefix
 			(concat " [" current-input-method-title "]: "))
 		     ": ")
 		   )))
-    (apply #'propertize (concat (isearch-lazy-count-format)
+    (apply #'propertize (concat (isearch-lazy-count-format lazy-count-prefix-format)
                         (upcase (substring m 0 1)) (substring m 1))
 	   isearch-message-properties)))
 
 (defun isearch-message-suffix (&optional c-q-hack)
   (apply #'propertize (concat (if c-q-hack "^Q" "")
-		      (isearch-lazy-count-format 'suffix)
+		              (isearch-lazy-count-format lazy-count-suffix-format)
 		      (if isearch-error
 			  (concat " [" isearch-error "]")
 			"")
 		      (or isearch-message-suffix-add ""))
 	 isearch-message-properties))
 
-(defun isearch-lazy-count-format (&optional suffix-p)
-  "Format the current match number and the total number of matches.
-When SUFFIX-P is non-nil, the returned string is intended for
-isearch-message-suffix prompt.  Otherwise, for isearch-message-prefix."
-  (let ((format-string (if suffix-p
-                           lazy-count-suffix-format
-                         lazy-count-prefix-format)))
-    (if (and format-string
-             isearch-lazy-count
-             isearch-lazy-count-current
-             (not isearch-error)
-             (not isearch-suspended))
-        (format format-string
-                (if isearch-lazy-highlight-forward
-                    isearch-lazy-count-current
-                  (if (eq isearch-lazy-count-current 0)
-                      0
-                    (- isearch-lazy-count-total
-                       isearch-lazy-count-current
-                       -1)))
-                (or isearch-lazy-count-total "?"))
-      "")))
+(defun isearch-lazy-count-format (format-string)
+  "Format the current match number and the total number of matches
+using FORMAT-STRING. It is given two integer substitutions, the
+first is the current match number and second the total number of
+matches."
+  (if (and format-string
+           isearch-lazy-count
+           isearch-lazy-count-current
+           (not isearch-error)
+           (not isearch-suspended))
+      (format format-string
+              (if isearch-lazy-highlight-forward
+                  isearch-lazy-count-current
+                (if (eq isearch-lazy-count-current 0)
+                    0
+                  (- isearch-lazy-count-total
+                     isearch-lazy-count-current
+                     -1)))
+              (or isearch-lazy-count-total "?"))
+    ""))
 
 \f
 ;; Searching
@@ -3990,6 +4020,7 @@ isearch-lazy-highlight-error
 (defvar isearch-lazy-count-current nil)
 (defvar isearch-lazy-count-total nil)
 (defvar isearch-lazy-count-hash (make-hash-table))
+(defvar isearch-lazy-count-at-match-overlay nil)
 
 (defun lazy-highlight-cleanup (&optional force procrastinate)
   "Stop lazy highlighting and remove extra highlighting from current buffer.
@@ -4325,17 +4356,52 @@ isearch-lazy-highlight-buffer-update
 		;; not found or zero-length match at the search bound
 		(if (not found)
 		    (setq looping nil
-			  nomore  t))))
-	    (if nomore
-		(when (and isearch-lazy-count isearch-mode (null isearch-message-function))
-		  (unless isearch-lazy-count-total
-		    (setq isearch-lazy-count-total 0))
-		  (setq isearch-lazy-count-current
-			(gethash opoint isearch-lazy-count-hash 0))
-		  (isearch-message))
-	      (setq isearch-lazy-highlight-timer
-		    (run-at-time lazy-highlight-interval nil
-				 'isearch-lazy-highlight-buffer-update)))))))))
+			  nomore  t))))))
+	(if nomore
+	    (when (and isearch-lazy-count isearch-mode (null isearch-message-function))
+	      (unless isearch-lazy-count-total
+		(setq isearch-lazy-count-total 0))
+	      (setq isearch-lazy-count-current
+		    (gethash opoint isearch-lazy-count-hash 0))
+	      (isearch-message))
+	  (setq isearch-lazy-highlight-timer
+		(run-at-time lazy-highlight-interval nil
+			     'isearch-lazy-highlight-buffer-update)))))))
+
+(defun isearch-show-lazy-count-at-match ()
+  "Show the match count just after the end of the currently matched
+line."
+  ;; We try to reuse the overlay as much as possible to remove
+  ;; flickering
+  (unless isearch-lazy-count-at-match-overlay
+    (let ((ov (make-overlay 0 0)))
+      (setq isearch-lazy-count-at-match-overlay ov)
+      ;; see isearch-lazy-highlight-match
+      (overlay-put ov 'priority 1001)
+      (overlay-put ov 'face 'lazy-count-at-match)
+      (unless isearch-lazy-highlight-buffer
+        (overlay-put ov 'window (selected-window)))))
+
+  (let ((ov isearch-lazy-count-at-match-overlay)
+        (pae (point-at-eol))
+        (count (propertize (isearch-lazy-count-format
+                            isearch-lazy-count-at-match-format)
+                           'cursor t)))
+    (unless (and (= (overlay-end ov)
+                    pae)
+                 (eq (overlay-buffer ov)
+                     (current-buffer)))
+      (move-overlay ov pae pae (current-buffer)))
+    (unless (string= (overlay-get ov 'after-string)
+                     count)
+      (overlay-put ov 'after-string count))))
+
+(defun isearch-show-lazy-count-at-match-cleanup ()
+  "Remove the search count used by
+\\[isearch-show-lazy-count-at-match]."
+  (when isearch-lazy-count-at-match-overlay
+    (delete-overlay isearch-lazy-count-at-match-overlay)
+    (setq isearch-lazy-count-at-match-overlay nil)))
 
 (defun isearch-resume (string regexp word forward message case-fold)
   "Resume an incremental search.
-- 
2.30.2


[-- Attachment #2: Type: text/plain, Size: 1203 bytes --]

Stefan Monnier <monnier@iro.umontreal.ca> writes:
> If it's not for everyone, then it should arguably be provided under the
> control of the config var, but that doesn't mean it should be in
> a separate package or relegated to some ELisp snippets for people to
> copy&paste into their init file.
>
> Whether it better belongs alongside `isearch` or `isearch-mb` will
> probably depend on details of how it's implemented.

Here's a patch providing just that for isearch. It could be added to
isearch-mb almost just as easily though it has nothing to do with search
entry.

With regards to an isearch-mb wiki "trick": the same result could be
achieved using `isearch-mode-end-hook` and :after advice on
`isearch-message`.

Whether it becomes a part of isearch or not some feedback would be
appreciated (;

1. Is it right to modify `isearch-lazy-count-format` in this way to
reduce code in `isearch-show-lazy-count-at-match`?

2. Is it right to add a new face for this and if so does this need to be
included in NEWS or other documentation?

3. Should it be extended to allow for custom positioning of the overlay?
Perhaps with a variable like `isearch-lazy-count-at-match-pos-function`?

-- 
Thanks,
Jai

  reply	other threads:[~2022-03-16 11:37 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-02-23 11:56 [NonGNU] New package: ctrlf and Questions jflack
2022-02-23 18:33 ` Augusto Stoffel
2022-02-23 19:40   ` Philip Kaludercic
2022-02-23 20:59     ` Augusto Stoffel
2022-02-24 10:36       ` Jai Flack
2022-02-26 11:02         ` Augusto Stoffel
2022-02-27  4:02           ` Stefan Monnier
2022-03-16 11:37             ` Jai Flack [this message]
2022-03-16 12:00               ` Overlay count for isearch Augusto Stoffel
2022-03-18  2:45                 ` Jai Flack
2022-03-18  8:21                   ` Philip Kaludercic
2022-03-24  1:22                     ` Jai Flack
2022-03-24  8:31                       ` Juri Linkov
2022-03-25  1:04                         ` lazy-count-update-hook run with inconsistent point (Was: Overlay count for isearch) Jai Flack
2022-03-25  7:54                           ` lazy-count-update-hook run with inconsistent point Augusto Stoffel
2022-03-25  8:36                             ` Juri Linkov
2022-03-25  9:48                               ` Augusto Stoffel
2022-03-27  5:24                                 ` Jai Flack
2022-03-27  7:48                                 ` Juri Linkov
2022-03-26  3:28                       ` Overlay count for isearch Richard Stallman
2022-03-27  5:03                         ` Jai Flack
2022-03-05  4:39           ` [NonGNU] New package: ctrlf and Questions Jai Flack

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=87czim3z8g.fsf_-_@disroot.org \
    --to=jflack@disroot.org \
    --cc=arstoffel@gmail.com \
    --cc=emacs-devel@gnu.org \
    --cc=monnier@iro.umontreal.ca \
    --cc=philipk@posteo.net \
    /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).