[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 @@
isearch-lazy-highlight-window-end))))
;; 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)
isearch-lazy-highlight-last-string
(if isearch-forward
@@ -2404,7 +2412,14 @@
(if isearch-lazy-highlight-wrapped
isearch-lazy-highlight-end
(window-start))))
- 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)
(save-match-data
(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)
(save-match-data
(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 "\^_"))
--
Juri Linkov
http://www.jurta.org/emacs/
- Type Ahead Find,
Juri Linkov <=
- RE: Type Ahead Find, Drew Adams, 2005/03/18
- Re: Type Ahead Find, Stefan Monnier, 2005/03/18
- Re: Type Ahead Find, Juri Linkov, 2005/03/19
- Re: Type Ahead Find, Miles Bader, 2005/03/19
- Re: Type Ahead Find, David Kastrup, 2005/03/19
- Re: Type Ahead Find, Miles Bader, 2005/03/19
- Re: Type Ahead Find, Juri Linkov, 2005/03/20
- Re: Type Ahead Find, David Kastrup, 2005/03/20
- Re: Type Ahead Find, Miles Bader, 2005/03/20
- Re: Type Ahead Find, Juri Linkov, 2005/03/21