unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
From: Juri Linkov <juri@jurta.org>
Subject: Type Ahead Find
Date: Fri, 18 Mar 2005 21:45:29 +0200	[thread overview]
Message-ID: <87k6o4eo2u.fsf@jurta.org> (raw)

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/

             reply	other threads:[~2005-03-18 19:45 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2005-03-18 19:45 Juri Linkov [this message]
2005-03-18 20:21 ` Type Ahead Find Drew Adams
2005-03-18 21:53 ` Stefan Monnier
2005-03-19 12:29   ` Juri Linkov
2005-03-19 21:19     ` Miles Bader
2005-03-19 22:09       ` David Kastrup
2005-03-19 23:33         ` Miles Bader
2005-03-20 20:17           ` Juri Linkov
2005-03-20 21:46             ` David Kastrup
2005-03-20 22:04               ` Miles Bader
2005-03-21 19:28               ` Juri Linkov
2005-03-20 20:14       ` Juri Linkov
2005-03-20 20:22     ` Juri Linkov
2005-03-20  0:22 ` Richard Stallman
2005-03-20 20:19   ` Juri Linkov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87k6o4eo2u.fsf@jurta.org \
    --to=juri@jurta.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).