From mboxrd@z Thu Jan 1 00:00:00 1970 Path: main.gmane.org!not-for-mail From: Juri Linkov Newsgroups: gmane.emacs.devel Subject: Re: isearch hooks Date: Sat, 19 Jun 2004 21:36:18 +0300 Organization: JURTA Sender: emacs-devel-bounces+emacs-devel=quimby.gnus.org@gnu.org Message-ID: <87smcro0nx.fsf@mail.jurta.org> References: <20040528.181649.25475113.wl@gnu.org> <200405291737.i4THbPJ06689@raven.dms.auburn.edu> <878yeyczec.fsf@mail.jurta.org> <87n03aa4jk.fsf@mail.jurta.org> <87d63wy6ux.fsf_-_@mail.jurta.org> NNTP-Posting-Host: deer.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-Trace: sea.gmane.org 1087670471 16611 80.91.224.253 (19 Jun 2004 18:41:11 GMT) X-Complaints-To: usenet@sea.gmane.org NNTP-Posting-Date: Sat, 19 Jun 2004 18:41:11 +0000 (UTC) Cc: emacs-devel@gnu.org Original-X-From: emacs-devel-bounces+emacs-devel=quimby.gnus.org@gnu.org Sat Jun 19 20:41:04 2004 Return-path: Original-Received: from quimby.gnus.org ([80.91.224.244]) by deer.gmane.org with esmtp (Exim 3.35 #1 (Debian)) id 1Bbkm0-0005IJ-00 for ; Sat, 19 Jun 2004 20:41:04 +0200 Original-Received: from lists.gnu.org ([199.232.76.165]) by quimby.gnus.org with esmtp (Exim 3.35 #1 (Debian)) id 1Bbklz-0007p3-00 for ; Sat, 19 Jun 2004 20:41:03 +0200 Original-Received: from localhost ([127.0.0.1] helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.33) id 1Bbkn9-0007DS-GA for emacs-devel@quimby.gnus.org; Sat, 19 Jun 2004 14:42:15 -0400 Original-Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.33) id 1Bbkn7-0007Bs-29 for emacs-devel@gnu.org; Sat, 19 Jun 2004 14:42:13 -0400 Original-Received: from exim by lists.gnu.org with spam-scanned (Exim 4.33) id 1Bbkn4-00077u-3N for emacs-devel@gnu.org; Sat, 19 Jun 2004 14:42:12 -0400 Original-Received: from [199.232.76.173] (helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.33) id 1Bbkn4-00077n-18 for emacs-devel@gnu.org; Sat, 19 Jun 2004 14:42:10 -0400 Original-Received: from [66.33.219.19] (helo=spoon.dreamhost.com) by monty-python.gnu.org with esmtp (Exim 4.34) id 1Bbklj-0001xv-5S; Sat, 19 Jun 2004 14:40:47 -0400 Original-Received: from mail.jurta.org (80-235-35-146-dsl.mus.estpak.ee [80.235.35.146]) by spoon.dreamhost.com (Postfix) with ESMTP id 63A8A13D8C4; Sat, 19 Jun 2004 11:40:44 -0700 (PDT) Original-To: rms@gnu.org In-Reply-To: (Richard Stallman's message of "Fri, 18 Jun 2004 23:19:32 -0400") User-Agent: Gnus/5.110002 (No Gnus v0.2) Emacs/21.3.50 (gnu/linux) X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.4 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+emacs-devel=quimby.gnus.org@gnu.org Xref: main.gmane.org gmane.emacs.devel:25110 X-Report-Spam: http://spam.gmane.org/gmane.emacs.devel:25110 Richard Stallman writes: > The patch below adds two hooks `isearch-wrapped-hook' and > `isearch-failed-hook'. > > Thanks for working on it. > > However, I have a feeling that `isearch-failed-hook' is not > implemented properly for the intended use. If isearch should move > between info nodes, the natural way is that a failing search should > switch nodes and then try again. To do that, this hook should run > shortly after the actual search primitive, and it should be run with > run-hook-with-args-until-success, and if it succeeds then > isearch-success should be t--as if the search primitive had succeeded. > So it won't put "Failed " in the echo area, for instance. This seems to be the right place to call the hook. > I just looked at isearch.el and came across isearch-search-fun-function. > I have a feeling that the right way to make isearch search through > multiple nodes or buffers is to define a new low-level search function > and interface it through isearch-search-fun-function. > > Does that look right to you? It doesn't look right since `isearch-search-fun' is used to specify the function to call for the search different from the default `search-forward' or `re-search-forward'. But in the intended cases default functions are suitable to search the text in the buffer. What is needed is to switch locations on the search when the search in the current buffers is failed. In the newest version I added a new variable `isearch-wrap-failed'. If it is set to non-nil the search will not pause for displaying the message "Failing I-search..." but will immediately wrap the search to the location found by `isearch-wrap-functions'. If `isearch-wrap-failed' is nil and `isearch-wrap-functions' are specified, these hooks are called in another place, where currently the point is moved to the beginning/end of the buffer. And below is the hook which works for moving between Info nodes. It sets isearch-cmds to nil, because it's impossible to restore previous positions in visited Info nodes by typing DEL in isearch mode. If it is ok, it could be added to info.el to be activated by some option or minor mode. (add-hook 'isearch-wrap-functions (lambda () (Info-search isearch-string (unless isearch-forward 'backward)) (goto-char (if isearch-forward (point-min) (point-max))) (setq isearch-cmds nil) t) nil t) (set (make-local-variable 'isearch-wrap-failed) t) There is also the patch to info.el below after isearch.el which implements a backward search in Info mode. Index: lisp/isearch.el =================================================================== RCS file: /cvsroot/emacs/emacs/lisp/isearch.el,v retrieving revision 1.228 diff -u -r1.228 isearch.el --- lisp/isearch.el 6 Jun 2004 13:57:39 -0000 1.228 +++ lisp/isearch.el 19 Jun 2004 18:02:39 -0000 @@ -199,6 +157,14 @@ (defvar isearch-mode-end-hook nil "Function(s) to call after terminating an incremental search.") +(defvar isearch-wrap-functions nil + "Function(s) to call to wrap the search when search is failed. +If nil, move point to the beginning of the buffer for a forward search, +or to the end of the buffer for a backward search.") + +(defvar isearch-wrap-failed nil + "If non-nil, search is wrapped immediately after failing.") + ;; Search ring. (defvar search-ring nil @@ -990,8 +967,12 @@ ;; If already have what to search for, repeat it. (or isearch-success (progn - (goto-char (if isearch-forward (point-min) (point-max))) - (setq isearch-wrapped t)))) + ;; `isearch-search' takes care of the following condition + (when (not (and isearch-wrap-functions isearch-wrap-failed)) + (if isearch-wrap-functions + (run-hook-with-args-until-success 'isearch-wrap-functions) + (goto-char (if isearch-forward (point-min) (point-max)))) + (setq isearch-wrapped t))))) ;; C-s in reverse or C-r in forward, change direction. (setq isearch-forward (not isearch-forward))) @@ -1786,6 +1885,7 @@ (or isearch-success (setq ellipsis nil)) (let ((m (concat (if isearch-success "" "failing ") (if (and isearch-wrapped + (not isearch-wrap-functions) (if isearch-forward (> (point) isearch-opoint) (< (point) isearch-opoint))) @@ -1836,7 +1939,8 @@ (let ((inhibit-point-motion-hooks search-invisible) (inhibit-quit nil) (case-fold-search isearch-case-fold-search) - (retry t)) + (retry t) + (m nil)) (if isearch-regexp (setq isearch-invalid-regexp nil)) (setq isearch-within-brackets nil) (while retry @@ -1852,7 +1956,15 @@ (= (match-beginning 0) (match-end 0)) (not (isearch-range-invisible (match-beginning 0) (match-end 0)))) - (setq retry nil))) + (setq retry nil)) + (if (and isearch-wrap-failed isearch-wrap-functions + (not isearch-success) + (not (and (markerp m) + (eq (marker-buffer m) (current-buffer)) + (eq (marker-position m) (point)))) + (run-hook-with-args-until-success + 'isearch-wrap-functions)) + (setq retry t m (point-marker) isearch-wrapped t))) (setq isearch-just-started nil) (if isearch-success (setq isearch-other-end @@ -1878,7 +1990,8 @@ ;; Ding if failed this time after succeeding last time. (and (nth 3 (car isearch-cmds)) (ding)) - (goto-char (nth 2 (car isearch-cmds))))) + (and (nth 2 (car isearch-cmds)) + (goto-char (nth 2 (car isearch-cmds)))))) ;; Called when opening an overlay, and we are still in isearch. Index: lisp/info.el =================================================================== RCS file: /cvsroot/emacs/emacs/lisp/info.el,v retrieving revision 1.398 diff -u -r1.398 info.el --- lisp/info.el 12 Jun 2004 05:54:43 -0000 1.398 +++ lisp/info.el 19 Jun 2004 18:31:05 -0000 @@ -1442,8 +1442,9 @@ (defvar Info-search-case-fold nil "The value of `case-fold-search' from previous `Info-search' command.") -(defun Info-search (regexp) - "Search for REGEXP, starting from point, and select node it's found in." +(defun Info-search (regexp &optional direction) + "Search for REGEXP, starting from point, and select node it's found in. +If DIRECTION is `backward', search in the reverse direction." (interactive (list (read-string (if Info-search-history (format "Regexp search%s (default `%s'): " @@ -1458,6 +1459,7 @@ (setq regexp (car Info-search-history))) (when regexp (let (found beg-found give-up + (backward (eq direction 'backward)) (onode Info-current-node) (ofile Info-current-file) (opoint (point)) @@ -1472,14 +1474,21 @@ (widen) (while (and (not give-up) (or (null found) - (isearch-range-invisible beg-found found))) - (if (re-search-forward regexp nil t) - (setq found (point) beg-found (match-beginning 0)) + (if backward + (isearch-range-invisible found beg-found) + (isearch-range-invisible beg-found found)))) + (if (if backward + (re-search-backward regexp nil t) + (re-search-forward regexp nil t)) + (setq found (point) beg-found (if backward (match-end 0) + (match-beginning 0))) (setq give-up t))))) ;; If no subfiles, give error now. (if give-up (if (null Info-current-subfile) - (re-search-forward regexp) + (if backward + (re-search-backward regexp) + (re-search-forward regexp)) (setq found nil))) (unless found @@ -1498,29 +1507,39 @@ ;; Find the subfile we just searched. (search-forward (concat "\n" osubfile ": ")) ;; Skip that one. - (forward-line 1) + (forward-line (if backward 0 1)) ;; Make a list of all following subfiles. ;; Each elt has the form (VIRT-POSITION . SUBFILENAME). - (while (not (eobp)) - (re-search-forward "\\(^.*\\): [0-9]+$") + (while (not (if backward (bobp) (eobp))) + (if backward + (re-search-backward "\\(^.*\\): [0-9]+$") + (re-search-forward "\\(^.*\\): [0-9]+$")) (goto-char (+ (match-end 1) 2)) (setq list (cons (cons (+ (point-min) (read (current-buffer))) (match-string-no-properties 1)) list)) - (goto-char (1+ (match-end 0)))) + (goto-char (if backward + (1- (match-beginning 0)) + (1+ (match-end 0))))) ;; Put in forward order (setq list (nreverse list)))) (while list (message "Searching subfile %s..." (cdr (car list))) (Info-read-subfile (car (car list))) + (if backward (goto-char (point-max))) (setq list (cdr list)) (setq give-up nil found nil) (while (and (not give-up) (or (null found) - (isearch-range-invisible beg-found found))) - (if (re-search-forward regexp nil t) - (setq found (point) beg-found (match-beginning 0)) + (if backward + (isearch-range-invisible found beg-found) + (isearch-range-invisible beg-found found)))) + (if (if backward + (re-search-backward regexp nil t) + (re-search-forward regexp nil t)) + (setq found (point) beg-found (if backward (match-end 0) + (match-beginning 0))) (setq give-up t))) (if give-up (setq found nil)) @@ -1556,6 +1575,19 @@ (if Info-search-history (Info-search (car Info-search-history)) (call-interactively 'Info-search)))) + +(defun Info-search-backward (regexp) + "Search for REGEXP in the reverse direction." + (interactive (list (read-string + (if Info-search-history + (format "Regexp search%s backward (default `%s'): " + (if case-fold-search "" " case-sensitively") + (car Info-search-history)) + (format "Regexp search%s backward: " + (if case-fold-search "" " case-sensitively"))) + nil 'Info-search-history))) + (Info-search regexp 'backward)) + (defun Info-extract-pointer (name &optional errorname) "Extract the value of the node-pointer named NAME. -- Juri Linkov http://www.jurta.org/emacs/