aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJuri Linkov2018-11-15 00:23:47 +0200
committerJuri Linkov2018-11-15 00:23:47 +0200
commit35a88c809e9eb5a32dd8d7f0dae960021f4cd707 (patch)
treea6cc5a092cf2c752f7df48c54e27edc29746f322
parent5fe81ebbb52a82ed13635df4861039ac7ed42022 (diff)
downloademacs-35a88c809e9eb5a32dd8d7f0dae960021f4cd707.tar.gz
emacs-35a88c809e9eb5a32dd8d7f0dae960021f4cd707.zip
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.
-rw-r--r--etc/NEWS6
-rw-r--r--lisp/isearch.el147
2 files changed, 136 insertions, 17 deletions
diff --git a/etc/NEWS b/etc/NEWS
index dff7c5d0d5f..76531f288ff 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -621,6 +621,12 @@ can now be searched via 'C-s'.
621 621
622** Search and Replace 622** Search and Replace
623 623
624*** isearch-lazy-count shows the current match number and total number
625of matches in the Isearch prompt. Customizable variables
626lazy-count-prefix-format and lazy-count-suffix-format define the
627format of the current and the total number of matches in the prompt's
628prefix and suffix respectively.
629
624*** lazy-highlight-buffer highlights matches in the full buffer. 630*** lazy-highlight-buffer highlights matches in the full buffer.
625It is useful in combination with lazy-highlight-cleanup customized to nil 631It is useful in combination with lazy-highlight-cleanup customized to nil
626to leave matches highlighted in the whole buffer after exiting isearch. 632to leave matches highlighted in the whole buffer after exiting isearch.
diff --git a/lisp/isearch.el b/lisp/isearch.el
index 42b3aa42ba9..035ff693275 100644
--- a/lisp/isearch.el
+++ b/lisp/isearch.el
@@ -316,6 +316,16 @@ this variable is set to the symbol `all-windows'."
316 :group 'lazy-highlight 316 :group 'lazy-highlight
317 :group 'isearch) 317 :group 'isearch)
318 318
319(defcustom isearch-lazy-count nil
320 "Show match numbers in the search prompt.
321When both this option and `isearch-lazy-highlight' are non-nil,
322show the current match number and the total number of matches
323in the buffer (or its restriction)."
324 :type 'boolean
325 :group 'lazy-count
326 :group 'isearch
327 :version "27.1")
328
319;;; Lazy highlight customization. 329;;; Lazy highlight customization.
320 330
321(defgroup lazy-highlight nil 331(defgroup lazy-highlight nil
@@ -386,6 +396,29 @@ and doesn't remove full-buffer highlighting after a search."
386 :group 'lazy-highlight 396 :group 'lazy-highlight
387 :group 'basic-faces) 397 :group 'basic-faces)
388 398
399;;; Lazy count customization.
400
401(defgroup lazy-count nil
402 "Lazy counting feature for reporting the number of matches."
403 :prefix "lazy-count-"
404 :version "27.1"
405 :group 'isearch
406 :group 'matching)
407
408(defcustom lazy-count-prefix-format "%s/%s "
409 "Format of the current/total number of matches for the prompt prefix."
410 :type '(choice (const :tag "No prefix" nil)
411 (string :tag "Prefix format string" "%s/%s "))
412 :group 'lazy-count
413 :version "27.1")
414
415(defcustom lazy-count-suffix-format nil
416 "Format of the current/total number of matches for the prompt suffix."
417 :type '(choice (const :tag "No suffix" nil)
418 (string :tag "Suffix format string" " [%s of %s]"))
419 :group 'lazy-count
420 :version "27.1")
421
389 422
390;; Define isearch help map. 423;; Define isearch help map.
391 424
@@ -2794,7 +2827,8 @@ the word mode."
2794 (concat " [" current-input-method-title "]: ")) 2827 (concat " [" current-input-method-title "]: "))
2795 ": ") 2828 ": ")
2796 ))) 2829 )))
2797 (propertize (concat (upcase (substring m 0 1)) (substring m 1)) 2830 (propertize (concat (isearch-lazy-count-format)
2831 (upcase (substring m 0 1)) (substring m 1))
2798 'face 'minibuffer-prompt))) 2832 'face 'minibuffer-prompt)))
2799 2833
2800(defun isearch-message-suffix (&optional c-q-hack) 2834(defun isearch-message-suffix (&optional c-q-hack)
@@ -2802,9 +2836,33 @@ the word mode."
2802 (if isearch-error 2836 (if isearch-error
2803 (concat " [" isearch-error "]") 2837 (concat " [" isearch-error "]")
2804 "") 2838 "")
2839 (isearch-lazy-count-format 'suffix)
2805 (or isearch-message-suffix-add "")) 2840 (or isearch-message-suffix-add ""))
2806 'face 'minibuffer-prompt)) 2841 'face 'minibuffer-prompt))
2807 2842
2843(defun isearch-lazy-count-format (&optional suffix-p)
2844 "Format the current match number and the total number of matches.
2845When SUFFIX-P is non-nil, the returned string is indended for
2846isearch-message-suffix prompt. Otherwise, for isearch-message-prefix."
2847 (let ((format-string (if suffix-p
2848 lazy-count-suffix-format
2849 lazy-count-prefix-format)))
2850 (if (and format-string
2851 isearch-lazy-count
2852 isearch-lazy-count-current
2853 (not isearch-error)
2854 (not isearch-suspended))
2855 (format format-string
2856 (if isearch-forward
2857 isearch-lazy-count-current
2858 (if (eq isearch-lazy-count-current 0)
2859 0
2860 (- isearch-lazy-count-total
2861 isearch-lazy-count-current
2862 -1)))
2863 (or isearch-lazy-count-total "?"))
2864 "")))
2865
2808 2866
2809;; Searching 2867;; Searching
2810 2868
@@ -3202,6 +3260,8 @@ since they have special meaning in a regexp."
3202(defvar isearch-lazy-highlight-window-group nil) 3260(defvar isearch-lazy-highlight-window-group nil)
3203(defvar isearch-lazy-highlight-window-start nil) 3261(defvar isearch-lazy-highlight-window-start nil)
3204(defvar isearch-lazy-highlight-window-end nil) 3262(defvar isearch-lazy-highlight-window-end nil)
3263(defvar isearch-lazy-highlight-window-start-changed nil)
3264(defvar isearch-lazy-highlight-window-end-changed nil)
3205(defvar isearch-lazy-highlight-point-min nil) 3265(defvar isearch-lazy-highlight-point-min nil)
3206(defvar isearch-lazy-highlight-point-max nil) 3266(defvar isearch-lazy-highlight-point-max nil)
3207(defvar isearch-lazy-highlight-buffer nil) 3267(defvar isearch-lazy-highlight-buffer nil)
@@ -3214,6 +3274,9 @@ since they have special meaning in a regexp."
3214(defvar isearch-lazy-highlight-regexp-function nil) 3274(defvar isearch-lazy-highlight-regexp-function nil)
3215(defvar isearch-lazy-highlight-forward nil) 3275(defvar isearch-lazy-highlight-forward nil)
3216(defvar isearch-lazy-highlight-error nil) 3276(defvar isearch-lazy-highlight-error nil)
3277(defvar isearch-lazy-count-current nil)
3278(defvar isearch-lazy-count-total nil)
3279(defvar isearch-lazy-count-hash (make-hash-table))
3217 3280
3218(defun lazy-highlight-cleanup (&optional force procrastinate) 3281(defun lazy-highlight-cleanup (&optional force procrastinate)
3219 "Stop lazy highlighting and remove extra highlighting from current buffer. 3282 "Stop lazy highlighting and remove extra highlighting from current buffer.
@@ -3258,18 +3321,41 @@ by other Emacs features."
3258 ;; In case we are recovering from an error. 3321 ;; In case we are recovering from an error.
3259 (not (equal isearch-error 3322 (not (equal isearch-error
3260 isearch-lazy-highlight-error)) 3323 isearch-lazy-highlight-error))
3261 (not (if lazy-highlight-buffer 3324 (if lazy-highlight-buffer
3262 (= (point-min) 3325 (not (= (point-min)
3263 isearch-lazy-highlight-point-min) 3326 isearch-lazy-highlight-point-min))
3264 (= (window-group-start) 3327 (setq isearch-lazy-highlight-window-start-changed
3265 isearch-lazy-highlight-window-start))) 3328 (not (= (window-group-start)
3266 (not (if lazy-highlight-buffer 3329 isearch-lazy-highlight-window-start))))
3267 (= (point-max) 3330 (if lazy-highlight-buffer
3268 isearch-lazy-highlight-point-max) 3331 (not (= (point-max)
3269 (= (window-group-end) ; Window may have been split/joined. 3332 isearch-lazy-highlight-point-max))
3270 isearch-lazy-highlight-window-end))))) 3333 (setq isearch-lazy-highlight-window-end-changed
3334 (not (= (window-group-end) ; Window may have been split/joined.
3335 isearch-lazy-highlight-window-end))))))
3271 ;; something important did indeed change 3336 ;; something important did indeed change
3272 (lazy-highlight-cleanup t (not (equal isearch-string ""))) ;stop old timer 3337 (lazy-highlight-cleanup t (not (equal isearch-string ""))) ;stop old timer
3338 (when isearch-lazy-count
3339 (when (or (equal isearch-string "")
3340 ;; Check if this place was reached by a condition above
3341 ;; other than changed window boundaries (that shouldn't
3342 ;; reset the counter)
3343 (and (not isearch-lazy-highlight-window-start-changed)
3344 (not isearch-lazy-highlight-window-end-changed))
3345 ;; Also check for changes in buffer boundaries in
3346 ;; a possibly narrowed buffer in case lazy-highlight-buffer
3347 ;; is nil, thus the same check was not performed above
3348 (not (= (point-min)
3349 isearch-lazy-highlight-point-min))
3350 (not (= (point-max)
3351 isearch-lazy-highlight-point-max)))
3352 ;; Reset old counter before going to count new numbers
3353 (clrhash isearch-lazy-count-hash)
3354 (setq isearch-lazy-count-current nil
3355 isearch-lazy-count-total nil)
3356 (funcall (or isearch-message-function #'isearch-message))))
3357 (setq isearch-lazy-highlight-window-start-changed nil)
3358 (setq isearch-lazy-highlight-window-end-changed nil)
3273 (setq isearch-lazy-highlight-error isearch-error) 3359 (setq isearch-lazy-highlight-error isearch-error)
3274 ;; It used to check for `(not isearch-error)' here, but actually 3360 ;; It used to check for `(not isearch-error)' here, but actually
3275 ;; lazy-highlighting might find matches to highlight even when 3361 ;; lazy-highlighting might find matches to highlight even when
@@ -3313,7 +3399,16 @@ by other Emacs features."
3313 (unless (equal isearch-string "") 3399 (unless (equal isearch-string "")
3314 (setq isearch-lazy-highlight-timer 3400 (setq isearch-lazy-highlight-timer
3315 (run-with-idle-timer lazy-highlight-initial-delay nil 3401 (run-with-idle-timer lazy-highlight-initial-delay nil
3316 'isearch-lazy-highlight-start))))) 3402 'isearch-lazy-highlight-start))))
3403 ;; Update the current match number only in isearch-mode and
3404 ;; unless isearch-mode is used specially with isearch-message-function
3405 (when (and isearch-lazy-count isearch-mode (null isearch-message-function))
3406 ;; Update isearch-lazy-count-current only when it was already set
3407 ;; at the end of isearch-lazy-highlight-buffer-update
3408 (when isearch-lazy-count-current
3409 (setq isearch-lazy-count-current
3410 (gethash (point) isearch-lazy-count-hash 0))
3411 (isearch-message nil t))))
3317 3412
3318(defun isearch-lazy-highlight-search (string bound) 3413(defun isearch-lazy-highlight-search (string bound)
3319 "Search ahead for the next or previous match, for lazy highlighting. 3414 "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."
3434 (goto-char (min (or isearch-lazy-highlight-end-limit (point-max)) 3529 (goto-char (min (or isearch-lazy-highlight-end-limit (point-max))
3435 window-end))))))) 3530 window-end)))))))
3436 (if nomore 3531 (if nomore
3437 (when isearch-lazy-highlight-buffer 3532 (when (or isearch-lazy-highlight-buffer
3533 (and isearch-lazy-count (null isearch-lazy-count-current)))
3438 (if isearch-lazy-highlight-forward 3534 (if isearch-lazy-highlight-forward
3439 (setq isearch-lazy-highlight-end (point-min)) 3535 (setq isearch-lazy-highlight-end (point-min))
3440 (setq isearch-lazy-highlight-start (point-max))) 3536 (setq isearch-lazy-highlight-start (point-max)))
@@ -3448,7 +3544,8 @@ Attempt to do the search exactly the way the pending Isearch would."
3448 "Update highlighting of other matches in the full buffer." 3544 "Update highlighting of other matches in the full buffer."
3449 (let ((max lazy-highlight-buffer-max-at-a-time) 3545 (let ((max lazy-highlight-buffer-max-at-a-time)
3450 (looping t) 3546 (looping t)
3451 nomore window-start window-end) 3547 nomore window-start window-end
3548 (opoint (point)))
3452 (with-local-quit 3549 (with-local-quit
3453 (save-selected-window 3550 (save-selected-window
3454 (if (and (window-live-p isearch-lazy-highlight-window) 3551 (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."
3483 (if (= mb (point-min)) 3580 (if (= mb (point-min))
3484 (setq found nil) 3581 (setq found nil)
3485 (forward-char -1))) 3582 (forward-char -1)))
3486 ;; Already highlighted by isearch-lazy-highlight-update 3583 (when isearch-lazy-count
3487 (unless (and (>= mb window-start) (<= me window-end)) 3584 (setq isearch-lazy-count-total
3585 (1+ (or isearch-lazy-count-total 0)))
3586 (puthash (if isearch-lazy-highlight-forward me mb)
3587 isearch-lazy-count-total
3588 isearch-lazy-count-hash))
3589 ;; Don't highlight the match when this loop is used
3590 ;; only to count matches or when matches were already
3591 ;; highlighted within the current window boundaries
3592 ;; by isearch-lazy-highlight-update
3593 (unless (or (not isearch-lazy-highlight-buffer)
3594 (and (>= mb window-start) (<= me window-end)))
3488 ;; non-zero-length match 3595 ;; non-zero-length match
3489 (isearch-lazy-highlight-match mb me))) 3596 (isearch-lazy-highlight-match mb me)))
3490 ;; Remember the current position of point for 3597 ;; Remember the current position of point for
@@ -3498,7 +3605,13 @@ Attempt to do the search exactly the way the pending Isearch would."
3498 (if (not found) 3605 (if (not found)
3499 (setq looping nil 3606 (setq looping nil
3500 nomore t)))) 3607 nomore t))))
3501 (unless nomore 3608 (if nomore
3609 (when (and isearch-lazy-count isearch-mode (null isearch-message-function))
3610 (unless isearch-lazy-count-total
3611 (setq isearch-lazy-count-total 0))
3612 (setq isearch-lazy-count-current
3613 (gethash opoint isearch-lazy-count-hash 0))
3614 (isearch-message nil t))
3502 (setq isearch-lazy-highlight-timer 3615 (setq isearch-lazy-highlight-timer
3503 (run-at-time lazy-highlight-interval nil 3616 (run-at-time lazy-highlight-interval nil
3504 'isearch-lazy-highlight-buffer-update))))))))) 3617 'isearch-lazy-highlight-buffer-update)))))))))