[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

isearch hooks (was: query-replace-interactive not documented)

From: Juri Linkov
Subject: isearch hooks (was: query-replace-interactive not documented)
Date: Fri, 18 Jun 2004 23:00:09 +0300
User-agent: Gnus/5.110002 (No Gnus v0.2) Emacs/21.3.50 (gnu/linux)

Juri Linkov <address@hidden> writes:
> I noticed that the commentary section of isearch.el has the following
> TODO item:
> ;; - Think about incorporating query-replace.

isearch.el has also another TODO item:

;; - Hooks and options for failed search.

I remember there was a discussion on emacs-devel two months ago about
searching across several buffers or Info nodes.  Adding hooks for
failed and wrapped search will allow to implement these features.

The patch below adds two hooks `isearch-wrapped-hook' and
`isearch-failed-hook'.  When these hooks are not specified, isearch
keeps its current behavior: when failed, it displays "Failing
I-search" message; and when wrapped, it moves the point to the
beginning/end of the buffer.

But with using these hooks many useful things are possible.
For example, to search across Info nodes `isearch-wrapped-hook' can
use `Info-search' to move between Info nodes, and `isearch-failed-hook'
to move to the next Info node immediately:

(add-hook 'Info-mode-hook
 (lambda ()
   (set (make-local-variable 'isearch-wrapped-hook)
        (lambda ()
          (Info-search isearch-string (unless isearch-forward 'backward))
          (goto-char (if isearch-forward (point-min) (point-max)))
          (setq isearch-cmds nil)))
   (set (make-local-variable 'isearch-failed-hook)
        (lambda ()
          (isearch-repeat (if isearch-forward 'forward 'backward))))))

Another example is isearching multiple buffers:

(defvar my-buffer-list nil)

(add-hook 'isearch-mode-hook
          (lambda () (setq my-buffer-list (cdr (buffer-list)))))

(add-hook 'isearch-wrapped-hook
          (lambda ()
            ;; skip buffers with no isearch-string
            (while (and my-buffer-list
                          (switch-to-buffer (car my-buffer-list))
                          (goto-char (point-min))
                          (prog1 (not (re-search-forward isearch-string nil t))
                            (setq my-buffer-list (cdr my-buffer-list))))))
            (goto-char (if isearch-forward (point-min) (point-max)))
            (setq isearch-cmds nil)))

These examples could be developed further to include them into info.el etc.
and to make options to enable hooks.

Anyway, I think the change which allows to call hooks can be installed
now, since it doesn't change the current behavior.

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     18 Jun 2004 16:15:25 -0000
@@ -57,48 +57,6 @@
 ;; keep the behavior.  No point in forcing nonincremental search until
 ;; the last possible moment.
-;; TODO
-;; - Integrate the emacs 19 generalized command history.
-;; - Think about incorporating query-replace.
-;; - Hooks and options for failed search.
 ;;; Change Log:
@@ -199,6 +157,15 @@
 (defvar isearch-mode-end-hook nil
   "Function(s) to call after terminating an incremental search.")
+(defvar isearch-wrapped-hook nil
+  "Function(s) to call when search is wrapped.
+If nil, move point to the beginning of the buffer for forward search,
+or to the end of the buffer for reverse search.")
+(defvar isearch-failed-hook nil
+  "Function(s) to call when search is failed.
+If nil, ding.")
 ;; Search ring.
 (defvar search-ring nil
@@ -990,7 +968,9 @@
        ;; If already have what to search for, repeat it.
        (or isearch-success
-             (goto-char (if isearch-forward (point-min) (point-max)))
+             (if isearch-wrapped-hook
+                  (run-hooks 'isearch-wrapped-hook)
+                (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 +1867,7 @@
   (or isearch-success (setq ellipsis nil))
   (let ((m (concat (if isearch-success "" "failing ")
                   (if (and isearch-wrapped
+                           (not isearch-wrapped-hook)
                            (if isearch-forward
                                (> (point) isearch-opoint)
                              (< (point) isearch-opoint)))
@@ -1876,9 +1961,9 @@
   (if isearch-success
     ;; 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 3 (car isearch-cmds)) (or isearch-failed-hook (ding)))
+    (goto-char (nth 2 (car isearch-cmds)))
+    (if isearch-failed-hook (run-hooks 'isearch-failed-hook))))
 ;; Called when opening an overlay, and we are still in isearch.

Juri Linkov

reply via email to

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