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)))))))))