[Top][All Lists]

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

Type Ahead Find

From: Juri Linkov
Subject: Type Ahead Find
Date: Fri, 18 Mar 2005 21:45:29 +0200
User-agent: Gnus/5.110002 (No Gnus v0.2) Emacs/22.0.50 (gnu/linux)

Many modern applications provide a feature called "type-ahead find".
In fact, this is rather a poor imitation of Emacs incremental search
with many limitations.  But it allows to narrow the search only
to specific text part (such as e.g. in Firefox typing a ' before the
search string searches only links) which is currently not easily
implementable in Emacs.  However, a simple 4-line change in isearch.el
will allow this.  The idea is to add a new variable to hold a predicate
function which, when called on the new search position, will return nil
when the current search point should be skipped.  Such a function,
when defined, will be used instead of the default `isearch-range-invisible'
to allow searching even in hidden parts.

One of possible uses of such a variable is to search only references,
menu items, indexes and links in Info manuals with simple code like this:

(set (make-local-variable 'isearch-success-function)
     (lambda () (save-match-data
         (setq isearch-error
               (or (Info-get-token (point)
                    "[hf]t?tp://" "[hf]t?tp://\\([^ \t\n\"`({<>})']+\\)")
                   (Info-get-token (point)
                    "\\*note[ \n\t]+"
                    "\\*note[ \n\t]+\\([^:]*\\):\\(:\\|[ \n\t]*(\\)?")
                   (Info-get-token (point) "\\* +" "\\* +\\([^:]*\\)::")
                   (Info-get-token (point) "\\* +" "\\* +\\(.*\\): "))))))

It displays the name of the current objects under point in square
brackets, so e.g. `C-s gnu' in the top node of the Emacs manual produces:

I-search: gnu [GNU Free Documentation License]

where `GNU Free Documentation License' is the menu item and node name
under the search point.

This change will also allow to implement links-only search in the
Emacs w3m browser with the following simple code:

(set (make-local-variable 'isearch-success-function)
     (lambda () (save-match-data (setq isearch-error (w3m-anchor)))))

which will display a link under the search point in square brackets:

I-search: gnu [http://www.gnu.org/]

This change has many other possible uses like for example searching
only in comments with:

(set (make-local-variable 'isearch-success-function)
     (lambda () (save-match-data (save-excursion (comment-beginning)))))

All this can be done with a new variable `isearch-success-function'.
In contrast with `isearch-search-fun-function' which mainly is used to
widen the search space (e.g. to other Info nodes, etc.), the new
variable `isearch-success-function' narrows the standard search space
to specific buffer regions.  It removes the need to write a complicated
search function for `isearch-search-fun-function'.

The patch below also fixes lazy highlighting to support
`isearch-success-function' with changing `isearch-lazy-highlight-search'
to look more like `isearch-search', i.e. to add a similar retry-success
while-loop, which also with using of `isearch-range-invisible' (when
`isearch-success-function' is nil) reduces the amount of created overlays
that currently are created in the hidden text.

The test for `(not isearch-error)' was removed from
`isearch-lazy-highlight-new-loop' to allow displaying the names
in square brackets (`isearch-lazy-highlight-search' takes care
about incomplete regexps).

There is also a similar change in info.el.

The actual code that would use this new variable and user interface
for its activating is a separate question.

Index: lisp/isearch.el
RCS file: /cvsroot/emacs/emacs/lisp/isearch.el,v
retrieving revision 1.261
diff -u -w -b -r1.261 isearch.el
--- lisp/isearch.el     18 Mar 2005 09:59:31 -0000      1.261
+++ lisp/isearch.el     18 Mar 2005 19:32:34 -0000
@@ -165,6 +165,9 @@
   "Function to save a function restoring the mode-specific isearch state
 to the search status stack.")
+(defvar isearch-success-function nil
+  "Function to report whether the new search match is considered successful.")
 ;; Search ring.
 (defvar search-ring nil
@@ -2056,8 +2059,10 @@
                  (not isearch-success)
                  (bobp) (eobp)
                  (= (match-beginning 0) (match-end 0))
+                 (if isearch-success-function
+                     (funcall isearch-success-function)
                  (not (isearch-range-invisible
-                       (match-beginning 0) (match-end 0))))
+                         (match-beginning 0) (match-end 0)))))
              (setq retry nil)))
        (setq isearch-just-started nil)
        (if isearch-success
@@ -2369,7 +2374,6 @@
     ;; something important did indeed change
     (lazy-highlight-cleanup t) ;kill old loop & remove overlays
-    (when (not isearch-error)
       (setq isearch-lazy-highlight-start-limit beg
            isearch-lazy-highlight-end-limit end)
       (setq isearch-lazy-highlight-window       (selected-window)
@@ -2384,7 +2388,7 @@
       (unless (equal isearch-string "")
        (setq isearch-lazy-highlight-timer
              (run-with-idle-timer lazy-highlight-initial-delay nil
-                                  'isearch-lazy-highlight-update))))))
+                                'isearch-lazy-highlight-update)))))
 (defun isearch-lazy-highlight-search ()
   "Search ahead for the next or previous match, for lazy highlighting.
@@ -2393,6 +2397,10 @@
        (isearch-regexp isearch-lazy-highlight-regexp)
        (search-spaces-regexp search-whitespace-regexp))
     (condition-case nil
+       (let ((retry t)
+             (success nil))
+         (while retry
+           (setq success
        (funcall (isearch-search-fun)
                 (if isearch-forward
@@ -2404,7 +2412,14 @@
                        (if isearch-lazy-highlight-wrapped
-                t)
+                          t))
+           (if (or (not success)
+                   (if isearch-success-function
+                       (funcall isearch-success-function)
+                     (not (isearch-range-invisible
+                           (match-beginning 0) (match-end 0)))))
+               (setq retry nil)))
+         success)
       (error nil))))
 (defun isearch-lazy-highlight-update ()

Index: lisp/info.el
RCS file: /cvsroot/emacs/emacs/lisp/info.el,v
retrieving revision 1.421
diff -u -r1.421 info.el
--- lisp/info.el        16 Mar 2005 07:32:43 -0000      1.421
+++ lisp/info.el        18 Mar 2005 19:33:20 -0000
@@ -1505,9 +1505,11 @@
          (while (and (not give-up)
                        (or (null found)
-                           (if backward
-                               (isearch-range-invisible found beg-found)
-                             (isearch-range-invisible beg-found found))
+                           (if isearch-success-function
+                               (not (funcall isearch-success-function))
+                             (if backward
+                                 (isearch-range-invisible found beg-found)
+                               (isearch-range-invisible beg-found found)))
                            ;; Skip node header line
                            (and (save-excursion (forward-line -1)
                                                 (looking-at "\^_"))
@@ -1593,9 +1595,11 @@
                (while (and (not give-up)
                              (or (null found)
-                                 (if backward
-                                     (isearch-range-invisible found beg-found)
-                                   (isearch-range-invisible beg-found found))
+                                 (if isearch-success-function
+                                     (not (funcall isearch-success-function))
+                                   (if backward
+                                       (isearch-range-invisible found 
+                                     (isearch-range-invisible beg-found 
                                  ;; Skip node header line
                                  (and (save-excursion (forward-line -1)
                                                       (looking-at "\^_"))

Juri Linkov

reply via email to

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