>From d3a741f1b782b31f0ba62b5b173b84fbfddf677c Mon Sep 17 00:00:00 2001 From: Jai Flack 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") + ;; 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 "?")) + "")) ;; 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