[Top][All Lists]

[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 ()
-(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)
          (forward-char (if isearch-forward 1 -1))
-      (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)))))
-(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."

reply via email to

[Prev in Thread] Current Thread [Next in Thread]