1
0
mirror of https://git.savannah.gnu.org/git/emacs.git synced 2024-11-26 07:33:47 +00:00

Isearch hit count. (Bug#29321)

* lisp/isearch.el (isearch-lazy-count): New defcustom.
(lazy-count): New defgroup.
(lazy-count-prefix-format, lazy-count-suffix-format): New defcustom.
(isearch-lazy-count-format): New function.
(isearch-message-prefix, isearch-message-suffix): Use it.
(isearch-lazy-highlight-window-start-changed)
(isearch-lazy-highlight-window-end-changed)
(isearch-lazy-count-current, isearch-lazy-count-total)
(isearch-lazy-count-hash): New variables.
(isearch-lazy-highlight-new-loop): Reset isearch-lazy-count-total
and update isearch-lazy-count-current for isearch-message.
(isearch-lazy-highlight-update): Run full-buffer loop for
isearch-lazy-count.
(isearch-lazy-highlight-buffer-update): Count isearch-lazy-count-total.
Set isearch-lazy-count-current at the end.
This commit is contained in:
Juri Linkov 2018-11-15 00:23:47 +02:00
parent 5fe81ebbb5
commit 35a88c809e
2 changed files with 136 additions and 17 deletions

View File

@ -621,6 +621,12 @@ can now be searched via 'C-s'.
** Search and Replace
*** isearch-lazy-count shows the current match number and total number
of matches in the Isearch prompt. Customizable variables
lazy-count-prefix-format and lazy-count-suffix-format define the
format of the current and the total number of matches in the prompt's
prefix and suffix respectively.
*** lazy-highlight-buffer highlights matches in the full buffer.
It is useful in combination with lazy-highlight-cleanup customized to nil
to leave matches highlighted in the whole buffer after exiting isearch.

View File

@ -316,6 +316,16 @@ this variable is set to the symbol `all-windows'."
:group 'lazy-highlight
:group 'isearch)
(defcustom isearch-lazy-count nil
"Show match numbers in the search prompt.
When both this option and `isearch-lazy-highlight' are non-nil,
show the current match number and the total number of matches
in the buffer (or its restriction)."
:type 'boolean
:group 'lazy-count
:group 'isearch
:version "27.1")
;;; Lazy highlight customization.
(defgroup lazy-highlight nil
@ -386,6 +396,29 @@ and doesn't remove full-buffer highlighting after a search."
:group 'lazy-highlight
:group 'basic-faces)
;;; Lazy count customization.
(defgroup lazy-count nil
"Lazy counting feature for reporting the number of matches."
:prefix "lazy-count-"
:version "27.1"
:group 'isearch
:group 'matching)
(defcustom lazy-count-prefix-format "%s/%s "
"Format of the current/total number of matches for the prompt prefix."
:type '(choice (const :tag "No prefix" nil)
(string :tag "Prefix format string" "%s/%s "))
:group 'lazy-count
:version "27.1")
(defcustom lazy-count-suffix-format nil
"Format of the current/total number of matches for the prompt suffix."
:type '(choice (const :tag "No suffix" nil)
(string :tag "Suffix format string" " [%s of %s]"))
:group 'lazy-count
:version "27.1")
;; Define isearch help map.
@ -2794,7 +2827,8 @@ the word mode."
(concat " [" current-input-method-title "]: "))
": ")
)))
(propertize (concat (upcase (substring m 0 1)) (substring m 1))
(propertize (concat (isearch-lazy-count-format)
(upcase (substring m 0 1)) (substring m 1))
'face 'minibuffer-prompt)))
(defun isearch-message-suffix (&optional c-q-hack)
@ -2802,9 +2836,33 @@ the word mode."
(if isearch-error
(concat " [" isearch-error "]")
"")
(isearch-lazy-count-format 'suffix)
(or isearch-message-suffix-add ""))
'face 'minibuffer-prompt))
(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 indended 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-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
@ -3202,6 +3260,8 @@ since they have special meaning in a regexp."
(defvar isearch-lazy-highlight-window-group nil)
(defvar isearch-lazy-highlight-window-start nil)
(defvar isearch-lazy-highlight-window-end nil)
(defvar isearch-lazy-highlight-window-start-changed nil)
(defvar isearch-lazy-highlight-window-end-changed nil)
(defvar isearch-lazy-highlight-point-min nil)
(defvar isearch-lazy-highlight-point-max nil)
(defvar isearch-lazy-highlight-buffer nil)
@ -3214,6 +3274,9 @@ since they have special meaning in a regexp."
(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-hash (make-hash-table))
(defun lazy-highlight-cleanup (&optional force procrastinate)
"Stop lazy highlighting and remove extra highlighting from current buffer.
@ -3258,18 +3321,41 @@ by other Emacs features."
;; In case we are recovering from an error.
(not (equal isearch-error
isearch-lazy-highlight-error))
(not (if lazy-highlight-buffer
(= (point-min)
isearch-lazy-highlight-point-min)
(= (window-group-start)
isearch-lazy-highlight-window-start)))
(not (if lazy-highlight-buffer
(= (point-max)
isearch-lazy-highlight-point-max)
(= (window-group-end) ; Window may have been split/joined.
isearch-lazy-highlight-window-end)))))
(if lazy-highlight-buffer
(not (= (point-min)
isearch-lazy-highlight-point-min))
(setq isearch-lazy-highlight-window-start-changed
(not (= (window-group-start)
isearch-lazy-highlight-window-start))))
(if lazy-highlight-buffer
(not (= (point-max)
isearch-lazy-highlight-point-max))
(setq isearch-lazy-highlight-window-end-changed
(not (= (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
(when isearch-lazy-count
(when (or (equal isearch-string "")
;; Check if this place was reached by a condition above
;; other than changed window boundaries (that shouldn't
;; reset the counter)
(and (not isearch-lazy-highlight-window-start-changed)
(not isearch-lazy-highlight-window-end-changed))
;; Also check for changes in buffer boundaries in
;; a possibly narrowed buffer in case lazy-highlight-buffer
;; is nil, thus the same check was not performed above
(not (= (point-min)
isearch-lazy-highlight-point-min))
(not (= (point-max)
isearch-lazy-highlight-point-max)))
;; 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)
(funcall (or isearch-message-function #'isearch-message))))
(setq isearch-lazy-highlight-window-start-changed nil)
(setq isearch-lazy-highlight-window-end-changed nil)
(setq isearch-lazy-highlight-error isearch-error)
;; It used to check for `(not isearch-error)' here, but actually
;; lazy-highlighting might find matches to highlight even when
@ -3313,7 +3399,16 @@ by other Emacs features."
(unless (equal isearch-string "")
(setq isearch-lazy-highlight-timer
(run-with-idle-timer lazy-highlight-initial-delay nil
'isearch-lazy-highlight-start)))))
'isearch-lazy-highlight-start))))
;; Update the current match number only in isearch-mode and
;; unless isearch-mode is used specially with isearch-message-function
(when (and isearch-lazy-count isearch-mode (null isearch-message-function))
;; 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 (point) isearch-lazy-count-hash 0))
(isearch-message nil t))))
(defun isearch-lazy-highlight-search (string bound)
"Search ahead for the next or previous match, for lazy highlighting.
@ -3434,7 +3529,8 @@ Attempt to do the search exactly the way the pending Isearch would."
(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
(and isearch-lazy-count (null isearch-lazy-count-current)))
(if isearch-lazy-highlight-forward
(setq isearch-lazy-highlight-end (point-min))
(setq isearch-lazy-highlight-start (point-max)))
@ -3448,7 +3544,8 @@ Attempt to do the search exactly the way the pending Isearch would."
"Update highlighting of other matches in the full buffer."
(let ((max lazy-highlight-buffer-max-at-a-time)
(looping t)
nomore window-start window-end)
nomore window-start window-end
(opoint (point)))
(with-local-quit
(save-selected-window
(if (and (window-live-p isearch-lazy-highlight-window)
@ -3483,8 +3580,18 @@ Attempt to do the search exactly the way the pending Isearch would."
(if (= mb (point-min))
(setq found nil)
(forward-char -1)))
;; Already highlighted by isearch-lazy-highlight-update
(unless (and (>= mb window-start) (<= me window-end))
(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))
;; 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
;; by isearch-lazy-highlight-update
(unless (or (not isearch-lazy-highlight-buffer)
(and (>= mb window-start) (<= me window-end)))
;; non-zero-length match
(isearch-lazy-highlight-match mb me)))
;; Remember the current position of point for
@ -3498,7 +3605,13 @@ Attempt to do the search exactly the way the pending Isearch would."
(if (not found)
(setq looping nil
nomore t))))
(unless nomore
(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 nil t))
(setq isearch-lazy-highlight-timer
(run-at-time lazy-highlight-interval nil
'isearch-lazy-highlight-buffer-update)))))))))