[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
bug#14563: Add prefix arg to more isearch commands
From: |
Juri Linkov |
Subject: |
bug#14563: Add prefix arg to more isearch commands |
Date: |
Sat, 15 Jun 2013 01:30:15 +0300 |
User-agent: |
Gnus/5.13 (Gnus v5.13) Emacs/24.3.50 (x86_64-pc-linux-gnu) |
The remaining command that could benefit from a prefix arg is
`isearch-repeat-forward'. There are 4 places on the call stack
that can process the count argument: `isearch-repeat-forward',
`isearch-repeat', `isearch-search', `isearch-search-string'.
`isearch-repeat-forward' is too high-level, so repeating
the call to the more low-level `isearch-repeat' COUNT times
has such bad effects as pushing to the search stack all
intermediate positions (because `isearch-repeat' calls
`isearch-push-state' on every invocation), so e.g.
`C-s str C-u 42 C-s DEL DEL DEL ...' requires 42 DELs
to return to the first match instead of just 1 `DEL',
And it also flickers because `isearch-update' quickly
highlights all visited matches.
OTOH, `isearch-search-string' is too low-level because passing
the COUNT argument to search functions like `search-forward'
doesn't skip invisible matches and other additional processing
in `isearch-search'.
So the most appropriate place to implement a prefix arg
is `isearch-repeat':
=== modified file 'lisp/isearch.el'
--- lisp/isearch.el 2013-06-13 22:08:45 +0000
+++ lisp/isearch.el 2013-06-14 22:28:27 +0000
@@ -1393,8 +1462,10 @@ (defun isearch-abort ()
(isearch-pop-state))
(isearch-update)))
-(defun isearch-repeat (direction)
+(defun isearch-repeat (direction &optional arg)
;; Utility for isearch-repeat-forward and -backward.
+ (unless arg (setq arg 1))
+
(if (eq isearch-forward (eq direction 'forward))
;; C-s in forward or C-r in reverse.
(if (equal isearch-string "")
@@ -1410,21 +1481,25 @@ (defun isearch-repeat (direction)
isearch-success t))
(setq isearch-barrier (point)) ; For subsequent \| if regexp.
+ (if (< arg 0) (setq arg (abs arg) isearch-forward (not isearch-forward)))
(if (equal isearch-string "")
(setq isearch-success t)
+ (let ((count arg)
+ ;; Don't remember intermediate states in global `isearch-cmds'.
+ (isearch-cmds isearch-cmds))
+ (while (> count 0)
(if (and isearch-success
(equal (point) isearch-other-end)
(not isearch-just-started))
@@ -1437,20 +1512,33 @@ (defun isearch-repeat (direction)
(ding))
(forward-char (if isearch-forward 1 -1))
(isearch-search))
- (isearch-search)))
+ (isearch-search))
+ (when (> count 1)
+ ;; For the next iteration, add the current state to `isearch-cmds',
+ ;; so that next failed `isearch-search' could restore old position.
+ (isearch-push-state)
+ (unless isearch-success
+ ;; Wrap the search with code like above.
+ (setq isearch-wrapped t)
+ (if isearch-wrap-function
+ (funcall isearch-wrap-function)
+ (goto-char (if isearch-forward (point-min) (point-max))))))
+ (setq count (1- count)))))
(isearch-push-state)
(isearch-update))
-(defun isearch-repeat-forward ()
- "Repeat incremental search forwards."
- (interactive)
- (isearch-repeat 'forward))
+(defun isearch-repeat-forward (&optional arg)
+ "Repeat incremental search forwards.
+With argument, repeat search ARG times."
+ (interactive "p")
+ (isearch-repeat 'forward arg))
-(defun isearch-repeat-backward ()
- "Repeat incremental search backwards."
- (interactive)
- (isearch-repeat 'backward))
+(defun isearch-repeat-backward (&optional arg)
+ "Repeat incremental search backwards.
+With argument, repeat search ARG times."
+ (interactive "p")
+ (isearch-repeat 'backward arg))
(defun isearch-toggle-regexp ()
"Toggle regexp searching on or off."