Subject: bug#11381: 23.3; isearch-search-and-update issue?

From: Stefan Monnier <[email-masked]>
Date: Mon, 28 May 2012 00:48:19 -0400

>>>>> "Juri" == Juri Linkov <[email-masked]> writes:

>>>> @@ -1425,7 +1445,11 @@ (defun word-search-backward (string &opt
>>>> of words in STRING to a regexp used to search words without regard
>>>> to punctuation."
>>>> (interactive "sWord search backward: ")
>>>> -  (re-search-backward (word-search-regexp string nil) bound noerror count))
>>>> +  (re-search-backward
>>>> +   (if (functionp isearch-word)
>>>> +       (funcall isearch-word string nil)
>>>> +     (word-search-regexp string nil))
>>>> +   bound noerror count))
>>> This doesn't sound right.
>> 
>> I guess I was a bit terse here: what I meant is that changing the
>> behavior depending on isearch-* variables is OK for a function named
>> isearch-foo but not word-search-*ward.
> Agreed.  This patch adds 4 new functions `isearch-word-search-*'.

Do we really need those 4?  I think we can just get away with
symbol-search-regexp (whose name also needs to start with "isearch-").

> Also it splits the standard default part of `isearch-search-fun'

You could actually set isearch-search-fun-function's default to
isearch-search-fun-default so we can just unconditionally call
isearch-search-fun-function's.

> into a separate function `isearch-search-fun-default' that can be
> used to obtain the default search function in any special search
> function that overrides `isearch-search-fun' like is is demonstrated
> in the second patch for `minibuffer-history-isearch-search' below.
> Additionally it enables the word search in the minibuffer with no effort
> (the key clash with `M-s w' in the minibuffer is another issue).
> I'll also go through other search functions and enable word/symbol search
> in them as well.

> === modified file 'lisp/isearch.el'
> --- lisp/isearch.el	2012-05-17 00:03:49 +0000
> +++ lisp/isearch.el	2012-05-27 09:43:07 +0000
> @@ -1468,6 +1500,62 @@ (defun word-search-forward-lax (string &
>    (interactive "sWord search: ")
>    (re-search-forward (word-search-regexp string t) bound noerror count))
 
> +;; General word-like regexp-based search.
> +
> +(defun isearch-word-search-backward (string &optional bound noerror count)
> +  "Search backward from point for STRING, converted to regexp.
> +Like `word-search-backward', but uses a function from the variable
> +`isearch-word' to convert STRING to the regexp."
> +  (re-search-backward
> +   (if (functionp isearch-word)
> +       (funcall isearch-word string nil)
> +     (word-search-regexp string nil))
> +   bound noerror count))
> +
> +(defun isearch-word-search-forward (string &optional bound noerror count)
> +  "Search forward from point for STRING, converted to regexp.
> +Like `word-search-forward', but uses a function from the variable
> +`isearch-word' to convert STRING to the regexp."
> +  (re-search-forward
> +   (if (functionp isearch-word)
> +       (funcall isearch-word string nil)
> +     (word-search-regexp string nil))
> +   bound noerror count))
> +
> +(defun isearch-word-search-backward-lax (string &optional bound noerror count)
> +  "Search backward from point for STRING, converted to regexp.
> +Like `word-search-backward-lax', but uses a function from the variable
> +`isearch-word' to convert STRING to the regexp."
> +  (re-search-backward
> +   (if (functionp isearch-word)
> +       (funcall isearch-word string t)
> +     (word-search-regexp string t))
> +   bound noerror count))
> +
> +(defun isearch-word-search-forward-lax (string &optional bound noerror count)
> +  "Search forward from point for STRING, converted to regexp.
> +Like `word-search-forward-lax', but uses a function from the variable
> +`isearch-word' to convert STRING to the regexp."
> +  (re-search-forward
> +   (if (functionp isearch-word)
> +       (funcall isearch-word string t)
> +     (word-search-regexp string t))
> +   bound noerror count))
> +
> +;; Symbol search
> +
> +(defun symbol-search-regexp (string &optional lax)
> +  "Return a regexp which matches STRING as a symbol.
> +Creates a regexp where STRING is surrounded by symbol delimiters \\_< and \\_>.
> +If LAX is non-nil, the end of the string need not match a symbol
> +boundary unless it ends in whitespace."
> +  (concat
> +   "\\_<"
> +   (regexp-quote string)
> +   (if (or (not lax) (string-match-p "\\W$" string)) "\\_>")))
> +
> +(put 'symbol-search-regexp 'isearch-message-prefix "symbol ")
> +
>  
>  (defun isearch-query-replace (&optional delimited regexp-flag)
>    "Start `query-replace' with string to replace from last search string.
> @@ -2370,20 +2473,23 @@ (defun isearch-search-fun ()
>  Can be changed via `isearch-search-fun-function' for special needs."
>    (if isearch-search-fun-function
>        (funcall isearch-search-fun-function)
> -    (cond
> -     (isearch-word
> -      ;; Use lax versions to not fail at the end of the word while
> -      ;; the user adds and removes characters in the search string
> -      ;; (or when using nonincremental word isearch)
> -      (if (or isearch-nonincremental
> -	      (eq (length isearch-string)
> -		  (length (isearch-string-state (car isearch-cmds)))))
> -	  (if isearch-forward 'word-search-forward 'word-search-backward)
> -	(if isearch-forward 'word-search-forward-lax 'word-search-backward-lax)))
> -     (isearch-regexp
> -      (if isearch-forward 're-search-forward 're-search-backward))
> -     (t
> -      (if isearch-forward 'search-forward 'search-backward)))))
> +    (isearch-search-fun-default)))
> +
> +(defun isearch-search-fun-default ()
> +  (cond
> +   (isearch-word
> +    ;; Use lax versions to not fail at the end of the word while
> +    ;; the user adds and removes characters in the search string
> +    ;; (or when using nonincremental word isearch)
> +    (if (or isearch-nonincremental
> +	    (eq (length isearch-string)
> +		(length (isearch-string-state (car isearch-cmds)))))

> +	(if isearch-forward 'isearch-word-search-forward 'isearch-word-search-backward)

If we inline your defs, this turns into:

        (if isearch-forward
            (lambda (string &optional bound noerror count)
              (re-search-forward
               (if (functionp isearch-word)
                   (funcall isearch-word string nil)
                 (word-search-regexp string nil))
               bound noerror count))
          (lambda (string &optional bound noerror count)
            (re-search-backward
             (if (functionp isearch-word)
                 (funcall isearch-word string nil)
               (word-search-regexp string nil))
             bound noerror count)))

which can be simplified to

        (lambda (string &optional bound noerror count)
          (if isearch-forward
              (re-search-forward
               (if (functionp isearch-word)
                   (funcall isearch-word string nil)
                 (word-search-regexp string nil))
               bound noerror count))
            (re-search-backward
             (if (functionp isearch-word)
                 (funcall isearch-word string nil)
               (word-search-regexp string nil))
             bound noerror count)))

and then

        (lambda (string &optional bound noerror count)
          (funcall
           (if isearch-forward #'re-search-forward #'re-search-backward)
           (if (functionp isearch-word)
               (funcall isearch-word string nil)
             (word-search-regexp string nil))
           bound noerror count))

-- Stefan