unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* Type Ahead Find
@ 2005-03-18 19:45 Juri Linkov
  2005-03-18 20:21 ` Drew Adams
                   ` (2 more replies)
  0 siblings, 3 replies; 15+ messages in thread
From: Juri Linkov @ 2005-03-18 19:45 UTC (permalink / 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/

^ permalink raw reply	[flat|nested] 15+ messages in thread

* RE: Type Ahead Find
  2005-03-18 19:45 Type Ahead Find Juri Linkov
@ 2005-03-18 20:21 ` Drew Adams
  2005-03-18 21:53 ` Stefan Monnier
  2005-03-20  0:22 ` Richard Stallman
  2 siblings, 0 replies; 15+ messages in thread
From: Drew Adams @ 2005-03-18 20:21 UTC (permalink / raw)


Tres cool. Very useful. (Haven't tried it, but the description sells it, to
me.)

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: Type Ahead Find
  2005-03-18 19:45 Type Ahead Find Juri Linkov
  2005-03-18 20:21 ` Drew Adams
@ 2005-03-18 21:53 ` Stefan Monnier
  2005-03-19 12:29   ` Juri Linkov
  2005-03-20  0:22 ` Richard Stallman
  2 siblings, 1 reply; 15+ messages in thread
From: Stefan Monnier @ 2005-03-18 21:53 UTC (permalink / raw)
  Cc: emacs-devel

> I-search: gnu [GNU Free Documentation License]

I'm not particularly happy about this reuse of the [...] message.
It's meant to hold an error message.

Maybe it's not too serious as such, but given that the text displayed there
is (at least in your example) nothing more than the text under point,
I don't find it to be worthwhile.

> 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.

Actually, the first implementation of isearch-search-fun-function (a good
bit before I installed it in the CVS) was triggered by a question on
gnu.emacs.help of how to do an "incremental imenu" and I implemented it with
isearch-search-fun-function where I simply mixed the "current search string"
with the imenu-generic-expression in order to constrain the search space,
pretty much in the way you suggest.

> It removes the need to write a complicated
> search function for `isearch-search-fun-function'.

It seems that what you're suggesting is basically implementable as:

   (setq isearch-search-fun-function
         `(lambda (string &optional bound noerror)
           (if (funcall isearch-success-function)
               (,(isearch-search-fun) string bound noerror))))
         
so I'm not sure what you mean by "complicated".


        Stefan

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: Type Ahead Find
  2005-03-18 21:53 ` Stefan Monnier
@ 2005-03-19 12:29   ` Juri Linkov
  2005-03-19 21:19     ` Miles Bader
  2005-03-20 20:22     ` Juri Linkov
  0 siblings, 2 replies; 15+ messages in thread
From: Juri Linkov @ 2005-03-19 12:29 UTC (permalink / raw)
  Cc: emacs-devel

Stefan Monnier <monnier@iro.umontreal.ca> writes:
>>
>> I-search: gnu [GNU Free Documentation License]
>
> I'm not particularly happy about this reuse of the [...] message.
> It's meant to hold an error message.

Reusing an error message variable is not a clean solution, indeed.
Perhaps, it's better to add a new similar variable with the purpose
of displaying an additional data during isearch.

> Maybe it's not too serious as such, but given that the text displayed
> there is (at least in your example) nothing more than the text
> under point, I don't find it to be worthwhile.

There is the text under point only in my first example.  It would be
very useful to display hidden text like when Info-hide-note-references
hides the reference node names, so for example, when isearch reaches
the reference `*Note Local Variables in Files: (emacs)File variables',
it would display the hidden node name in square brackets:

I-search: local variables [(emacs)File variables]

It is also useful to display a data associated with the text
under point (from text properties, or other associated sources).
So in w3m buffers (where only a link text is displayed) it would
display an URL (not present in the buffer) in square brackets.
For example, for a link <a href="http://www.gnu.org/">The GNU Project</a>
when isearch finds the link text `The GNU Project', the message will be:

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

> Actually, the first implementation of isearch-search-fun-function
> (a good bit before I installed it in the CVS) was triggered by
> a question on gnu.emacs.help of how to do an "incremental imenu" and
> I implemented it with isearch-search-fun-function where I simply
> mixed the "current search string" with the imenu-generic-expression
> in order to constrain the search space, pretty much in the way
> you suggest.

IMO, it would be much simpler to implement this with
`isearch-success-function', with a small piece of code:

(set (make-local-variable 'isearch-success-function)
     ;; isearch only in function names
     (lambda ()
       (save-match-data
	 (let* ((re (cdr (assoc nil imenu-generic-expression))))
	   (and (save-excursion (beginning-of-line) (looking-at (car re)))
		(>= (point) (match-beginning (cadr re)))
		(<= (point) (match-end (cadr re))))))))

> It seems that what you're suggesting is basically implementable as:
>
>    (setq isearch-search-fun-function
>          `(lambda (string &optional bound noerror)
>            (if (funcall isearch-success-function)
>                (,(isearch-search-fun) string bound noerror))))

This won't work.  There should be a while-loop to call the
default search function in loop until the predicate function
`isearch-success-function' reports the success.  But there is
already such a loop in `isearch-search'.  It's better to reuse it.

`isearch-success-function' has another useful property: it overrides
the test with `(isearch-range-invisible)'.  This will allow searching
in invisible texts in a function defined in `isearch-success-function'.

The new `isearch-success-function' will also simplify implementing of
search in modes where both "widening" and constraining the search space
is simultaneously needed, like in Info to search text only in references
and menu items through multiple nodes.

-- 
Juri Linkov
http://www.jurta.org/emacs/

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: Type Ahead Find
  2005-03-19 12:29   ` Juri Linkov
@ 2005-03-19 21:19     ` Miles Bader
  2005-03-19 22:09       ` David Kastrup
  2005-03-20 20:14       ` Juri Linkov
  2005-03-20 20:22     ` Juri Linkov
  1 sibling, 2 replies; 15+ messages in thread
From: Miles Bader @ 2005-03-19 21:19 UTC (permalink / raw)
  Cc: Stefan Monnier, emacs-devel

On Sat, 19 Mar 2005 14:29:29 +0200, Juri Linkov <juri@jurta.org> wrote:
> There is the text under point only in my first example.  It would be
> very useful to display hidden text like when Info-hide-note-references
> hides the reference node names, so for example, when isearch reaches
> the reference `*Note Local Variables in Files: (emacs)File variables',
> it would display the hidden node name in square brackets:
> 
> I-search: local variables [(emacs)File variables]

I disagree strongly -- I've been seeing this sort of usage in the
latest info-mode isearch, and I find it very confusing to see random
information put into square-brackets after the input, because that
area is used normally for error messages or very temporary feedback on
the user's input.  [The use in info-isearch that I'm complaining about
is " [initial node]" --- which BTW is also confusingly worded, it took
me a while to realize what that was trying to say...]

Maybe there should be an area for "interesting information", but it
shouldn't be the same area used for error messages.

Ideally it'd  be some area not so noticeable, e.g., at the far-right
edge of the mini-buffer; but since that would require new redisplay
hacking, how about just something like:

   I-search (in node File Variables): local variables

That's also more similar to other "informational messages" used by
search, e.g., "overwrapped" or whatever.

[It seems a good idea for space reasons to omit the info-file name;
AFAIK, isearch won't cross info file boundaries.]

-Miles
-- 
Do not taunt Happy Fun Ball.

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: Type Ahead Find
  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:14       ` Juri Linkov
  1 sibling, 1 reply; 15+ messages in thread
From: David Kastrup @ 2005-03-19 22:09 UTC (permalink / raw)
  Cc: Juri Linkov, emacs-devel, Stefan Monnier, miles

Miles Bader <snogglethorpe@gmail.com> writes:

> Ideally it'd be some area not so noticeable, e.g., at the far-right
> edge of the mini-buffer; but since that would require new redisplay
> hacking, how about just something like:
>
>    I-search (in node File Variables): local variables
>
> That's also more similar to other "informational messages" used by
> search, e.g., "overwrapped" or whatever.

Please not.  Tags like that make the search text jump left and right
as they change, which makes it harder to keep track of it.  For a
basic error condition once per search, this is tolerable.  As a
regular part of the operation (as when going through several files),
it isn't.

-- 
David Kastrup, Kriemhildstr. 15, 44793 Bochum

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: Type Ahead Find
  2005-03-19 22:09       ` David Kastrup
@ 2005-03-19 23:33         ` Miles Bader
  2005-03-20 20:17           ` Juri Linkov
  0 siblings, 1 reply; 15+ messages in thread
From: Miles Bader @ 2005-03-19 23:33 UTC (permalink / raw)
  Cc: Juri Linkov, emacs-devel, Stefan Monnier, miles

On Sat, 19 Mar 2005 23:09:13 +0100, David Kastrup <dak@gnu.org> wrote:
> >    I-search (in node File Variables): local variables
> >
> > That's also more similar to other "informational messages" used by
> > search, e.g., "overwrapped" or whatever.
> 
> Please not.  Tags like that make the search text jump left and right
> as they change, which makes it harder to keep track of it.  For a
> basic error condition once per search, this is tolerable.  As a
> regular part of the operation (as when going through several files),
> it isn't.

Yeah; the node-name info is gratuitous anyway - - the node name is
already right there in the modeline about .5 cm above the i-search
prompt.

Something like:

   Global info I-search:  foo

[Maybe "Cross-node" would be better than "Global"?]

or whatever would be even more similar to the existing "Wrapped", get
the point across well, and address your concern about the prompt size
bouncing around excessively.

-Miles
-- 
Do not taunt Happy Fun Ball.

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: Type Ahead Find
  2005-03-18 19:45 Type Ahead Find Juri Linkov
  2005-03-18 20:21 ` Drew Adams
  2005-03-18 21:53 ` Stefan Monnier
@ 2005-03-20  0:22 ` Richard Stallman
  2005-03-20 20:19   ` Juri Linkov
  2 siblings, 1 reply; 15+ messages in thread
From: Richard Stallman @ 2005-03-20  0:22 UTC (permalink / raw)
  Cc: emacs-devel

      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.

Making such a feature useful, and not intolerable, in the context
of Emacs is not a simple matter.  I think I'd rather turn off any
feature that makes some printing characters special in isearch.

Please let's not think about this now.  If you'd like to work
on new features for after the release, how about implementing
some of the features listed in etc/TODO?

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: Type Ahead Find
  2005-03-19 21:19     ` Miles Bader
  2005-03-19 22:09       ` David Kastrup
@ 2005-03-20 20:14       ` Juri Linkov
  1 sibling, 0 replies; 15+ messages in thread
From: Juri Linkov @ 2005-03-20 20:14 UTC (permalink / raw)
  Cc: emacs-devel, monnier, miles

Miles Bader <snogglethorpe@gmail.com> writes:
>> I-search: local variables [(emacs)File variables]
>
>    I-search (in node File Variables): local variables
>
> That's also more similar to other "informational messages" used by
> search, e.g., "overwrapped" or whatever.
>
> [It seems a good idea for space reasons to omit the info-file name;
> AFAIK, isearch won't cross info file boundaries.]

Perhaps you misunderstood what was in square brackets in my example

I-search: local variables [(emacs)File variables]

`(emacs)File variables' is not the name of the current node and file.
It is the name of the reference to another info file and node which is
normally hidden by `Info-hide-note-references'.  The purpose of text
in square brackets is to show hidden reference names under the search point.

This is especially useful in browser-like buffers (e.g. w3m)
to show URLs of displayed link texts.

Some web browsers (for example, text mode browser ELinks) already has
such a feature where during typeahead search URLs are displayed
in square brackets:

Typeahead: gnu project [http://www.gnu.org/]

In Emacs this will look similarly:

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

-- 
Juri Linkov
http://www.jurta.org/emacs/

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: Type Ahead Find
  2005-03-19 23:33         ` Miles Bader
@ 2005-03-20 20:17           ` Juri Linkov
  2005-03-20 21:46             ` David Kastrup
  0 siblings, 1 reply; 15+ messages in thread
From: Juri Linkov @ 2005-03-20 20:17 UTC (permalink / raw)
  Cc: emacs-devel, monnier, miles

Miles Bader <snogglethorpe@gmail.com> writes:
> Something like:
>
>    Global info I-search:  foo
>
> [Maybe "Cross-node" would be better than "Global"?]
>
> or whatever would be even more similar to the existing "Wrapped", get
> the point across well, and address your concern about the prompt size
> bouncing around excessively.

I don't like "[initial node]" too.  Your idea of using a prefix
looks better.  We could have the following prefixes:

1. In the initial node:

Info I-search: foo

2. Before leaving the initial node:

Failing Info I-search: foo

3. After leaving the initial node:

Cross-node Info I-search: foo

4. When failing for the rest of the manual:

Failing Cross-node Info I-search: foo

5. After wrapping to the top node:

Wrapped Cross-node Info I-search: foo

6. Failing wrapped search:

Failing wrapped Cross-node Info I-search: foo

The prefix "Info " indicates that a special Info search is active
that will wrap to the next node instead of the top of the current node.

This can be implemented by adding a new variable `isearch-type'
holding a search type string and set in the `isearch-search-fun-function'
or the proposed `isearch-success-function'.  With both these
functions defined (e.g. to search menu items, references and links
through multiple nodes in Info) the search message will look like this:

Cross-node Links Info regexp I-search: foo

In the function `isearch-message-prefix' the most suitable place for
this variable seems to be after the error prefixes ("failing", "wrapped")
and before generic search type prefixes "regexp", "word", "backward"
(shown by the arrow below):

    (if isearch-success "" "failing ")
    (if isearch-adjusted "pending " "")
    (if (and isearch-wrapped ...) "over")
    (if isearch-wrapped "wrapped ")
->  (or isearch-type "")
    (if isearch-word "word " "")
    (if isearch-regexp "regexp " "")
    (if nonincremental "search" "I-search")
    (if isearch-forward "" " backward")
    (if current-input-method (concat " [" current-input-method-title "]: ")
    ": ")

-- 
Juri Linkov
http://www.jurta.org/emacs/

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: Type Ahead Find
  2005-03-20  0:22 ` Richard Stallman
@ 2005-03-20 20:19   ` Juri Linkov
  0 siblings, 0 replies; 15+ messages in thread
From: Juri Linkov @ 2005-03-20 20:19 UTC (permalink / raw)
  Cc: emacs-devel

Richard Stallman <rms@gnu.org> writes:
>       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.
>
> Making such a feature useful, and not intolerable, in the context
> of Emacs is not a simple matter.  I think I'd rather turn off any
> feature that makes some printing characters special in isearch.

The change I proposed has nothing to do with making some characters
special in isearch.

> Please let's not think about this now.  If you'd like to work
> on new features for after the release, how about implementing
> some of the features listed in etc/TODO?

This is not a new feature.  This is the change very closely related
to other recent fixes in isearch.el.  I want to finish all fixes
related to isearch.el before the next release.

Essentially, my proposed change is to make configurable the
currently hard-coded constraint imposed by `isearch-range-invisible'
in `isearch-search'.  The new variable `isearch-success-function'
will allow to override it with a user-defined function.

Also in the course of preparing this change I noticed some problems
in isearch.el related to searching of invisible text:

The lazy highlighting feature creates overlays even for matches inside
invisible texts.  A solution is to create a loop similar to the while-loop
in `isearch-search', but instead of `isearch-range-invisible' (which also
opens invisible overlays) to use the following condition in
`isearch-lazy-highlight-search':

    (text-property-any (match-beginning 0) (match-end 0)
                       'invisible nil)

This condition seems to be more correct even if it lazy-highlights
partly hidden matches.  An alternative condition

    (not (text-property-not-all (match-beginning 0) (match-end 0)
                                'invisible nil))

that lazy-highlights a match only if it is fully visible, doesn't
follow the logic of `isearch-range-invisible' used in `isearch-search'
which matches partly invisible text.

The current version of a patch is below:

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	20 Mar 2005 20:03:07 -0000
@@ -165,6 +165,11 @@
   "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.
+The function has two arguments: the positions of start and end of text
+matched by search.")
+
 ;; Search ring.
 
 (defvar search-ring nil
@@ -2039,7 +2046,8 @@
       (setq isearch-case-fold-search
 	    (isearch-no-upper-case-p isearch-string isearch-regexp)))
   (condition-case lossage
-      (let ((inhibit-point-motion-hooks search-invisible)
+      (let ((inhibit-point-motion-hooks
+	     (and (not isearch-success-function) search-invisible))
 	    (inhibit-quit nil)
 	    (case-fold-search isearch-case-fold-search)
 	    (search-spaces-regexp search-whitespace-regexp)
@@ -2052,12 +2060,15 @@
 		 isearch-string nil t))
 	  ;; Clear RETRY unless we matched some invisible text
 	  ;; and we aren't supposed to do that.
-	  (if (or (eq search-invisible t)
-		  (not isearch-success)
+	  (if (or (not isearch-success)
 		  (bobp) (eobp)
 		  (= (match-beginning 0) (match-end 0))
+		  (if isearch-success-function
+		      (funcall isearch-success-function
+			       (match-beginning 0) (match-end 0))
+		    (or (eq search-invisible t)
 		  (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 +2381,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 +2395,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,9 +2404,9 @@
 	(isearch-regexp isearch-lazy-highlight-regexp)
 	(search-spaces-regexp search-whitespace-regexp))
     (condition-case nil
-	(funcall (isearch-search-fun)
-		 isearch-lazy-highlight-last-string
-		 (if isearch-forward
+	(let ((retry t)
+	      (success nil)
+	      (bound (if isearch-forward
 		     (min (or isearch-lazy-highlight-end-limit (point-max))
 			  (if isearch-lazy-highlight-wrapped
 			      isearch-lazy-highlight-start
@@ -2403,8 +2414,22 @@
 		   (max (or isearch-lazy-highlight-start-limit (point-min))
 			(if isearch-lazy-highlight-wrapped
 			    isearch-lazy-highlight-end
-			  (window-start))))
-		 t)
+			      (window-start))))))
+	  (while retry
+	    (setq success
+		  (funcall (isearch-search-fun)
+			   isearch-lazy-highlight-last-string
+			   bound t))
+	    (if (or (not success)
+		    (eq (point) bound)
+		    (if isearch-success-function
+			(funcall isearch-success-function
+				 (match-beginning 0) (match-end 0))
+		      (text-property-any
+		       (match-beginning 0) (match-end 0)
+		       'invisible nil)))
+		(setq retry nil)))
+	  success)
       (error nil))))
 
 (defun isearch-lazy-highlight-update ()

-- 
Juri Linkov
http://www.jurta.org/emacs/

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: Type Ahead Find
  2005-03-19 12:29   ` Juri Linkov
  2005-03-19 21:19     ` Miles Bader
@ 2005-03-20 20:22     ` Juri Linkov
  1 sibling, 0 replies; 15+ messages in thread
From: Juri Linkov @ 2005-03-20 20:22 UTC (permalink / raw)
  Cc: emacs-devel

Juri Linkov <juri@jurta.org> writes:
> (set (make-local-variable 'isearch-success-function)
>      ;; isearch only in function names
>      (lambda ()
>        (save-match-data
> 	 (let* ((re (cdr (assoc nil imenu-generic-expression))))
> 	   (and (save-excursion (beginning-of-line) (looking-at (car re)))
> 		(>= (point) (match-beginning (cadr re)))
> 		(<= (point) (match-end (cadr re))))))))

I noticed that `(point)' is not a reliable indicator to find
a matching point.  It seems better to give two arguments
(match-beginning 0) and (match-end 0) to `isearch-success-function'.
So a correct example would be:

(set (make-local-variable 'isearch-success-function)
     ;; isearch only in function names
     (lambda (mb me)
       (save-match-data
	 (let ((re (cdr (assoc nil imenu-generic-expression))))
	   (and (save-excursion (beginning-of-line) (looking-at (car re)))
		(>= mb (match-beginning (cadr re)))
		(<= me (match-end (cadr re))))))))

-- 
Juri Linkov
http://www.jurta.org/emacs/

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: Type Ahead Find
  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
  0 siblings, 2 replies; 15+ messages in thread
From: David Kastrup @ 2005-03-20 21:46 UTC (permalink / raw)
  Cc: snogglethorpe, emacs-devel, monnier, miles

Juri Linkov <juri@jurta.org> writes:

> Miles Bader <snogglethorpe@gmail.com> writes:
>> Something like:
>>
>>    Global info I-search:  foo
>>
>> [Maybe "Cross-node" would be better than "Global"?]
>>
>> or whatever would be even more similar to the existing "Wrapped", get
>> the point across well, and address your concern about the prompt size
>> bouncing around excessively.
>
> I don't like "[initial node]" too.  Your idea of using a prefix
> looks better.  We could have the following prefixes:

Again: I don't like the left-right jump of the minibuffer caused by
that.  If there really is a need for that kind of information, can't
we put this in the mode-line lighter of Isearch mode?

Like Isearch/Wrapped, Isearch/X-Node...

Then the information is available in case of need, but does not take
up room and concentration in the minibuffer.

-- 
David Kastrup, Kriemhildstr. 15, 44793 Bochum

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: Type Ahead Find
  2005-03-20 21:46             ` David Kastrup
@ 2005-03-20 22:04               ` Miles Bader
  2005-03-21 19:28               ` Juri Linkov
  1 sibling, 0 replies; 15+ messages in thread
From: Miles Bader @ 2005-03-20 22:04 UTC (permalink / raw)
  Cc: Juri Linkov, emacs-devel, monnier, miles

On Sun, 20 Mar 2005 22:46:42 +0100, David Kastrup <dak@gnu.org> wrote:
> > Your idea of using a prefix
> > looks better.  We could have the following prefixes:
> 
> Again: I don't like the left-right jump of the minibuffer caused by
> that.  If there really is a need for that kind of information, can't
> we put this in the mode-line lighter of Isearch mode?
> 
> Like Isearch/Wrapped, Isearch/X-Node...

It's a trade-off:  having it in the I-search prompt make sure that the
user sees it; having in the mode-line is much less sure.

I think that `incidental information' (like a node name etc) is not
important enough to put in the I-search prompt, and that your concern
about the jumping around is valid there.

However I think that these various states of "wrapping" &c are _very_
important to communicate -- it can be extremely confusing for a user
if I-search is finding stuff and he doesn't realize that it's in the
other direction than he originally searched, or in another info node. 
[I say this from personal experience :-]

So while your concern is valid, I think these state-indicators should
definitely be included in the prompt -- they're far too critical to
leave out.

-Miles
-- 
Do not taunt Happy Fun Ball.

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: Type Ahead Find
  2005-03-20 21:46             ` David Kastrup
  2005-03-20 22:04               ` Miles Bader
@ 2005-03-21 19:28               ` Juri Linkov
  1 sibling, 0 replies; 15+ messages in thread
From: Juri Linkov @ 2005-03-21 19:28 UTC (permalink / raw)
  Cc: snogglethorpe, emacs-devel, monnier, miles

David Kastrup <dak@gnu.org> writes:
> Again: I don't like the left-right jump of the minibuffer caused by
> that.  If there really is a need for that kind of information, can't
> we put this in the mode-line lighter of Isearch mode?
>
> Like Isearch/Wrapped, Isearch/X-Node...
>
> Then the information is available in case of need, but does not take
> up room and concentration in the minibuffer.

As I see in isearch.el there is the following line in `isearch-mode'
function with the comment indicating that someone already considered
this idea:

  (setq	isearch-mode " Isearch")  ;; forward? regexp?

This suggests to put the search type in the mode-line.  But I think
its biggest drawback is that the search state might be not visible
in the mode-line when the mode-line is too wide.  For example,
in the current buffer when I activate the search I see the text
"Isearch" truncated in the mode-line:

-=:**  *wide reply to David Kastrup*   All (32,42)    (Message MML Abbrev Fill Isea

Any additional information in the mode-line will not be visible at all.

So the only place for this information is the minibuffer.
Instead of putting it in the message prefix we could put
it in the suffix in square brackets:

I-search: foo [Failing]
I-search: foo [Wrapped]
I-search: foo [Failing wrapped]

But this doesn't look good either when after wrapping the suffix [Wrapped]
remains for the wrapped search.

-- 
Juri Linkov
http://www.jurta.org/emacs/

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2005-03-21 19:28 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2005-03-18 19:45 Type Ahead Find Juri Linkov
2005-03-18 20:21 ` 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

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).