summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJuri Linkov <juri@linkov.net>2018-11-21 01:43:21 +0200
committerJuri Linkov <juri@linkov.net>2018-11-21 01:43:21 +0200
commit166f6274b4118344612e60fba831e223728f3e89 (patch)
tree5912a969d7e022807e2545ead7c23ffc5fdf0ff4
parent11c9343fe63fdc8bfef3246d95f42523d73fb733 (diff)
downloademacs-166f6274b4118344612e60fba831e223728f3e89.tar.gz
Add prefix arg to isearch-repeat-forward/backward (bug#14563, bug#29321)
* 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.
-rw-r--r--etc/NEWS5
-rw-r--r--lisp/isearch.el81
2 files changed, 63 insertions, 23 deletions
diff --git a/etc/NEWS b/etc/NEWS
index 1382b4d81e5..4ed312c7216 100644
--- 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
diff --git a/lisp/isearch.el b/lisp/isearch.el
index 87f4d495f4e..6d94ef66931 100644
--- a/lisp/isearch.el
+++ b/lisp/isearch.el
@@ -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)))
;;; Toggles for `isearch-regexp-function' and `search-default-mode'.