]> git.eshelyaron.com Git - emacs.git/commitdiff
Add prefix arg to isearch-repeat-forward/backward (bug#14563, bug#29321)
authorJuri Linkov <juri@linkov.net>
Tue, 20 Nov 2018 23:43:21 +0000 (01:43 +0200)
committerJuri Linkov <juri@linkov.net>
Tue, 20 Nov 2018 23:43:21 +0000 (01:43 +0200)
* lisp/isearch.el (isearch-repeat): Add optional arg COUNT.
Add a while-loop that calls `isearch-search' COUNT times.
(isearch-repeat-forward, isearch-repeat-backward):
Add optional prefix ARG passed down to `isearch-repeat'.
Handle reversed directions.

etc/NEWS
lisp/isearch.el

index 1382b4d81e54cacb5a382eb0a2d88bc71f4da1f8..4ed312c721607a5125e1861e9c0fbaf6dbadd79a 100644 (file)
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -640,6 +640,11 @@ can now be searched via 'C-s'.
 
 ** Search and Replace
 
+*** Isearch supports a prefix argument for 'C-s' ('isearch-repeat-forward')
+and 'C-r' ('isearch-repeat-backward').  With a prefix argument, these
+commands repeat the search for the specified occurrence of the search string.
+A negative argument repeats the search in the opposite direction.
+
 *** '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
index 87f4d495f4e7cea0f506997fcc448b8814c9d3be..6d94ef66931e3c64e458280b3933215f9c17b901 100644 (file)
@@ -1555,8 +1555,8 @@ Use `isearch-exit' to quit without signaling."
       (isearch-pop-state))
     (isearch-update)))
 
-(defun isearch-repeat (direction)
-  ;; Utility for isearch-repeat-forward and -backward.
+(defun isearch-repeat (direction &optional count)
+  ;; Utility for isearch-repeat-forward and isearch-repeat-backward.
   (if (eq isearch-forward (eq direction 'forward))
       ;; C-s in forward or C-r in reverse.
       (if (equal isearch-string "")
@@ -1587,32 +1587,67 @@ Use `isearch-exit' to quit without signaling."
 
   (if (equal isearch-string "")
       (setq isearch-success t)
-    (if (and isearch-success
-            (equal (point) isearch-other-end)
-            (not isearch-just-started))
-       ;; If repeating a search that found
-       ;; an empty string, ensure we advance.
-       (if (if isearch-forward (eobp) (bobp))
-           ;; If there's nowhere to advance to, fail (and wrap next time).
-           (progn
-             (setq isearch-success nil)
-             (ding))
-         (forward-char (if isearch-forward 1 -1))
+    ;; For the case when count > 1, don't keep intermediate states
+    ;; added to isearch-cmds by isearch-push-state in this loop.
+    (let ((isearch-cmds isearch-cmds))
+      (while (<= 0 (setq count (1- (or count 1))))
+       (if (and isearch-success
+                (equal (point) isearch-other-end)
+                (not isearch-just-started))
+           ;; If repeating a search that found
+           ;; an empty string, ensure we advance.
+           (if (if isearch-forward (eobp) (bobp))
+               ;; If there's nowhere to advance to, fail (and wrap next time).
+               (progn
+                 (setq isearch-success nil)
+                 (ding))
+             (forward-char (if isearch-forward 1 -1))
+             (isearch-search))
          (isearch-search))
-      (isearch-search)))
+       (when (> count 0)
+         ;; Update isearch-cmds, so if isearch-search fails later,
+         ;; it can restore old successful state from isearch-cmds.
+         (isearch-push-state))
+       ;; Stop looping on failure.
+       (when (or (not isearch-success) isearch-error)
+         (setq count 0)))))
 
   (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 the search ARG times.
+A negative argument searches backwards."
+  (interactive "P")
+  (if arg
+      (let ((count (prefix-numeric-value arg)))
+        (cond ((< count 0)
+               (isearch-repeat-backward (abs count))
+               ;; Reverse the direction back
+               (isearch-repeat 'forward))
+              (t
+               ;; Take into account one iteration to reverse direction
+               (when (not isearch-forward) (setq count (1+ count)))
+               (isearch-repeat 'forward count))))
+    (isearch-repeat 'forward)))
+
+(defun isearch-repeat-backward (&optional arg)
+  "Repeat incremental search backwards.
+With a prefix argument, repeat the search ARG times.
+A negative argument searches forwards."
+  (interactive "P")
+  (if arg
+      (let ((count (prefix-numeric-value arg)))
+        (cond ((< count 0)
+               (isearch-repeat-forward (abs count))
+               ;; Reverse the direction back
+               (isearch-repeat 'backward))
+              (t
+               ;; Take into account one iteration to reverse direction
+               (when isearch-forward (setq count (1+ count)))
+               (isearch-repeat 'backward count))))
+    (isearch-repeat 'backward)))
 
 \f
 ;;; Toggles for `isearch-regexp-function' and `search-default-mode'.