From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Juri Linkov Newsgroups: gmane.emacs.bugs Subject: bug#14742: 24.3.50; enhancement request: be able to prepend stuff from buffer when search backward Date: Sat, 06 Jul 2013 01:28:15 +0300 Organization: JURTA Message-ID: <877gh43ara.fsf@mail.jurta.org> References: <4b9029ca-1775-482f-ba9a-46a891be7405@default> <87sj01c3n2.fsf@mail.jurta.org> <7518b30b-63d2-40ea-956f-a504f40c4cfd@default> <87haggoc6r.fsf@mail.jurta.org> <8ada7269-baa9-483f-9595-d46619393aa7@default> <87y59ok18k.fsf@mail.jurta.org> <6ae1046e-e6ae-43ae-96ff-064fd01c9ec2@default> <87k3l8ik77.fsf@mail.jurta.org> <87k3l79seh.fsf@mail.jurta.org> <9fa6642c-dbcb-47aa-a8a3-29ee892bd933@default> <87y59lc32c.fsf@mail.jurta.org> NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: text/plain X-Trace: ger.gmane.org 1373063892 18628 80.91.229.3 (5 Jul 2013 22:38:12 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Fri, 5 Jul 2013 22:38:12 +0000 (UTC) Cc: 14742@debbugs.gnu.org To: Stefan Monnier Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Sat Jul 06 00:38:13 2013 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by plane.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1UvEdn-0003PW-Pa for geb-bug-gnu-emacs@m.gmane.org; Sat, 06 Jul 2013 00:38:12 +0200 Original-Received: from localhost ([::1]:47513 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UvEdn-0001NY-E2 for geb-bug-gnu-emacs@m.gmane.org; Fri, 05 Jul 2013 18:38:11 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:34963) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UvEdh-0001K4-Bk for bug-gnu-emacs@gnu.org; Fri, 05 Jul 2013 18:38:07 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1UvEde-00054E-HN for bug-gnu-emacs@gnu.org; Fri, 05 Jul 2013 18:38:05 -0400 Original-Received: from debbugs.gnu.org ([140.186.70.43]:38666) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1UvEde-00054A-DJ for bug-gnu-emacs@gnu.org; Fri, 05 Jul 2013 18:38:02 -0400 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.80) (envelope-from ) id 1UvEde-0002Yv-1M for bug-gnu-emacs@gnu.org; Fri, 05 Jul 2013 18:38:02 -0400 X-Loop: help-debbugs@gnu.org Resent-From: Juri Linkov Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Fri, 05 Jul 2013 22:38:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 14742 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: Original-Received: via spool by 14742-submit@debbugs.gnu.org id=B14742.13730638589799 (code B ref 14742); Fri, 05 Jul 2013 22:38:01 +0000 Original-Received: (at 14742) by debbugs.gnu.org; 5 Jul 2013 22:37:38 +0000 Original-Received: from localhost ([127.0.0.1]:32982 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.80) (envelope-from ) id 1UvEdF-0002Xy-RY for submit@debbugs.gnu.org; Fri, 05 Jul 2013 18:37:38 -0400 Original-Received: from ps18281.dreamhost.com ([69.163.218.105]:44543 helo=ps18281.dreamhostps.com) by debbugs.gnu.org with esmtp (Exim 4.80) (envelope-from ) id 1UvEdC-0002XT-8e for 14742@debbugs.gnu.org; Fri, 05 Jul 2013 18:37:35 -0400 Original-Received: from localhost (ps18281.dreamhostps.com [69.163.218.105]) by ps18281.dreamhostps.com (Postfix) with ESMTP id AC029258B9E920; Fri, 5 Jul 2013 15:37:32 -0700 (PDT) In-Reply-To: (Stefan Monnier's message of "Fri, 05 Jul 2013 06:37:39 -0400") User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/24.3.50 (x86_64-pc-linux-gnu) X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.15 Precedence: list X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 140.186.70.43 X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Original-Sender: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.bugs:75963 Archived-At: > Could you move this new code to a separate function? In the following patch I moved new code to a separate function `isearch-yank-or-del' that works like a combination of the existing functions `isearch-yank-string' and `isearch-del-char'. `isearch-yank-or-del' is general enough that it can be used separately from the movement-yanking feature. The remaining code in `isearch-other-meta-char' is also general enough that it can be used to implement other features as well. For example, I tried to replace the call `(isearch-yank-or-del (point) new-point)' with `(goto-char new-point)' and got another useful fully working feature mentioned by Drew in this thread where cursor movement doesn't yank text. This raises the question how users would be able to select between these alternatives. Maybe `isearch-allow-move' should provide two options: - `jump' that doesn't yank text during cursor movement; - `yank' to yank text during cursor movement. These options could be implemented in the next patch, whereas this patch just moves yanking/deleting to a new function `isearch-yank-or-del'. === modified file 'lisp/isearch.el' --- lisp/isearch.el 2013-06-13 22:08:45 +0000 +++ lisp/isearch.el 2013-07-05 22:27:08 +0000 @@ -987,6 +1046,8 @@ (defun isearch-update () ;; We must prevent the point moving to the end of composition when a ;; part of the composition has just been searched. (setq disable-point-adjustment t) + (when (eq (car-safe isearch-allow-move) 'only) + (setq isearch-allow-move (cdr isearch-allow-move))) (run-hooks 'isearch-update-post-hook)) (defun isearch-done (&optional nopush edit) @@ -1969,6 +2142,56 @@ (defun isearch-yank-line (&optional arg) (lambda () (let ((inhibit-field-text-motion t)) (line-end-position (if (eolp) (1+ arg) arg)))))) +(defun isearch-yank-or-del (old-point new-point) + "Add or delete text in search string, depending on two given positions. +Given an old position of point in OLD-POINT and a new position NEW-POINT, +either pull text from the buffer between these positions into the search +string, or delete text from the search string to the length of the text +between these positions. +In forward search, when NEW-POINT is greater than OLD-POINT, +yank text from the buffer between NEW-POINT and OLD-POINT; +when NEW-POINT is less than OLD-POINT, delete text from +the search string between NEW-POINT and OLD-POINT. +In reverse search, when NEW-POINT is greater than OLD-POINT, +delete text from the search string between NEW-POINT and OLD-POINT; +when NEW-POINT is less than OLD-POINT, yank text from the buffer +between NEW-POINT and OLD-POINT. +When NEW-POINT is less than the beginning of the currently matched string +in forward search, then change search direction to reverse search. +When NEW-POINT is greater than the end of the currently matched string +in reverse search, then change search direction to forward search." + ;; Change search direction between forward and backward. + (when (if isearch-other-end + (and (not isearch-error) ; for regexp incomplete input + (if isearch-forward + (< new-point isearch-other-end) + (> new-point isearch-other-end))) + (if isearch-forward + (< new-point old-point) + (> new-point old-point))) + (setq isearch-forward (not isearch-forward)) + (setq isearch-string "" isearch-message "") + (if isearch-other-end (setq old-point isearch-other-end))) + (if (< old-point new-point) + (if isearch-forward + ;; Add text to the search string. + (isearch-yank-string + (buffer-substring-no-properties old-point new-point)) + ;; In reverse search, lax whitespace doesn't work, + ;; so go to the new point explicitly. + (goto-char new-point) + ;; In reverse search, delete text from beginning of search string. + (isearch-del-char (- new-point old-point) t)) + (if isearch-forward + ;; Delete text from the search string. + (isearch-del-char (- old-point new-point)) + ;; In reverse search, lax whitespace doesn't work, + ;; so go to the new point explicitly. + (goto-char new-point) + ;; In reverse search, add text to beginning of search string. + (isearch-yank-string + (buffer-substring-no-properties old-point new-point) t)))) + (defun isearch-char-by-name (&optional count) "Read a character by its Unicode name and add it to the search string. Completion is available like in `read-char-by-name' used by `insert-char'. @@ -2267,6 +2483,77 @@ (defun isearch-lookup-scroll-key (key-se (eq (get binding 'scroll-command) t)) binding))) +(defcustom isearch-allow-move nil + "Whether cursor movement is allowed to yank text in Isearch mode. +If nil, point motion commands will exit Isearch mode immediately. +If non-nil, point motion commands extend Isearch by yanking the text +the cursor moves over in the buffer. E.g., `C-f' yanks the next char, +`C-M-f' yanks the next expression, etc. to the end of the search string +in forward search. In reverse search, `C-b' yanks the previous char, +`C-M-b' yanks the previous expression, etc. to the beginning of the +search string. And conversely, backward cursor movements, e.g., `C-b' +deletes text from the end of the search string when searching forward. +When searching backward, forward cursor movements, e.g., `C-f' deletes +text from the beginning of the search string. + +Lisp programs may give this variable a special value of +\(only . OLDVAL) to enable motion yanking temporarily. +After any subsequent Isearch command that is not point motion, +the value of `isearch-allow-move' is set to OLDVAL." + :type 'boolean + :version "24.4" + :group 'isearch) + (defalias 'isearch-other-control-char 'isearch-other-meta-char) (defun isearch-other-meta-char (&optional arg) @@ -2292,7 +2579,7 @@ (defun isearch-other-meta-char (&optiona (this-command-keys))) (main-event (aref key 0)) (keylist (listify-key-sequence key)) - scroll-command isearch-point) + scroll-command move-command isearch-point) (cond ((and (= (length key) 1) (let ((lookup (lookup-key local-function-key-map key))) (not (or (null lookup) (integerp lookup) @@ -2379,7 +2666,35 @@ (defun isearch-other-meta-char (&optiona (if ab-bel (isearch-back-into-window (eq ab-bel 'above) isearch-point) (goto-char isearch-point))) (isearch-update)) + ;; Handle a motion function. + ((and isearch-allow-move + (progn (setq key (isearch-reread-key-sequence-naturally keylist)) + (setq keylist (listify-key-sequence key)) + (setq main-event (aref key 0)) + (setq move-command (or + (isearch-lookup-move-key key) + (isearch-lookup-move-key + ;; Use the last key in the sequence. + (vector (aref key (1- (length key))))))))) + (setq prefix-arg arg) + (let ((new-point (save-excursion + (condition-case () + (command-execute move-command) + (error nil)) + (point)))) + ;; An alternative to move without yanking is (goto-char new-point) + (isearch-yank-or-del (point) new-point)) + (unless (eq (car-safe isearch-allow-move) 'only) + (setq isearch-allow-move (cons 'only isearch-allow-move)))) ;; A mouse click on the isearch message starts editing the search string ((and (eq (car-safe main-event) 'down-mouse-1) (window-minibuffer-p (posn-window (event-start main-event))))