diff options
| author | Juri Linkov | 2018-11-15 00:23:47 +0200 |
|---|---|---|
| committer | Juri Linkov | 2018-11-15 00:23:47 +0200 |
| commit | 35a88c809e9eb5a32dd8d7f0dae960021f4cd707 (patch) | |
| tree | a6cc5a092cf2c752f7df48c54e27edc29746f322 | |
| parent | 5fe81ebbb52a82ed13635df4861039ac7ed42022 (diff) | |
| download | emacs-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/NEWS | 6 | ||||
| -rw-r--r-- | lisp/isearch.el | 147 |
2 files changed, 136 insertions, 17 deletions
| @@ -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 | ||
| 625 | of matches in the Isearch prompt. Customizable variables | ||
| 626 | lazy-count-prefix-format and lazy-count-suffix-format define the | ||
| 627 | format of the current and the total number of matches in the prompt's | ||
| 628 | prefix and suffix respectively. | ||
| 629 | |||
| 624 | *** lazy-highlight-buffer highlights matches in the full buffer. | 630 | *** lazy-highlight-buffer highlights matches in the full buffer. |
| 625 | It is useful in combination with lazy-highlight-cleanup customized to nil | 631 | It is useful in combination with lazy-highlight-cleanup customized to nil |
| 626 | to leave matches highlighted in the whole buffer after exiting isearch. | 632 | to 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. | ||
| 321 | When both this option and `isearch-lazy-highlight' are non-nil, | ||
| 322 | show the current match number and the total number of matches | ||
| 323 | in 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. | ||
| 2845 | When SUFFIX-P is non-nil, the returned string is indended for | ||
| 2846 | isearch-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))))))))) |