unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
* bug#14563: Add prefix arg to more isearch commands
@ 2013-06-06  6:30 Juri Linkov
  2013-06-09 20:35 ` Juri Linkov
  0 siblings, 1 reply; 5+ messages in thread
From: Juri Linkov @ 2013-06-06  6:30 UTC (permalink / raw)
  To: 14563

Severity: wishlist
Tags: patch

Since bug#9706 to allow a prefix arg pass to isearch commands
is done now more isearch commands can support prefix args.

bug#10614 and bug#10638 deals with adding a prefix arg to
`isearch-repeat-forward' and `isearch-repeat-backward'.

And the following patch adds a prefix arg to
`isearch-quote-char' (to use the same args as in `quoted-insert'),
`isearch-printing-char' (to use the same args as in `insert-char'),
`isearch-process-search-char' and
`isearch-process-search-multibyte-characters':

=== modified file 'lisp/isearch.el'
--- lisp/isearch.el	2013-06-05 20:57:09 +0000
+++ lisp/isearch.el	2013-06-06 06:28:07 +0000
@@ -2381,9 +2585,11 @@ (defun isearch-other-meta-char (&optiona
           (t;; otherwise nil
 	   (isearch-process-search-string key key)))))
 
-(defun isearch-quote-char ()
-  "Quote special characters for incremental search."
-  (interactive)
+(defun isearch-quote-char (&optional count)
+  "Quote special characters for incremental search.
+With argument, add COUNT copies of the character."
+  (interactive "p")
   (let ((char (read-quoted-char (isearch-message t))))
     ;; Assume character codes 0200 - 0377 stand for characters in some
     ;; single-byte character set, and convert them to Emacs
@@ -2391,24 +2597,27 @@ (defun isearch-quote-char ()
     (if (and isearch-regexp isearch-regexp-lax-whitespace (= char ?\s))
 	(if (subregexp-context-p isearch-string (length isearch-string))
 	    (isearch-process-search-string "[ ]" " ")
-	  (isearch-process-search-char char))
+	  (isearch-process-search-char char count))
       (and enable-multibyte-characters
 	   (>= char ?\200)
 	   (<= char ?\377)
 	   (setq char (unibyte-char-to-multibyte char)))
-      (isearch-process-search-char char))))
+      (isearch-process-search-char char count))))
 
-(defun isearch-printing-char ()
-  "Add this ordinary printing character to the search string and search."
-  (interactive)
-  (let ((char last-command-event))
+(defun isearch-printing-char (&optional char count)
+  "Add this ordinary printing CHAR to the search string and search.
+With argument, add COUNT copies of the character."
+  (interactive (list last-command-event
+		     (prefix-numeric-value current-prefix-arg)))
+  (let ((char (or char last-command-event)))
     (if (= char ?\S-\ )
 	(setq char ?\s))
     (if current-input-method
-	(isearch-process-search-multibyte-characters char)
-      (isearch-process-search-char char))))
+	(isearch-process-search-multibyte-characters char count)
+      (isearch-process-search-char char count))))
 
-(defun isearch-process-search-char (char)
+(defun isearch-process-search-char (char &optional count)
   ;; * and ? are special in regexps when not preceded by \.
   ;; } and | are special in regexps when preceded by \.
   ;; Nothing special for + because it matches at least once.
@@ -2417,12 +2627,15 @@ (defun isearch-process-search-char (char
    ((eq   char ?\})      (isearch-fallback t t))
    ((eq   char ?|)       (isearch-fallback t nil t)))
 
-  ;; Append the char to the search string, update the message and re-search.
-  (isearch-process-search-string
-   (char-to-string char)
-   (if (>= char ?\200)
-       (char-to-string char)
-     (isearch-text-char-description char))))
+  ;; Append the char(s) to the search string,
+  ;; update the message and re-search.
+  (let* ((string (if (and (integerp count) (> count 1))
+		     (make-string count char)
+		   (char-to-string char)))
+	 (message (if (>= char ?\200)
+		      string
+		    (mapconcat 'isearch-text-char-description string ""))))
+    (isearch-process-search-string string message)))
 
 (defun isearch-process-search-string (string message)
   (setq isearch-string (concat isearch-string string)

=== modified file 'lisp/international/isearch-x.el'
--- lisp/international/isearch-x.el	2013-01-01 09:11:05 +0000
+++ lisp/international/isearch-x.el	2013-06-06 06:29:51 +0000
@@ -94,7 +94,7 @@ (defun isearch-with-input-method ()
     (exit-minibuffer)))
 
 ;;;###autoload
-(defun isearch-process-search-multibyte-characters (last-char)
+(defun isearch-process-search-multibyte-characters (last-char &optional count)
   (if (eq this-command 'isearch-printing-char)
       (let ((overriding-terminal-local-map nil)
 	    (prompt (isearch-message-prefix))
@@ -136,8 +136,11 @@ (defun isearch-process-search-multibyte-
 
 	(if (and str (> (length str) 0))
 	    (let ((unread-command-events nil))
-	      (isearch-process-search-string str str))
+	      (if (and (integerp count) (> count 1))
+		  (let ((strs (mapconcat 'identity (make-list count str) "")))
+		    (isearch-process-search-string strs strs))
+		(isearch-process-search-string str str)))
 	  (isearch-update)))
-    (isearch-process-search-char last-char)))
+    (isearch-process-search-char last-char count)))
 
 ;;; isearch-x.el ends here





^ permalink raw reply	[flat|nested] 5+ messages in thread

* bug#14563: Add prefix arg to more isearch commands
  2013-06-06  6:30 bug#14563: Add prefix arg to more isearch commands Juri Linkov
@ 2013-06-09 20:35 ` Juri Linkov
  2013-06-13 21:12   ` Juri Linkov
  0 siblings, 1 reply; 5+ messages in thread
From: Juri Linkov @ 2013-06-09 20:35 UTC (permalink / raw)
  To: 14563

> bug#10614 and bug#10638 deals with adding a prefix arg to
> `isearch-repeat-forward' and `isearch-repeat-backward'.
>
> And the following patch adds a prefix arg to
> `isearch-quote-char' (to use the same args as in `quoted-insert'),
> `isearch-printing-char' (to use the same args as in `insert-char'),
> `isearch-process-search-char' and
> `isearch-process-search-multibyte-characters':

I have no intention to add a prefix arg to all isearch commands
because for some commands a prefix arg doesn't make sense.
For instance, it makes no sense to add a prefix arg to
`isearch-delete-char' since after every DEL it requires
examination to visually confirm that the current search match
is what the user wants (because the search stack is invisible
to the user and it's difficult to keep it in mind and count items
in the stack).

Also a prefix arg for `isearch-yank-word-or-char' is useless too,
because it is too unpredictable in the exact number of characters
it will move forward (depends on the word syntax in the buffer),
so it's difficult for the user to give such a prefix arg that would
move forward the specified amount of unit (characters or words)
and stop at the exact position.

As for `isearch-yank-word' and `isearch-yank-line' it makes sense
to add a prefix arg to them only when a new feature `isearch-allow-move'
(intended to replace these commands) is not going to be added to isearch.el.
In this case a prefix arg for these commands can be added by this patch:

=== modified file 'lisp/isearch.el'
--- lisp/isearch.el	2013-06-06 06:23:19 +0000
+++ lisp/isearch.el	2013-06-09 20:34:11 +0000
@@ -1919,29 +2082,33 @@ (defun isearch-yank-word-or-char ()
 	   (forward-word 1))
        (forward-char 1)) (point))))
 
-(defun isearch-yank-word ()
+(defun isearch-yank-word (&optional arg)
   "Pull next word from buffer into search string."
-  (interactive)
-  (isearch-yank-internal (lambda () (forward-word 1) (point))))
+  (interactive "p")
+  (isearch-yank-internal (lambda () (forward-word arg) (point))))
 
-(defun isearch-yank-line ()
+(defun isearch-yank-line (&optional arg)
   "Pull rest of line from buffer into search string."
-  (interactive)
+  (interactive "p")
   (isearch-yank-internal
    (lambda () (let ((inhibit-field-text-motion t))
-		(line-end-position (if (eolp) 2 1))))))
+		(line-end-position (if (eolp) (1+ arg) arg))))))
 
(defun isearch-char-by-name ()
   "Read a character by its Unicode name and add it to the search string.





^ permalink raw reply	[flat|nested] 5+ messages in thread

* bug#14563: Add prefix arg to more isearch commands
  2013-06-09 20:35 ` Juri Linkov
@ 2013-06-13 21:12   ` Juri Linkov
  2013-06-14 22:30     ` Juri Linkov
  0 siblings, 1 reply; 5+ messages in thread
From: Juri Linkov @ 2013-06-13 21:12 UTC (permalink / raw)
  To: 14563

Additionally, I also fixed the existing arg of `isearch-del-char'
for the case where it failed when its arg is larger than the length
of the search string.  The test case is `C-s C-M-y C-u 2 C-M-w'.





^ permalink raw reply	[flat|nested] 5+ messages in thread

* bug#14563: Add prefix arg to more isearch commands
  2013-06-13 21:12   ` Juri Linkov
@ 2013-06-14 22:30     ` Juri Linkov
  2018-11-20 23:45       ` Juri Linkov
  0 siblings, 1 reply; 5+ messages in thread
From: Juri Linkov @ 2013-06-14 22:30 UTC (permalink / raw)
  To: 14563

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."





^ permalink raw reply	[flat|nested] 5+ messages in thread

* bug#14563: Add prefix arg to more isearch commands
  2013-06-14 22:30     ` Juri Linkov
@ 2018-11-20 23:45       ` Juri Linkov
  0 siblings, 0 replies; 5+ messages in thread
From: Juri Linkov @ 2018-11-20 23:45 UTC (permalink / raw)
  To: 14563-done

> The remaining command that could benefit from a prefix arg is
> `isearch-repeat-forward'.

Implemented in bug#29321 and closed.





^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2018-11-20 23:45 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-06-06  6:30 bug#14563: Add prefix arg to more isearch commands Juri Linkov
2013-06-09 20:35 ` Juri Linkov
2013-06-13 21:12   ` Juri Linkov
2013-06-14 22:30     ` Juri Linkov
2018-11-20 23:45       ` Juri Linkov

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).