Subject: Re: bug#29321: Isearch hit count

From: Live System User <[email-masked]>
Date: Thu, 15 Nov 2018 03:02:51 -0500

Juri Linkov <[email-masked]> writes:

>> Isearch could show in the mode line how many matches follow or precede 
>> the currently highlighted one (or we could write "3 of 4 matches", as, 
>> e.g., Firefox does).  For big files, it could be helpful to calculate 
>> this information either lazily or in another thread.
>
> Lazy-counting is now pushed to master.
>
>> If we had this, it would also be convenient to say "go forward n
>> matches", so that typing "M-3 C-s" during a search would be the
>> equivalent of typing C-s three times.  To do this we could add numeric
>> prefix arg handling to C-s/C-r/C-M-s/C-M-r, if that isn't already
>> taken for some other behavior.
>
> Adding a numeric prefix arg to C-s/C-r is implemented in
> https://debbugs.gnu.org/29321#86

  Thanks!
  
>
> But this implementation causes flicker because it updates
> isearch highlighting on every search hit while traversing
> all found matches COUNT times until it reaches COUNT-th match.
>
> Attached is a better approach that adds the COUNT arg to
> isearch functions down to the lowest-level isearch function,
> thus making it compatible with the COUNT arg of re-search-forward:

  Unfortunately, this patch (below) had errrs for me:

0. emacs -Q &

1. M-: (setq isearch-lazy-count t)

2. M-x load-file RET isearch-new.el RET

3. C-x C-r isearch-new.el

  I then search for the string "-count" ...

4. C-s -c

   ...and in the echo area I see:

             0/0 I-search: -c [(void-variable +)]

   The cursor doesn't  move and no matches are not highlighted nor
   is there a "Failing I-search" " meassage.

   Thanks.

>
> diff --git a/lisp/isearch.el b/lisp/isearch.el
> index 035ff69327..3e6e696a74 100644
> --- a/lisp/isearch.el
> +++ b/lisp/isearch.el
> @@ -1547,7 +1547,7 @@ isearch-abort
>        (isearch-pop-state))
>      (isearch-update)))
>  
> -(defun isearch-repeat (direction)
> +(defun isearch-repeat (direction &optional count)
>    ;; Utility for isearch-repeat-forward and -backward.
>    (if (eq isearch-forward (eq direction 'forward))
>        ;; C-s in forward or C-r in reverse.
> @@ -1590,21 +1590,29 @@ isearch-repeat
>  	      (setq isearch-success nil)
>  	      (ding))
>  	  (forward-char (if isearch-forward 1 -1))
> -	  (isearch-search))
> -      (isearch-search)))
> +	  (isearch-search count))
> +      (isearch-search count)))
>  
>    (isearch-push-state)
>    (isearch-update))
>  
> -(defun isearch-repeat-forward ()
> -  "Repeat incremental search forwards."
> -  (interactive)
> -  (isearch-repeat 'forward))
> -
> -(defun isearch-repeat-backward ()
> -  "Repeat incremental search backwards."
> -  (interactive)
> -  (isearch-repeat 'backward))
> +(defun isearch-repeat-forward (&optional arg)
> +  "Repeat incremental search forwards.
> +With a prefix argument, repeat a search ARG times."
> +  (interactive "P")
> +  (let ((count (and arg (abs (prefix-numeric-value arg)))))
> +    ;; Take into account one search iteration to reverse direction.
> +    (when (and count (not isearch-forward)) (setq count (1+ count)))
> +    (isearch-repeat 'forward count)))
> +
> +(defun isearch-repeat-backward (&optional arg)
> +  "Repeat incremental search backwards.
> +With a prefix argument, repeat a search ARG times."
> +  (interactive "P")
> +  (let ((count (and arg (abs (prefix-numeric-value arg)))))
> +    ;; Take into account one search iteration to reverse direction.
> +    (when (and count isearch-forward) (setq count (1+ count)))
> +    (isearch-repeat 'backward count)))
>  
>  
>  ;;; Toggles for `isearch-regexp-function' and `search-default-mode'.
> @@ -2910,7 +2918,7 @@ isearch-search-fun-default
>               (t (regexp-quote string)))
>         bound noerror count))))
>  
> -(defun isearch-search-string (string bound noerror)
> +(defun isearch-search-string (string bound noerror &optional count)
>    "Search for the first occurrence of STRING or its translation.
>  STRING's characters are translated using `translation-table-for-input'
>  if that is non-nil.
> @@ -2921,7 +2929,10 @@ isearch-search-string
>  Optional third argument, if t, means if fail just return nil (no error).
>    If not nil and not t, move to limit of search and return nil."
>    (let* ((func (isearch-search-fun))
> -         (pos1 (save-excursion (funcall func string bound noerror)))
> +         (pos1 (save-excursion (if count
> +                                   (funcall func string bound noerror count)
> +                                 ;; Backward-compatibility for functions that don't support count arg
> +                                 (funcall func string bound noerror))))
>           pos2)
>      (when (and
>  	   ;; Avoid "obsolete" warnings for translation-table-for-input.
> @@ -2960,7 +2971,7 @@ isearch-search-string
>        (goto-char pos1)
>        pos1)))
>  
> -(defun isearch-search ()
> +(defun isearch-search (&optional count)
>    ;; Do the search with the current search string.
>    (if (and (eq isearch-case-fold-search t) search-upper-case)
>        (setq isearch-case-fold-search
> @@ -2974,7 +2985,7 @@ isearch-search
>  	(setq isearch-error nil)
>  	(while retry
>  	  (setq isearch-success
> -		(isearch-search-string isearch-string nil t))
> +		(isearch-search-string isearch-string nil t count))
>  	  ;; Clear RETRY unless the search predicate says
>  	  ;; to skip this search hit.
>  	  (if (or (not isearch-success)