unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* query-replace-interactive not documented
@ 2004-05-28 16:16 Werner LEMBERG
  2004-05-29 17:02 ` Richard Stallman
  0 siblings, 1 reply; 101+ messages in thread
From: Werner LEMBERG @ 2004-05-28 16:16 UTC (permalink / raw)



The variable `query-replace-interactive' isn't documented in
emacs.info or elisp.info.


    Werner

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

* Re: query-replace-interactive not documented
  2004-05-28 16:16 query-replace-interactive not documented Werner LEMBERG
@ 2004-05-29 17:02 ` Richard Stallman
  2004-05-29 17:37   ` Luc Teirlinck
  0 siblings, 1 reply; 101+ messages in thread
From: Richard Stallman @ 2004-05-29 17:02 UTC (permalink / raw)
  Cc: emacs-devel

    The variable `query-replace-interactive' isn't documented in
    emacs.info or elisp.info.

If we document this option, the logical place for it would be the
Emacs manual.  But we cannot set the goal of mentioning every option
in the manual.  It would make the manual too big to print.
I am not sure this option is worth adding.

One of the benefits of Custom is that it will help users find
options without having to put them in the manual.

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

* Re: query-replace-interactive not documented
  2004-05-29 17:02 ` Richard Stallman
@ 2004-05-29 17:37   ` Luc Teirlinck
  2004-05-29 20:33     ` Juri Linkov
  2004-05-30 19:41     ` Richard Stallman
  0 siblings, 2 replies; 101+ messages in thread
From: Luc Teirlinck @ 2004-05-29 17:37 UTC (permalink / raw)
  Cc: wl, emacs-devel

Richard Stallman wrote:

       The variable `query-replace-interactive' isn't documented in
       emacs.info or elisp.info.

   If we document this option, the logical place for it would be the
   Emacs manual.  But we cannot set the goal of mentioning every option
   in the manual.  It would make the manual too big to print.
   I am not sure this option is worth adding.

   One of the benefits of Custom is that it will help users find
   options without having to put them in the manual.

`query-replace-interactive' is not a user option.  It is defined using
defvar in replace.el.  Its docstring does not start with a `*' either.
Of course, we can not document every single defvar either.

Should it be a defcustom?  Is it something one would want to set
permanently to t?  (I would not want to, but might other people want
to?)

Sincerely,

Luc.

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

* Re: query-replace-interactive not documented
  2004-05-29 17:37   ` Luc Teirlinck
@ 2004-05-29 20:33     ` Juri Linkov
  2004-06-11  8:19       ` Juri Linkov
  2004-05-30 19:41     ` Richard Stallman
  1 sibling, 1 reply; 101+ messages in thread
From: Juri Linkov @ 2004-05-29 20:33 UTC (permalink / raw)
  Cc: wl, rms, emacs-devel

Luc Teirlinck <teirllm@dms.auburn.edu> writes:
> `query-replace-interactive' is not a user option.  It is defined using
> defvar in replace.el.  Its docstring does not start with a `*' either.
> Of course, we can not document every single defvar either.
>
> Should it be a defcustom?  Is it something one would want to set
> permanently to t?  (I would not want to, but might other people want
> to?)

I remember there was a discussion about changing user options defined
by defvar into defcustom.  At least, `query-replace-interactive' looks
like a typical user option.

However, I think it should not be added to the Emacs manual
because there are many other similar undocumented options which
don't fit into the manual.

What should be documented in the Emacs manual is a very useful command
`query-replace-regexp-eval'.  It even deserves its own keybinding.
But if there are no spare keybindings for it, then perhaps it could be
invoked by a prefix arg of `query-replace-regexp' like e.g.  C-u C-M-% ?

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

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

* Re: query-replace-interactive not documented
  2004-05-29 17:37   ` Luc Teirlinck
  2004-05-29 20:33     ` Juri Linkov
@ 2004-05-30 19:41     ` Richard Stallman
  2004-05-30 22:00       ` Luc Teirlinck
  2004-06-08  6:55       ` Juri Linkov
  1 sibling, 2 replies; 101+ messages in thread
From: Richard Stallman @ 2004-05-30 19:41 UTC (permalink / raw)
  Cc: wl, emacs-devel

    `query-replace-interactive' is not a user option.  It is defined using
    defvar in replace.el.  Its docstring does not start with a `*' either.
    Of course, we can not document every single defvar either.

    Should it be a defcustom?

Yes.

      Is it something one would want to set
    permanently to t?

Some people might.

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

* Re: query-replace-interactive not documented
  2004-05-30 19:41     ` Richard Stallman
@ 2004-05-30 22:00       ` Luc Teirlinck
  2004-06-08  6:55       ` Juri Linkov
  1 sibling, 0 replies; 101+ messages in thread
From: Luc Teirlinck @ 2004-05-30 22:00 UTC (permalink / raw)
  Cc: wl, emacs-devel

Richard Stallman wrote:

       `query-replace-interactive' is not a user option.  It is defined using
       defvar in replace.el.  Its docstring does not start with a `*' either.
       Of course, we can not document every single defvar either.

       Should it be a defcustom?

   Yes.

I converted it into a defcustom.  What is actually the policy
concerning :version keywords in converted old defvars?  Strictly
speaking, for people using only Custom to customize variables this is
a _new_ customizable option, and thus should get a `:version "21.4"'
(or whatever we are going to call the next release, I do not know
whether that has actually already been decided.)  However, this seemed
silly for a ten year old variable, so I did _not_ put in a :version
keyword.

Sincerely,

Luc.

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

* Re: query-replace-interactive not documented
  2004-05-30 19:41     ` Richard Stallman
  2004-05-30 22:00       ` Luc Teirlinck
@ 2004-06-08  6:55       ` Juri Linkov
  2004-06-11  8:22         ` Juri Linkov
  1 sibling, 1 reply; 101+ messages in thread
From: Juri Linkov @ 2004-06-08  6:55 UTC (permalink / raw)
  Cc: wl, teirllm, emacs-devel

Richard Stallman <rms@gnu.org> writes:
>     `query-replace-interactive' is not a user option.  It is defined using
>     defvar in replace.el.  Its docstring does not start with a `*' either.
>     Of course, we can not document every single defvar either.
>
>       Is it something one would want to set permanently to t?
>
> Some people might.

I doubt that people may want to set it permanently to t.
And toggling this variable on/off is very inconvenient.

However, this variable might be useful in the following situation:
it can be set temporarily to t by typing M-% in isearch mode, which
can exit isearch mode and start query-replace with isearch string.
It's natural to assume that if the user types M-% or C-M-% in isearch
mode he wants to use the current search string as FROM-STRING for
query-replace and query-replace-regexp.

I also added a new value `initial' to `query-replace-interactive' to
insert the last search string into FROM-STRING prompt as an initial
value to allow the user to modify it before performing replacements.

Index: lisp/isearch.el
===================================================================
RCS file: /cvsroot/emacs/emacs/lisp/isearch.el,v
retrieving revision 1.228
diff -u -w -b -r1.228 isearch.el
--- lisp/isearch.el	6 Jun 2004 13:57:39 -0000	1.228
+++ lisp/isearch.el	8 Jun 2004 03:18:36 -0000
@@ -336,6 +338,9 @@
     (define-key map "\M-r" 'isearch-toggle-regexp)
     (define-key map "\M-e" 'isearch-edit-string)
 
+    (define-key map    [?\M-%] 'isearch-query-replace)
+    (define-key map [?\C-\M-%] 'isearch-query-replace-regexp)
+
     map)
   "Keymap for `isearch-mode'.")
 
@@ -1047,6 +1054,23 @@
   (sit-for 1)
   (isearch-update))
 
+(defun isearch-query-replace ()
+  "Start query-replace with string to replace from last search string."
+  (interactive)
+  (let ((query-replace-interactive 'initial))
+    (isearch-exit)
+    (if isearch-forward (goto-char isearch-other-end))
+    (call-interactively 'query-replace)))
+
+(defun isearch-query-replace-regexp ()
+  "Start query-replace-regexp with string to replace from last search string."
+  (interactive)
+  (let ((query-replace-interactive 'initial))
+    (isearch-exit)
+    (if isearch-forward (goto-char isearch-other-end))
+    (call-interactively 'query-replace-regexp)))
+
 (defun isearch-delete-char ()
   "Discard last input item and move point back.
 If no previous match was done, just beep."

Index: lisp/replace.el
===================================================================
RCS file: /cvsroot/emacs/emacs/lisp/replace.el,v
retrieving revision 1.171
diff -u -r1.171 replace.el
--- lisp/replace.el	30 May 2004 21:50:35 -0000	1.171
+++ lisp/replace.el	8 Jun 2004 02:58:37 -0000
@@ -38,8 +38,12 @@
 
 (defcustom query-replace-interactive nil
   "Non-nil means `query-replace' uses the last search string.
-That becomes the \"string to replace\"."
-  :type 'boolean
+That becomes the \"string to replace\".
+If value is `initial', the last search string is inserted into
+the minibuffer as an initial value for \"string to replace\"."
+  :type '(choice (const :tag "Off" nil)
+                 (const :tag "Initial content" initial)
+                 (other :tag "Default value" t))
   :group 'matching)
 
 (defcustom query-replace-from-history-variable 'query-replace-history
@@ -70,16 +74,20 @@
   (unless noerror
     (barf-if-buffer-read-only))
   (let (from to)
-    (if query-replace-interactive
+    (if (and query-replace-interactive
+             (not (eq query-replace-interactive 'initial)))
 	(setq from (car (if regexp-flag regexp-search-ring search-ring)))
       ;; The save-excursion here is in case the user marks and copies
       ;; a region in order to specify the minibuffer input.
       ;; That should not clobber the region for the query-replace itself.
       (save-excursion
-	(setq from (read-from-minibuffer (format "%s: " string)
-					 nil nil nil
-					 query-replace-from-history-variable
-					 nil t)))
+	(setq from (read-from-minibuffer
+                    (format "%s: " string)
+                    (if (eq query-replace-interactive 'initial)
+                        (car (if regexp-flag regexp-search-ring search-ring)))
+                    nil nil
+                    query-replace-from-history-variable
+                    nil t)))
       ;; Warn if user types \n or \t, but don't reject the input.
       (if (string-match "\\\\[nt]" from)
 	  (let ((match (match-string 0 from)))

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

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

* Re: query-replace-interactive not documented
  2004-05-29 20:33     ` Juri Linkov
@ 2004-06-11  8:19       ` Juri Linkov
  2004-06-11  8:39         ` Kim F. Storm
                           ` (2 more replies)
  0 siblings, 3 replies; 101+ messages in thread
From: Juri Linkov @ 2004-06-11  8:19 UTC (permalink / raw)
  Cc: rms, emacs-devel

Juri Linkov <juri@jurta.org> writes:
> What should be documented in the Emacs manual is a very useful command
> `query-replace-regexp-eval'.  It even deserves its own keybinding.
> But if there are no spare keybindings for it, then perhaps it could be
> invoked by a prefix arg of `query-replace-regexp' like e.g. C-u C-M-% ?

I don't want to abandon the attempt to make this useful command more
accessible.

How about typing a special key (say, `M-e', where "e" stands for
"eval" or "expression") in the second prompt for a replacement string
to switch it to expression reading mode, and after typing RET
to call `query-replace-regexp-eval' instead of `query-replace-regexp'.
Actually, this means typing:

C-M-% from-string RET M-e to-expr RET

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

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

* Re: query-replace-interactive not documented
  2004-06-08  6:55       ` Juri Linkov
@ 2004-06-11  8:22         ` Juri Linkov
  2004-06-12  1:50           ` Richard Stallman
  0 siblings, 1 reply; 101+ messages in thread
From: Juri Linkov @ 2004-06-11  8:22 UTC (permalink / raw)
  Cc: teirllm, emacs-devel

Juri Linkov <juri@jurta.org> writes:
> However, this variable might be useful in the following situation:
> it can be set temporarily to t by typing M-% in isearch mode, which
> can exit isearch mode and start query-replace with isearch string.
> It's natural to assume that if the user types M-% or C-M-% in isearch
> mode he wants to use the current search string as FROM-STRING for
> query-replace and query-replace-regexp.

I noticed that the commentary section of isearch.el has the following
TODO item:

;; - Think about incorporating query-replace.

Does anyone know what it was intended to do?  Won't my proposal conflict
with someone's plans by stealing isearch keybindings M-% and C-M-%?

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

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

* Re: query-replace-interactive not documented
  2004-06-11  8:19       ` Juri Linkov
@ 2004-06-11  8:39         ` Kim F. Storm
  2004-06-11  9:00         ` David Kastrup
  2004-06-12  1:50         ` Richard Stallman
  2 siblings, 0 replies; 101+ messages in thread
From: Kim F. Storm @ 2004-06-11  8:39 UTC (permalink / raw)
  Cc: Luc Teirlinck, rms, emacs-devel

Juri Linkov <juri@jurta.org> writes:

> Juri Linkov <juri@jurta.org> writes:
> > What should be documented in the Emacs manual is a very useful command
> > `query-replace-regexp-eval'.  It even deserves its own keybinding.
> > But if there are no spare keybindings for it, then perhaps it could be
> > invoked by a prefix arg of `query-replace-regexp' like e.g. C-u C-M-% ?
> 
> I don't want to abandon the attempt to make this useful command more
> accessible.
> 
What about

C-x C-M-%


-- 
Kim F. Storm <storm@cua.dk> http://www.cua.dk

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

* Re: query-replace-interactive not documented
  2004-06-11  8:19       ` Juri Linkov
  2004-06-11  8:39         ` Kim F. Storm
@ 2004-06-11  9:00         ` David Kastrup
  2004-06-12  8:21           ` Juri Linkov
  2004-06-12  1:50         ` Richard Stallman
  2 siblings, 1 reply; 101+ messages in thread
From: David Kastrup @ 2004-06-11  9:00 UTC (permalink / raw)
  Cc: Luc Teirlinck, rms, emacs-devel

Juri Linkov <juri@jurta.org> writes:

> Juri Linkov <juri@jurta.org> writes:
> > What should be documented in the Emacs manual is a very useful
> > command `query-replace-regexp-eval'.  It even deserves its own
> > keybinding.  But if there are no spare keybindings for it, then
> > perhaps it could be invoked by a prefix arg of
> > `query-replace-regexp' like e.g. C-u C-M-% ?
> 
> I don't want to abandon the attempt to make this useful command more
> accessible.
> 
> How about typing a special key (say, `M-e', where "e" stands for
> "eval" or "expression") in the second prompt for a replacement string
> to switch it to expression reading mode, and after typing RET
> to call `query-replace-regexp-eval' instead of `query-replace-regexp'.
> Actually, this means typing:
> 
> C-M-% from-string RET M-e to-expr RET

This has the advantage that if one starts out with a replacement, and
then figures that the replacement string needs to be as complicated
as to have to be specified in Lisp, one does not need to abandon the
already started replacement.

Actually, I find myself doing this sort of starting over from M-% not
too rarely.  So perhaps we should apply this
switch-type-of-replacement keybinding idea also to query-replace.

-- 
David Kastrup, Kriemhildstr. 15, 44793 Bochum

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

* Re: query-replace-interactive not documented
  2004-06-11  8:19       ` Juri Linkov
  2004-06-11  8:39         ` Kim F. Storm
  2004-06-11  9:00         ` David Kastrup
@ 2004-06-12  1:50         ` Richard Stallman
  2004-06-12  8:16           ` Juri Linkov
  2004-06-12  8:21           ` David Kastrup
  2 siblings, 2 replies; 101+ messages in thread
From: Richard Stallman @ 2004-06-12  1:50 UTC (permalink / raw)
  Cc: teirllm, emacs-devel

    How about typing a special key (say, `M-e', where "e" stands for
    "eval" or "expression") in the second prompt for a replacement string
    to switch it to expression reading mode, and after typing RET
    to call `query-replace-regexp-eval' instead of `query-replace-regexp'.
    Actually, this means typing:

    C-M-% from-string RET M-e to-expr RET

This is rather obsure, and ad hoc.  So it is probably harder to
remember than M-x que TAB - TAB - TAB, which works now
and can be found systematically from the command name.

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

* Re: query-replace-interactive not documented
  2004-06-11  8:22         ` Juri Linkov
@ 2004-06-12  1:50           ` Richard Stallman
  2004-06-18 20:00             ` isearch hooks (was: query-replace-interactive not documented) Juri Linkov
  0 siblings, 1 reply; 101+ messages in thread
From: Richard Stallman @ 2004-06-12  1:50 UTC (permalink / raw)
  Cc: teirllm, emacs-devel

    I noticed that the commentary section of isearch.el has the following
    TODO item:

    ;; - Think about incorporating query-replace.

    Does anyone know what it was intended to do?

I don't remember any specific plan, but I think the idea was
that at some point you'd switch from isearch to query-replacing
the current string.  In other words, what you're talking about
seems more or less the idea that was intended.

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

* Re: query-replace-interactive not documented
  2004-06-12  1:50         ` Richard Stallman
@ 2004-06-12  8:16           ` Juri Linkov
  2004-06-13  0:01             ` Richard Stallman
  2004-06-12  8:21           ` David Kastrup
  1 sibling, 1 reply; 101+ messages in thread
From: Juri Linkov @ 2004-06-12  8:16 UTC (permalink / raw)
  Cc: emacs-devel

Richard Stallman <rms@gnu.org> writes:
>     How about typing a special key (say, `M-e', where "e" stands for
>     "eval" or "expression") in the second prompt for a replacement string
>     to switch it to expression reading mode, and after typing RET
>     to call `query-replace-regexp-eval' instead of `query-replace-regexp'.
>     Actually, this means typing:
>
>     C-M-% from-string RET M-e to-expr RET
>
> This is rather obsure, and ad hoc.

This is not quite ad hoc.  Some GNU programs already provide exactly
the same feature.  Here is an excerpt from `man less':

       /pattern
              [...]

              Certain characters are special if entered at the beginning of the
              pattern; they modify the type of search rather than  become  part
              of the pattern:

              [^N ^E ^F ^K skipped...]

              ^R     Don't interpret  regular  expression  metacharacters;
                     that is, do a simple textual comparison.

> So it is probably harder to remember than M-x que TAB - TAB - TAB,
> which works now and can be found systematically from the command
> name.

What do you think about documenting `query-replace-regexp-eval'
in the Emacs manual even without a keybinding?

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

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

* Re: query-replace-interactive not documented
  2004-06-11  9:00         ` David Kastrup
@ 2004-06-12  8:21           ` Juri Linkov
  0 siblings, 0 replies; 101+ messages in thread
From: Juri Linkov @ 2004-06-12  8:21 UTC (permalink / raw)
  Cc: rms, emacs-devel

David Kastrup <dak@gnu.org> writes:
> Juri Linkov <juri@jurta.org> writes:
>> How about typing a special key (say, `M-e', where "e" stands for
>> "eval" or "expression") in the second prompt for a replacement string
>> to switch it to expression reading mode, and after typing RET
>> to call `query-replace-regexp-eval' instead of `query-replace-regexp'.
>> Actually, this means typing:
>> 
>> C-M-% from-string RET M-e to-expr RET
>
> This has the advantage that if one starts out with a replacement, and
> then figures that the replacement string needs to be as complicated
> as to have to be specified in Lisp, one does not need to abandon the
> already started replacement.
>
> Actually, I find myself doing this sort of starting over from M-% not
> too rarely.  So perhaps we should apply this
> switch-type-of-replacement keybinding idea also to query-replace.

The most natural keybinding for this would be M-r (like in isearch mode),
but unfortunately it can't be used because this key is already bound
in the minibuffer to the command that finds the previous history element.

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

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

* Re: query-replace-interactive not documented
  2004-06-12  1:50         ` Richard Stallman
  2004-06-12  8:16           ` Juri Linkov
@ 2004-06-12  8:21           ` David Kastrup
  1 sibling, 0 replies; 101+ messages in thread
From: David Kastrup @ 2004-06-12  8:21 UTC (permalink / raw)
  Cc: Juri Linkov, teirllm, emacs-devel

Richard Stallman <rms@gnu.org> writes:

>     How about typing a special key (say, `M-e', where "e" stands for
>     "eval" or "expression") in the second prompt for a replacement string
>     to switch it to expression reading mode, and after typing RET
>     to call `query-replace-regexp-eval' instead of `query-replace-regexp'.
>     Actually, this means typing:
> 
>     C-M-% from-string RET M-e to-expr RET
> 
> This is rather obsure, and ad hoc.

Well, I often have the case where I have to make this decision ad-hoc
since I just notice that I started off with the wrong kind of
replacement.

> So it is probably harder to remember than M-x que TAB - TAB - TAB,
> which works now and can be found systematically from the command
> name.

The ability to switch from one replacement to another does not
preclude that.

-- 
David Kastrup, Kriemhildstr. 15, 44793 Bochum

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

* Re: query-replace-interactive not documented
  2004-06-12  8:16           ` Juri Linkov
@ 2004-06-13  0:01             ` Richard Stallman
  2004-06-13  0:46               ` Miles Bader
                                 ` (2 more replies)
  0 siblings, 3 replies; 101+ messages in thread
From: Richard Stallman @ 2004-06-13  0:01 UTC (permalink / raw)
  Cc: emacs-devel

    What do you think about documenting `query-replace-regexp-eval'
    in the Emacs manual even without a keybinding?

The reason I did not document it before is that I'm not sure it is
really very useful.  I never use it.  How many people here actually
use it?

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

* Re: query-replace-interactive not documented
  2004-06-13  0:01             ` Richard Stallman
@ 2004-06-13  0:46               ` Miles Bader
  2004-06-13  9:03               ` David Kastrup
  2004-06-14 16:59               ` Juri Linkov
  2 siblings, 0 replies; 101+ messages in thread
From: Miles Bader @ 2004-06-13  0:46 UTC (permalink / raw)
  Cc: Juri Linkov, emacs-devel

On Sat, Jun 12, 2004 at 08:01:20PM -0400, Richard Stallman wrote:
>     What do you think about documenting `query-replace-regexp-eval'
>     in the Emacs manual even without a keybinding?
> 
> The reason I did not document it before is that I'm not sure it is
> really very useful.  I never use it.  How many people here actually
> use it?

I use it -- not everyday, but for some problems, it can be invaluable.

When I found out about this function I was elated; it replaces various
less-flexible ad-hoc elisp code I had, and for the cases where you need it,
it's actually very succinct.

E.g., when I have some C defines:

   #define X 0x001	/* bla blah */
   #define Y 0x002
   ...

and I rearrange the cases or do something that screws up the values, it's
much easier to use a region-limited `query-replace-regexp-eval' replacing
"0x[0-9a-f]*" with (format "0x%04x" (lsh 1 replace-count)) than to do it by
hand.

-Miles
-- 
I'm beginning to think that life is just one long Yoko Ono album; no rhyme
or reason, just a lot of incoherent shrieks and then it's over.  --Ian Wolff

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

* Re: query-replace-interactive not documented
  2004-06-13  0:01             ` Richard Stallman
  2004-06-13  0:46               ` Miles Bader
@ 2004-06-13  9:03               ` David Kastrup
  2004-06-14 18:50                 ` Richard Stallman
  2004-06-14 16:59               ` Juri Linkov
  2 siblings, 1 reply; 101+ messages in thread
From: David Kastrup @ 2004-06-13  9:03 UTC (permalink / raw)
  Cc: Juri Linkov, emacs-devel

Richard Stallman <rms@gnu.org> writes:

>     What do you think about documenting `query-replace-regexp-eval'
>     in the Emacs manual even without a keybinding?
> 
> The reason I did not document it before is that I'm not sure it is
> really very useful.  I never use it.  How many people here actually
> use it?

I do.  One typical qpplication is

M-x query-replace-regexp-eval RET
\\footnote{ RET
(format "\\footnote{\\label{fn:%d}" replace-count) RET

Also other stuff where you want to replace with numerical expressions.

Of course, most of these uses could be avoided if the replacement
string of the ordinary query-replace-regexp would offer, say

M-x query-replace-regexp RET
\\footnote{ RET
\\footnote{\\label{fn:\!replace-count} RET

or

\\footnote{\\label{fn:\!(format "%d" replace-count)} RET

Namely \! followed by a sexp.  This would allow the full flexibility
of query-replace-regexp-eval without needing a separate command, and
one would need to switch to Lisp only for the really needed passages
instead of the whole replacement string.

-- 
David Kastrup, Kriemhildstr. 15, 44793 Bochum

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

* Re: query-replace-interactive not documented
  2004-06-13  0:01             ` Richard Stallman
  2004-06-13  0:46               ` Miles Bader
  2004-06-13  9:03               ` David Kastrup
@ 2004-06-14 16:59               ` Juri Linkov
  2 siblings, 0 replies; 101+ messages in thread
From: Juri Linkov @ 2004-06-14 16:59 UTC (permalink / raw)
  Cc: emacs-devel

Richard Stallman <rms@gnu.org> writes:
>     What do you think about documenting `query-replace-regexp-eval'
>     in the Emacs manual even without a keybinding?
>
> The reason I did not document it before is that I'm not sure it is
> really very useful.  I never use it.  How many people here actually
> use it?

It is not a frequently used command.  But when there is a need to
replace a regexp with a variable string, it becomes a real time saver.
I have seen people unaware of this command trying to solve a problem
in a too complicated way.  This is one of the commands Emacs users
need to know about to not reinvent the wheel.

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

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

* Re: query-replace-interactive not documented
  2004-06-13  9:03               ` David Kastrup
@ 2004-06-14 18:50                 ` Richard Stallman
  2004-06-14 20:49                   ` Kim F. Storm
  0 siblings, 1 reply; 101+ messages in thread
From: Richard Stallman @ 2004-06-14 18:50 UTC (permalink / raw)
  Cc: juri, emacs-devel

    Of course, most of these uses could be avoided if the replacement
    string of the ordinary query-replace-regexp would offer, say

    M-x query-replace-regexp RET
    \\footnote{ RET
    \\footnote{\\label{fn:\!replace-count} RET

    or

    \\footnote{\\label{fn:\!(format "%d" replace-count)} RET

    Namely \! followed by a sexp.

That seems like an interesting idea.

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

* Re: query-replace-interactive not documented
  2004-06-14 18:50                 ` Richard Stallman
@ 2004-06-14 20:49                   ` Kim F. Storm
  2004-06-14 21:20                     ` David Kastrup
  0 siblings, 1 reply; 101+ messages in thread
From: Kim F. Storm @ 2004-06-14 20:49 UTC (permalink / raw)
  Cc: juri, David Kastrup, emacs-devel

Richard Stallman <rms@gnu.org> writes:

>     Of course, most of these uses could be avoided if the replacement
>     string of the ordinary query-replace-regexp would offer, say
> 
>     M-x query-replace-regexp RET
>     \\footnote{ RET
>     \\footnote{\\label{fn:\!replace-count} RET
> 
>     or
> 
>     \\footnote{\\label{fn:\!(format "%d" replace-count)} RET
> 
>     Namely \! followed by a sexp.
> 
> That seems like an interesting idea.

I would prefer a syntax which can be parsed with `read', which
includes the second example above, but not the first one.

-- 
Kim F. Storm <storm@cua.dk> http://www.cua.dk

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

* Re: query-replace-interactive not documented
  2004-06-14 20:49                   ` Kim F. Storm
@ 2004-06-14 21:20                     ` David Kastrup
  2004-06-15 14:29                       ` Juri Linkov
  0 siblings, 1 reply; 101+ messages in thread
From: David Kastrup @ 2004-06-14 21:20 UTC (permalink / raw)
  Cc: juri, rms, emacs-devel

storm@cua.dk (Kim F. Storm) writes:

> Richard Stallman <rms@gnu.org> writes:
> 
> >     Of course, most of these uses could be avoided if the replacement
> >     string of the ordinary query-replace-regexp would offer, say
> > 
> >     M-x query-replace-regexp RET
> >     \\footnote{ RET
> >     \\footnote{\\label{fn:\!replace-count} RET
> > 
> >     or
> > 
> >     \\footnote{\\label{fn:\!(format "%d" replace-count)} RET
> > 
> >     Namely \! followed by a sexp.
> > 
> > That seems like an interesting idea.
> 
> I would prefer a syntax which can be parsed with `read', which
> includes the second example above, but not the first one.

Well, this was of course just a wild proposal without any serious
thought behind the involved details.  One should probably take a look
at eshell syntax maybe for getting some suggestions for a somewhat
consistent syntax, and one would need to think about a way that makes
it possible to end the expression in question without adding
unnecessary spaces or so to the match.

And of course, this sort of stuff should not be done by replace-match
or similar functions but just by the interactive function, to avoid
opening security concerns when Emacs is used as a match-and-replace
engine (where people don't expect it to execute arbitrary code).

-- 
David Kastrup, Kriemhildstr. 15, 44793 Bochum

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

* Re: query-replace-interactive not documented
  2004-06-14 21:20                     ` David Kastrup
@ 2004-06-15 14:29                       ` Juri Linkov
  2004-06-15 15:43                         ` David Kastrup
  2004-06-15 22:25                         ` Andreas Schwab
  0 siblings, 2 replies; 101+ messages in thread
From: Juri Linkov @ 2004-06-15 14:29 UTC (permalink / raw)
  Cc: emacs-devel, rms, storm

David Kastrup <dak@gnu.org> writes:
> storm@cua.dk (Kim F. Storm) writes:
>> Richard Stallman <rms@gnu.org> writes:
>> > That seems like an interesting idea.
>> 
>> I would prefer a syntax which can be parsed with `read', which
>> includes the second example above, but not the first one.
>
> Well, this was of course just a wild proposal without any serious
> thought behind the involved details.  One should probably take a look
> at eshell syntax maybe for getting some suggestions for a somewhat
> consistent syntax, and one would need to think about a way that makes
> it possible to end the expression in question without adding
> unnecessary spaces or so to the match.

I like this idea.  To avoid problems with `read' and to end the expression
explicitly I suggest to always place the expression in parenthesis.
To use a single variable inside a replacement string, one can use
a no-op function like `+':

    \\footnote{\\label{fn:\!(+ replace-count)}

> And of course, this sort of stuff should not be done by replace-match
> or similar functions but just by the interactive function, to avoid
> opening security concerns when Emacs is used as a match-and-replace
> engine (where people don't expect it to execute arbitrary code).

Doing it only in the interactive function instead of `replace-match'
seems right.  This is needed only to save keystrokes for users.
Since `replace-match' is not a command, when the programmer writes
a loop with `re-search-forward' and `replace-match', he can construct
a replacement string explicitly with appropriate functions.

Anyway, below is a quick implementation of such a feature.  I tried it
a bit and I like it.  What I don't like yet is the choice of a special
meta symbol `\!'.  Usually this symbol is associated with the error code.
Perhaps, a better symbol would be \( itself like in:

    \\footnote{\\label{fn:\(+ replace-count)}

but this has another problem: the open parenthesis is escaped
and Emacs commands don't match it with the close parenthesis.
So the choice of a good symbol is still an open issue.

Index: replace.el
===================================================================
RCS file: /cvsroot/emacs/emacs/lisp/replace.el,v
retrieving revision 1.172
diff -c -r1.172 replace.el
*** replace.el	10 Jun 2004 04:21:14 -0000	1.172
--- replace.el	15 Jun 2004 14:56:15 -0000
***************
*** 174,180 ****
  	   (if (and transient-mark-mode mark-active)
  	       (region-end)))))
  
!   (perform-replace regexp to-string t t delimited nil nil start end))
  (define-key esc-map [?\C-%] 'query-replace-regexp)
  
  (defun query-replace-regexp-eval (regexp to-expr &optional delimited start end)
--- 183,200 ----
  	   (if (and transient-mark-mode mark-active)
  	       (region-end)))))
  
!   (if (string-match "!\(" to-string)
!       (let (res)
!         (while (string-match "!\(" to-string)
!           (setq res (cons (substring to-string 0 (1- (match-beginning 0))) res)
!                 to-string (substring to-string (1- (match-end 0))))
!           (let ((r (read-from-string to-string)))
!             (setq res (cons `(format "%s" ,(car r)) res)
!                   to-string (substring to-string (cdr r)))))
!         (perform-replace regexp `(replace-eval-replacement
!                                   concat ,@(nreverse (cons to-string res)))
!                          t 'literal delimited nil nil start end))
!     (perform-replace regexp to-string t t delimited nil nil start end)))
  (define-key esc-map [?\C-%] 'query-replace-regexp)
  
  (defun query-replace-regexp-eval (regexp to-expr &optional delimited start end)

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

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

* Re: query-replace-interactive not documented
  2004-06-15 14:29                       ` Juri Linkov
@ 2004-06-15 15:43                         ` David Kastrup
  2004-06-15 18:17                           ` Juri Linkov
                                             ` (2 more replies)
  2004-06-15 22:25                         ` Andreas Schwab
  1 sibling, 3 replies; 101+ messages in thread
From: David Kastrup @ 2004-06-15 15:43 UTC (permalink / raw)
  Cc: emacs-devel, rms, storm

Juri Linkov <juri@jurta.org> writes:

> David Kastrup <dak@gnu.org> writes:
> > storm@cua.dk (Kim F. Storm) writes:
> >> Richard Stallman <rms@gnu.org> writes:
> >> > That seems like an interesting idea.
> >> 
> >> I would prefer a syntax which can be parsed with `read', which
> >> includes the second example above, but not the first one.
> >
> > Well, this was of course just a wild proposal without any serious
> > thought behind the involved details.  One should probably take a look
> > at eshell syntax maybe for getting some suggestions for a somewhat
> > consistent syntax, and one would need to think about a way that makes
> > it possible to end the expression in question without adding
> > unnecessary spaces or so to the match.
> 
> I like this idea.  To avoid problems with `read' and to end the expression
> explicitly I suggest to always place the expression in parenthesis.
> To use a single variable inside a replacement string, one can use
> a no-op function like `+':
> 
>     \\footnote{\\label{fn:\!(+ replace-count)}

If there are always to be parens around, then there would be no need for
!.  One could just write

\\footnote{\\label{fn:\(+ replace-count\)}

I don't see a good way around having to backslash the closing paren:
if one doesn't, paren matching goes awry.

> > And of course, this sort of stuff should not be done by
> > replace-match or similar functions but just by the interactive
> > function, to avoid opening security concerns when Emacs is used as
> > a match-and-replace engine (where people don't expect it to
> > execute arbitrary code).
> 
> Doing it only in the interactive function instead of `replace-match'
> seems right.  This is needed only to save keystrokes for users.
> Since `replace-match' is not a command, when the programmer writes a
> loop with `re-search-forward' and `replace-match', he can construct
> a replacement string explicitly with appropriate functions.
> 
> Anyway, below is a quick implementation of such a feature.  I tried it
> a bit and I like it.  What I don't like yet is the choice of a special
> meta symbol `\!'.  Usually this symbol is associated with the error code.
> Perhaps, a better symbol would be \( itself like in:
> 
>     \\footnote{\\label{fn:\(+ replace-count)}
> 
> but this has another problem: the open parenthesis is escaped
> and Emacs commands don't match it with the close parenthesis.

Oh shucks.  That's what I get from replying before reading to the end.
Anyway, since it appears that we can hardly avoid using non-escaped
parens if we want to make use of the Lisp reader as well as paren
matching, one might as well use the original proposal allowing a
variable name directly.

How about using \'?  After all, we have an unevaled expression
following.

That would allow either

\\footnote{\\label{fn:\'(+ replace-count)}

or

\\footnote{\\label{fn:\'replace-count }}

Well, the latter has a spurious space.  Bother.

> Index: replace.el
> ===================================================================
> RCS file: /cvsroot/emacs/emacs/lisp/replace.el,v
> retrieving revision 1.172
> diff -c -r1.172 replace.el
> *** replace.el	10 Jun 2004 04:21:14 -0000	1.172
> --- replace.el	15 Jun 2004 14:56:15 -0000
> ***************
> *** 174,180 ****
>   	   (if (and transient-mark-mode mark-active)
>   	       (region-end)))))
>   
> !   (perform-replace regexp to-string t t delimited nil nil start end))
>   (define-key esc-map [?\C-%] 'query-replace-regexp)
>   
>   (defun query-replace-regexp-eval (regexp to-expr &optional delimited start end)
> --- 183,200 ----
>   	   (if (and transient-mark-mode mark-active)
>   	       (region-end)))))
>   
> !   (if (string-match "!\(" to-string)
> !       (let (res)
> !         (while (string-match "!\(" to-string)
> !           (setq res (cons (substring to-string 0 (1- (match-beginning 0))) res)
> !                 to-string (substring to-string (1- (match-end 0))))
> !           (let ((r (read-from-string to-string)))
> !             (setq res (cons `(format "%s" ,(car r)) res)
> !                   to-string (substring to-string (cdr r)))))
> !         (perform-replace regexp `(replace-eval-replacement
> !                                   concat ,@(nreverse (cons to-string res)))
> !                          t 'literal delimited nil nil start end))
> !     (perform-replace regexp to-string t t delimited nil nil start end)))
>   (define-key esc-map [?\C-%] 'query-replace-regexp)
>   
>   (defun query-replace-regexp-eval (regexp to-expr &optional delimited start end)

First you are matching against !( not against \!( or similar.  Then
you are not replacing any \1 \2 or similar sequences as far as I can
see.  It will probably not be easy to do this right: have the \(
replacement not being interpreted afterwards, but the non-evalled
ones still being interpreted.  Probably one needs to explicitly
double any \ returned from the evaluation, and then call
perform-replace with "t" instead of 'literal.

Something like that.

-- 
David Kastrup, Kriemhildstr. 15, 44793 Bochum

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

* Re: query-replace-interactive not documented
  2004-06-15 15:43                         ` David Kastrup
@ 2004-06-15 18:17                           ` Juri Linkov
  2004-06-15 20:23                             ` David Kastrup
  2004-06-15 22:30                             ` Andreas Schwab
  2004-06-16  1:41                           ` Miles Bader
  2004-06-16 16:57                           ` Richard Stallman
  2 siblings, 2 replies; 101+ messages in thread
From: Juri Linkov @ 2004-06-15 18:17 UTC (permalink / raw)
  Cc: emacs-devel, rms, storm

David Kastrup <dak@gnu.org> writes:
> Anyway, since it appears that we can hardly avoid using non-escaped
> parens if we want to make use of the Lisp reader as well as paren
> matching, one might as well use the original proposal allowing a
> variable name directly.

Yes, I think paren matching is needed for editing Lisp expressions
in the minibuffer.

> How about using \'?  After all, we have an unevaled expression
> following.

In regexps \' is used to match the empty string at the end of the
buffer.  But perhaps in the replacement string this symbol is free
to use.  Also in some pattern-matching languages like Perl $' is
an alias for $POSTMATCH.  But I don't see what it could mean in the
context of `query-replace-regexp'.  So unless a potential meaning for
\' in `query-replace-regexp' will be proposed, I think \' is a good
symbol which would have mnemonics of quoting Lisp expression.

> First you are matching against !( not against \!( or similar.

OK, this is the easiest part.  I tried different prefixes and messed up
the latest one.

> Then you are not replacing any \1 \2 or similar sequences as far as
> I can see.  It will probably not be easy to do this right: have the
> \( replacement not being interpreted afterwards, but the non-evalled
> ones still being interpreted.  Probably one needs to explicitly
> double any \ returned from the evaluation, and then call
> perform-replace with "t" instead of 'literal.

Replacing backreferences in expressions is easy: it is just one call
to `replace-match-string-symbols'.  Replacing them in strings is easy
as well: just using t instead of `literal'.  However, this has one
side-effect: when evaluation returns a string in the form \D, then it
is substituted later for the Dth occurrence.  But I think this is right:
it allows to construct replacement strings by Lisp expressions (though,
it is not very needed).

Anyway, with the current implementation all three expressions below
produce the same replacement for the entire string:

\& = \'\& = \'"\\&"

Here is the newest version.  I tested it a little, and it seems
it works in all mentioned cases.

Index: replace.el
===================================================================
RCS file: /cvsroot/emacs/emacs/lisp/replace.el,v
retrieving revision 1.172
diff -c -r1.172 replace.el
*** replace.el	10 Jun 2004 04:21:14 -0000	1.172
--- replace.el	15 Jun 2004 17:57:28 -0000
***************
*** 174,179 ****
--- 183,199 ----
  	   (if (and transient-mark-mode mark-active)
  	       (region-end)))))
  
+   (if (string-match "\\\\'" to-string)
+       (let (to expr)
+         (while (string-match "\\\\'" to-string)
+           (setq to  (cons (substring to-string 0 (match-beginning 0)) to)
+                 to-string (substring to-string   (match-end       0))
+                 expr      (read-from-string to-string)
+                 to        (cons `(format "%s" ,(car expr)) to)
+                 to-string (substring to-string (cdr expr))))
+         (setq to (nreverse (cons to-string to)))
+         (replace-match-string-symbols to)
+         (setq to-string `(replace-eval-replacement concat ,@to))))
    (perform-replace regexp to-string t t delimited nil nil start end))
  (define-key esc-map [?\C-%] 'query-replace-regexp)

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

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

* Re: query-replace-interactive not documented
  2004-06-15 18:17                           ` Juri Linkov
@ 2004-06-15 20:23                             ` David Kastrup
  2004-06-15 22:30                             ` Andreas Schwab
  1 sibling, 0 replies; 101+ messages in thread
From: David Kastrup @ 2004-06-15 20:23 UTC (permalink / raw)
  Cc: emacs-devel, rms, storm

Juri Linkov <juri@jurta.org> writes:

> David Kastrup <dak@gnu.org> writes:
> > Anyway, since it appears that we can hardly avoid using non-escaped
> > parens if we want to make use of the Lisp reader as well as paren
> > matching, one might as well use the original proposal allowing a
> > variable name directly.
> 
> Yes, I think paren matching is needed for editing Lisp expressions
> in the minibuffer.
> 
> > How about using \'?  After all, we have an unevaled expression
> > following.
> 
> In regexps \' is used to match the empty string at the end of the
> buffer.  But perhaps in the replacement string this symbol is free
> to use.  Also in some pattern-matching languages like Perl $' is
> an alias for $POSTMATCH.  But I don't see what it could mean in the
> context of `query-replace-regexp'.  So unless a potential meaning for
> \' in `query-replace-regexp' will be proposed, I think \' is a good
> symbol which would have mnemonics of quoting Lisp expression.
> 
> > First you are matching against !( not against \!( or similar.
> 
> OK, this is the easiest part.  I tried different prefixes and messed up
> the latest one.

Ok.

> > Then you are not replacing any \1 \2 or similar sequences as far as
> > I can see.  It will probably not be easy to do this right: have the
> > \( replacement not being interpreted afterwards, but the non-evalled
> > ones still being interpreted.  Probably one needs to explicitly
> > double any \ returned from the evaluation, and then call
> > perform-replace with "t" instead of 'literal.
> 
> Replacing backreferences in expressions is easy: it is just one call
> to `replace-match-string-symbols'.  Replacing them in strings is easy
> as well: just using t instead of `literal'.  However, this has one
> side-effect: when evaluation returns a string in the form \D, then it
> is substituted later for the Dth occurrence.  But I think this is right:
> it allows to construct replacement strings by Lisp expressions (though,
> it is not very needed).

It is not even unneeded, it is even completely wrong.  That is why
there had been the 'literal stuff in the first place.  You can use
things like \1 and \2 also in the Lisp expression, and if they match,
say, \footnote, things will go horribly wrong because of that
additional backslash interpretation.

> Anyway, with the current implementation all three expressions below
> produce the same replacement for the entire string:
> 
> \& = \'\& = \'"\\&"

The latter is wrong IMO.  A string is a string is a string.

-- 
David Kastrup, Kriemhildstr. 15, 44793 Bochum

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

* Re: query-replace-interactive not documented
  2004-06-15 14:29                       ` Juri Linkov
  2004-06-15 15:43                         ` David Kastrup
@ 2004-06-15 22:25                         ` Andreas Schwab
  2004-06-15 22:28                           ` Kim F. Storm
  1 sibling, 1 reply; 101+ messages in thread
From: Andreas Schwab @ 2004-06-15 22:25 UTC (permalink / raw)
  Cc: David Kastrup, rms, storm, emacs-devel

Juri Linkov <juri@jurta.org> writes:

> To use a single variable inside a replacement string, one can use
> a no-op function like `+':

Or even progn.

Andreas.

-- 
Andreas Schwab, SuSE Labs, schwab@suse.de
SuSE Linux AG, Maxfeldstraße 5, 90409 Nürnberg, Germany
Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."

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

* Re: query-replace-interactive not documented
  2004-06-15 22:25                         ` Andreas Schwab
@ 2004-06-15 22:28                           ` Kim F. Storm
  2004-06-16  9:00                             ` Juri Linkov
  0 siblings, 1 reply; 101+ messages in thread
From: Kim F. Storm @ 2004-06-15 22:28 UTC (permalink / raw)
  Cc: Juri Linkov, David Kastrup, rms, emacs-devel

Andreas Schwab <schwab@suse.de> writes:

> Juri Linkov <juri@jurta.org> writes:
> 
> > To use a single variable inside a replacement string, one can use
> > a no-op function like `+':
> 
> Or even progn.

Or or, which is even shorter...

-- 
Kim F. Storm <storm@cua.dk> http://www.cua.dk

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

* Re: query-replace-interactive not documented
  2004-06-15 18:17                           ` Juri Linkov
  2004-06-15 20:23                             ` David Kastrup
@ 2004-06-15 22:30                             ` Andreas Schwab
  2004-06-15 22:36                               ` David Kastrup
  2004-06-16  8:17                               ` Juri Linkov
  1 sibling, 2 replies; 101+ messages in thread
From: Andreas Schwab @ 2004-06-15 22:30 UTC (permalink / raw)
  Cc: David Kastrup, rms, storm, emacs-devel

Juri Linkov <juri@jurta.org> writes:

> Index: replace.el
> ===================================================================
> RCS file: /cvsroot/emacs/emacs/lisp/replace.el,v
> retrieving revision 1.172
> diff -c -r1.172 replace.el
> *** replace.el	10 Jun 2004 04:21:14 -0000	1.172
> --- replace.el	15 Jun 2004 17:57:28 -0000
> ***************
> *** 174,179 ****
> --- 183,199 ----
>   	   (if (and transient-mark-mode mark-active)
>   	       (region-end)))))
>   
> +   (if (string-match "\\\\'" to-string)
> +       (let (to expr)
> +         (while (string-match "\\\\'" to-string)

That needs more careful treatment, to handle cases like "\\\\'" where one
wants to substitute a backslash followed by a single quote.

Andreas.

-- 
Andreas Schwab, SuSE Labs, schwab@suse.de
SuSE Linux AG, Maxfeldstraße 5, 90409 Nürnberg, Germany
Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."

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

* Re: query-replace-interactive not documented
  2004-06-15 22:30                             ` Andreas Schwab
@ 2004-06-15 22:36                               ` David Kastrup
  2004-06-15 22:43                                 ` Kim F. Storm
  2004-06-16  8:17                               ` Juri Linkov
  1 sibling, 1 reply; 101+ messages in thread
From: David Kastrup @ 2004-06-15 22:36 UTC (permalink / raw)
  Cc: Juri Linkov, storm, rms, emacs-devel

Andreas Schwab <schwab@suse.de> writes:

> Juri Linkov <juri@jurta.org> writes:
> 
> > Index: replace.el
> > ===================================================================
> > RCS file: /cvsroot/emacs/emacs/lisp/replace.el,v
> > retrieving revision 1.172
> > diff -c -r1.172 replace.el
> > *** replace.el	10 Jun 2004 04:21:14 -0000	1.172
> > --- replace.el	15 Jun 2004 17:57:28 -0000
> > ***************
> > *** 174,179 ****
> > --- 183,199 ----
> >   	   (if (and transient-mark-mode mark-active)
> >   	       (region-end)))))
> >   
> > +   (if (string-match "\\\\'" to-string)
> > +       (let (to expr)
> > +         (while (string-match "\\\\'" to-string)
> 
> That needs more careful treatment, to handle cases like "\\\\'" where one
> wants to substitute a backslash followed by a single quote.

I am going to take a stab at this.

-- 
David Kastrup, Kriemhildstr. 15, 44793 Bochum

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

* Re: query-replace-interactive not documented
  2004-06-15 22:36                               ` David Kastrup
@ 2004-06-15 22:43                                 ` Kim F. Storm
  2004-06-15 23:13                                   ` David Kastrup
                                                     ` (2 more replies)
  0 siblings, 3 replies; 101+ messages in thread
From: Kim F. Storm @ 2004-06-15 22:43 UTC (permalink / raw)
  Cc: Juri Linkov, Andreas Schwab, rms, emacs-devel

David Kastrup <dak@gnu.org> writes:

> Andreas Schwab <schwab@suse.de> writes:
> 
> > Juri Linkov <juri@jurta.org> writes:
> > 
> > > Index: replace.el
> > > ===================================================================
> > > RCS file: /cvsroot/emacs/emacs/lisp/replace.el,v
> > > retrieving revision 1.172
> > > diff -c -r1.172 replace.el
> > > *** replace.el	10 Jun 2004 04:21:14 -0000	1.172
> > > --- replace.el	15 Jun 2004 17:57:28 -0000
> > > ***************
> > > *** 174,179 ****
> > > --- 183,199 ----
> > >   	   (if (and transient-mark-mode mark-active)
> > >   	       (region-end)))))
> > >   
> > > +   (if (string-match "\\\\'" to-string)
> > > +       (let (to expr)
> > > +         (while (string-match "\\\\'" to-string)
> > 
> > That needs more careful treatment, to handle cases like "\\\\'" where one
> > wants to substitute a backslash followed by a single quote.
> 
> I am going to take a stab at this.


I don't like the \'(...) form  -- to me ' means "DONT INTERPRET"

Maybe \=(...) is better ?

Also, \? could be used to ask the user for a string to insert at
that point in each replacement...


-- 
Kim F. Storm <storm@cua.dk> http://www.cua.dk

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

* Re: query-replace-interactive not documented
  2004-06-15 22:43                                 ` Kim F. Storm
@ 2004-06-15 23:13                                   ` David Kastrup
  2004-06-16  1:16                                     ` David Kastrup
  2004-06-16  8:02                                   ` Juri Linkov
  2004-06-17  5:06                                   ` Richard Stallman
  2 siblings, 1 reply; 101+ messages in thread
From: David Kastrup @ 2004-06-15 23:13 UTC (permalink / raw)
  Cc: Juri Linkov, Andreas Schwab, rms, emacs-devel

storm@cua.dk (Kim F. Storm) writes:

> David Kastrup <dak@gnu.org> writes:
> 
> > Andreas Schwab <schwab@suse.de> writes:
> > 
> > > Juri Linkov <juri@jurta.org> writes:
> > > 
> > > > Index: replace.el
> > > > ===================================================================
> > > > RCS file: /cvsroot/emacs/emacs/lisp/replace.el,v
> > > > retrieving revision 1.172
> > > > diff -c -r1.172 replace.el
> > > > *** replace.el	10 Jun 2004 04:21:14 -0000	1.172
> > > > --- replace.el	15 Jun 2004 17:57:28 -0000
> > > > ***************
> > > > *** 174,179 ****
> > > > --- 183,199 ----
> > > >   	   (if (and transient-mark-mode mark-active)
> > > >   	       (region-end)))))
> > > >   
> > > > +   (if (string-match "\\\\'" to-string)
> > > > +       (let (to expr)
> > > > +         (while (string-match "\\\\'" to-string)
> > > 
> > > That needs more careful treatment, to handle cases like "\\\\'" where one
> > > wants to substitute a backslash followed by a single quote.
> > 
> > I am going to take a stab at this.
> 
> 
> I don't like the \'(...) form  -- to me ' means "DONT INTERPRET"

Well, it _is_ a delayed interpretation after all.

Another option may be
\`read-expression optionally followed by ' which gives us

\\footnote{\\label{fn:\`replace-count'}}

as well as

\\footnote{\\label{fn:\`(or replace-count)}}

\` has somewhat more of a "will be evaluated later" scent and it has
the advantage that it is somewhat natural to match it up with ' in
case we need to explicitly end the read expression.

> Maybe \=(...) is better ?

= is really comparison in my book instead of evaluation...

> Also, \? could be used to ask the user for a string to insert at
> that point in each replacement...

One after the other.

-- 
David Kastrup, Kriemhildstr. 15, 44793 Bochum

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

* Re: query-replace-interactive not documented
  2004-06-15 23:13                                   ` David Kastrup
@ 2004-06-16  1:16                                     ` David Kastrup
  2004-06-16  8:08                                       ` Juri Linkov
  0 siblings, 1 reply; 101+ messages in thread
From: David Kastrup @ 2004-06-16  1:16 UTC (permalink / raw)
  Cc: Juri Linkov, Andreas Schwab, rms, emacs-devel

[-- Attachment #1: Type: text/plain, Size: 1171 bytes --]

David Kastrup <dak@gnu.org> writes:

> Another option may be
> \`read-expression optionally followed by ' which gives us
> 
> \\footnote{\\label{fn:\`replace-count'}}
> 
> as well as
> 
> \\footnote{\\label{fn:\`(or replace-count)}}
> 
> \` has somewhat more of a "will be evaluated later" scent and it has
> the advantage that it is somewhat natural to match it up with ' in
> case we need to explicitly end the read expression.

Ok, here is the whole ugly thing: it certainly won't interfere with
programming since it does all the work in the interactive spec (see
C-x ESC ESC for the show.  BTW, can anybody tell me how the command
history manages to record the last two arguments unevaluated?  I can't
for the life of me figure out how this works), so certainly no
security risk.

You can use all the special symbols that are available in
query-replace-regexp-eval, too, like \& \#1 and so on.

If somebody has a good suggestion how one could get rid of
replace-requote in the command history, it would be nice to hear.
But I really think that \`"\\3"' should deliver a _verbatim_ \3, or
we could have written \`\3' in the first place.

Docstring missing as to yet.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: Type: text/x-patch, Size: 2501 bytes --]

--- replace.el	10 Jun 2004 09:36:09 +0200	1.172
+++ replace.el	16 Jun 2004 03:01:16 +0200	
@@ -165,16 +165,44 @@
   (interactive
    (let ((common
 	  (query-replace-read-args "Query replace regexp" t)))
-     (list (nth 0 common) (nth 1 common) (nth 2 common)
-	   ;; These are done separately here
-	   ;; so that command-history will record these expressions
-	   ;; rather than the values they had this time.
-	   (if (and transient-mark-mode mark-active)
-	       (region-beginning))
-	   (if (and transient-mark-mode mark-active)
-	       (region-end)))))
-
+     (list
+      (nth 0 common)
+      (if (string-match "\\(\\`\\|[^\\]\\)\\(\\\\\\\\\\)*\\\\`"
+			(nth 1 common))
+	  (let ((to-string (nth 1 common)) (pos (match-end 0)) to-expr)
+	    (while pos
+	      (when (> pos 2)
+		(push (substring to-string 0 (- pos 2)) to-expr))
+	      (setq pos (read-from-string to-string pos))
+	      (push `(replace-requote ,(pop pos)) to-expr)
+	      (setq to-string (and (< pos (length to-string))
+				   (substring to-string
+					      (if (eq (aref to-string pos) ?')
+						  (1+ pos)
+						pos)))
+		    pos (and
+			 to-string
+			 (string-match "\\(\\`\\|[^\\]\\)\\(\\\\\\\\\\)*\\\\`"
+				       to-string)
+			 (match-end 0))))
+	    (unless (zerop (length to-string))
+	      (push to-string to-expr))
+	    (replace-match-string-symbols to-expr)
+	    (cons 'replace-eval-replacement 
+		  (if (> (length to-expr) 1)
+		      (cons 'concat (nreverse to-expr))
+		    (car to-expr))))
+	(nth 1 common))
+      (nth 2 common)
+      ;; These are done separately here
+      ;; so that command-history will record these expressions
+      ;; rather than the values they had this time.
+      (if (and transient-mark-mode mark-active)
+	  (region-beginning))
+      (if (and transient-mark-mode mark-active)
+	  (region-end)))))
   (perform-replace regexp to-string t t delimited nil nil start end))
+
 (define-key esc-map [?\C-%] 'query-replace-regexp)
 
 (defun query-replace-regexp-eval (regexp to-expr &optional delimited start end)
@@ -1040,6 +1068,14 @@
         replacement
       (prin1-to-string replacement t))))
 
+(defun replace-requote (replacement)
+  (save-match-data
+    (replace-regexp-in-string "\\\\" "\\\\"
+			      (if (stringp replacement)
+				  replacement
+				(prin1-to-string replacement t))
+			      t t)))
+
 (defun replace-loop-through-replacements (data replace-count)
   ;; DATA is a vector contaning the following values:
   ;;   0 next-rotate-count

[-- Attachment #3: Type: text/plain, Size: 52 bytes --]



-- 
David Kastrup, Kriemhildstr. 15, 44793 Bochum

[-- Attachment #4: Type: text/plain, Size: 142 bytes --]

_______________________________________________
Emacs-devel mailing list
Emacs-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/emacs-devel

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

* Re: query-replace-interactive not documented
  2004-06-15 15:43                         ` David Kastrup
  2004-06-15 18:17                           ` Juri Linkov
@ 2004-06-16  1:41                           ` Miles Bader
  2004-06-16  2:01                             ` David Kastrup
  2004-06-16 16:57                           ` Richard Stallman
  2 siblings, 1 reply; 101+ messages in thread
From: Miles Bader @ 2004-06-16  1:41 UTC (permalink / raw)
  Cc: Juri Linkov, storm, rms, emacs-devel

On Tue, Jun 15, 2004 at 05:43:52PM +0200, David Kastrup wrote:
> How about using \'?  After all, we have an unevaled expression
> following.

I think it should use \, (backslash-comma), as comma is the `unquote'
chracter for backquote.

-Miles
-- 
.Numeric stability is probably not all that important when you're guessing.

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

* Re: query-replace-interactive not documented
  2004-06-16  1:41                           ` Miles Bader
@ 2004-06-16  2:01                             ` David Kastrup
  2004-06-16  2:11                               ` Miles Bader
  0 siblings, 1 reply; 101+ messages in thread
From: David Kastrup @ 2004-06-16  2:01 UTC (permalink / raw)
  Cc: Juri Linkov, storm, rms, emacs-devel

Miles Bader <miles@gnu.org> writes:

> On Tue, Jun 15, 2004 at 05:43:52PM +0200, David Kastrup wrote:
> > How about using \'?  After all, we have an unevaled expression
> > following.
> 
> I think it should use \, (backslash-comma), as comma is the `unquote'
> chracter for backquote.

That makes sense.  It has the disadvantage as compared to my more
recent proposal \` that it has no running mate like ' to complete the
expression in case that we want to write something like
\`replace-count'}
where otherwise replace-count} would become a single symbol.

Or should we perhaps just discard a single optional _space_ after the
expression?  That would mean also

\,(1+ replace-count) xxx
                    ^ this space would get removed.

-- 
David Kastrup, Kriemhildstr. 15, 44793 Bochum

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

* Re: query-replace-interactive not documented
  2004-06-16  2:01                             ` David Kastrup
@ 2004-06-16  2:11                               ` Miles Bader
  0 siblings, 0 replies; 101+ messages in thread
From: Miles Bader @ 2004-06-16  2:11 UTC (permalink / raw)
  Cc: Juri Linkov, emacs-devel, rms, storm, Miles Bader

On Wed, Jun 16, 2004 at 04:01:07AM +0200, David Kastrup wrote:
> It has the disadvantage as compared to my more
> recent proposal \` that it has no running mate like ' to complete the
> expression in case that we want to write something like
> \`replace-count'}
> where otherwise replace-count} would become a single symbol.

Is it not possible to tweak the reader so that only `normal' variables are
read, and it stops reading at the "}"?  That would make the common case very
convenient, and anyone who really wanted to use a weirdly named variable in
that location could just use (progn WEIRD{}34) instead.  I think since it's
clearly an odd situation (a lisp expression embedded in the middle an
otherwise uninterpreted string), users would probably find such a reader
`restriction' fairly natural.

-Miles
-- 
I'm beginning to think that life is just one long Yoko Ono album; no rhyme
or reason, just a lot of incoherent shrieks and then it's over.  --Ian Wolff

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

* Re: query-replace-interactive not documented
  2004-06-15 22:43                                 ` Kim F. Storm
  2004-06-15 23:13                                   ` David Kastrup
@ 2004-06-16  8:02                                   ` Juri Linkov
  2004-06-17  5:06                                   ` Richard Stallman
  2 siblings, 0 replies; 101+ messages in thread
From: Juri Linkov @ 2004-06-16  8:02 UTC (permalink / raw)
  Cc: David Kastrup, emacs-devel

storm@cua.dk (Kim F. Storm) writes:
> Also, \? could be used to ask the user for a string to insert at
> that point in each replacement...

Good idea!  Below is an improved version.

Index: replace.el
===================================================================
RCS file: /cvsroot/emacs/emacs/lisp/replace.el,v
retrieving revision 1.172
diff -c -r1.172 replace.el
*** replace.el	10 Jun 2004 04:21:14 -0000	1.172
--- replace.el	15 Jun 2004 17:57:28 -0000
@@ -174,6 +183,23 @@
 	   (if (and transient-mark-mode mark-active)
 	       (region-end)))))
 
+  (if (string-match "\\(\\`\\|[^\\]\\)\\(\\\\\\\\\\)*\\\\[`?]" to-string)
+      (let (to expr sym)
+        (while (string-match "\\(\\`\\|[^\\]\\)\\(\\\\\\\\\\)*\\\\\\([`?]\\)" to-string)
+          (setq sym (match-string 3 to-string)
+                to  (cons (substring to-string 0 (- (match-end 0) 2)) to)
+                to-string (substring to-string      (match-end 0)))
+          (cond
+           ((equal sym "`")
+            (setq expr      (read-from-string to-string)
+                  to        (cons `(format "%s" ,(car expr)) to)
+                  to-string (substring to-string (cdr expr))))
+           ((equal sym "?")
+            (setq to        (cons `(read-string "Enter string: ") to)))))
+        (setq to (nreverse (delete "" (cons to-string to))))
+        (replace-match-string-symbols to)
+        (setq to-string `(replace-eval-replacement concat ,@to))))
   (perform-replace regexp to-string t t delimited nil nil start end))
 (define-key esc-map [?\C-%] 'query-replace-regexp)

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

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

* Re: query-replace-interactive not documented
  2004-06-16  1:16                                     ` David Kastrup
@ 2004-06-16  8:08                                       ` Juri Linkov
  2004-06-16  9:23                                         ` David Kastrup
  0 siblings, 1 reply; 101+ messages in thread
From: Juri Linkov @ 2004-06-16  8:08 UTC (permalink / raw)
  Cc: emacs-devel

David Kastrup <dak@gnu.org> writes:
>> Another option may be
>> \`read-expression optionally followed by ' which gives us
>> 
>> \\footnote{\\label{fn:\`replace-count'}}
>> 
>> as well as
>> 
>> \\footnote{\\label{fn:\`(or replace-count)}}
>> 
>> \` has somewhat more of a "will be evaluated later" scent and it has
>> the advantage that it is somewhat natural to match it up with ' in
>> case we need to explicitly end the read expression.

Perhaps \` is a better symbol than \', but having a special
meaning of ' following the expression seems wrong.  This is
an additional rule that the user should learn, and it may produce
undesirable results when users forget this rule and put ' with
the intention to use it in the replacement.

> Ok, here is the whole ugly thing: it certainly won't interfere with
> programming since it does all the work in the interactive spec (see
> C-x ESC ESC for the show.  BTW, can anybody tell me how the command
> history manages to record the last two arguments unevaluated?  I can't
> for the life of me figure out how this works), so certainly no
> security risk.

I think moving the code into the interactive spec is not needed.
There is no security risk in having it in the function body,
because the `query-flag' argument of `perform-replace' is t,
which means that even when the function `query-replace-regexp'
is called non-interactively the user can see the replacement string
and type `y' if he agrees with it.

> If somebody has a good suggestion how one could get rid of
> replace-requote in the command history, it would be nice to hear.
> But I really think that \`"\\3"' should deliver a _verbatim_ \3, or
> we could have written \`\3' in the first place.

This imposes artificial restrictions on what the user can do.  The user
may want to construct a replacement string with backreferences in the
Lisp expression.  I think that only the user should decide whether he
wants a verbatim \3 or its replacement.  He can add backslashes for
the literal meaning and write \`"\\\\3"' instead of \`"\\3"'.

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

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

* Re: query-replace-interactive not documented
  2004-06-15 22:30                             ` Andreas Schwab
  2004-06-15 22:36                               ` David Kastrup
@ 2004-06-16  8:17                               ` Juri Linkov
  2004-06-16  9:01                                 ` David Kastrup
  2004-06-16  9:02                                 ` Andreas Schwab
  1 sibling, 2 replies; 101+ messages in thread
From: Juri Linkov @ 2004-06-16  8:17 UTC (permalink / raw)
  Cc: David Kastrup, emacs-devel

Andreas Schwab <schwab@suse.de> writes:
>> +   (if (string-match "\\\\'" to-string)
>> +       (let (to expr)
>> +         (while (string-match "\\\\'" to-string)
>
> That needs more careful treatment, to handle cases like "\\\\'" where one
> wants to substitute a backslash followed by a single quote.

It seems the regexp from David's version handles it right:

(string-match "\\(\\`\\|[^\\]\\)\\(\\\\\\\\\\)*\\\\`")

Do you see any problems with it?

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

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

* Re: query-replace-interactive not documented
  2004-06-15 22:28                           ` Kim F. Storm
@ 2004-06-16  9:00                             ` Juri Linkov
  2004-06-16  9:25                               ` Andreas Schwab
  2004-06-16  9:32                               ` David Kastrup
  0 siblings, 2 replies; 101+ messages in thread
From: Juri Linkov @ 2004-06-16  9:00 UTC (permalink / raw)
  Cc: schwab, dak, emacs-devel

storm@cua.dk (Kim F. Storm) writes:
> Andreas Schwab <schwab@suse.de> writes:
>> Juri Linkov <juri@jurta.org> writes:
>> > To use a single variable inside a replacement string, one can use
>> > a no-op function like `+':
>> 
>> Or even progn.
>
> Or or, which is even shorter...

Which is shorter only for non-numeric variables.
But for numeric variables + is the shortest one.

But there is still one too long name that the user should type:
`replace-count'.  WIBN to have aliases for this name?
At least, `c' and `i' would make sense.

So, instead of:

C-M-% \\footnote{ RET \&\\label{fn:\,(+ replace-count)} RET

to type:

C-M-% \\footnote{ RET \&\\label{fn:\,(+ c)} RET

or to add a special symbol for replace-count, e.g. \!:

C-M-% \\footnote{ RET \&\\label{fn:\!} RET

and make it possible to use it even in expressions:

C-M-% \\footnote{ RET \&\\label{fn:\,(+ 1000 \!)} RET

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

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

* Re: query-replace-interactive not documented
  2004-06-16  8:17                               ` Juri Linkov
@ 2004-06-16  9:01                                 ` David Kastrup
  2004-06-16 17:06                                   ` Kevin Rodgers
  2004-06-16  9:02                                 ` Andreas Schwab
  1 sibling, 1 reply; 101+ messages in thread
From: David Kastrup @ 2004-06-16  9:01 UTC (permalink / raw)
  Cc: Andreas Schwab, emacs-devel

Juri Linkov <juri@jurta.org> writes:

> Andreas Schwab <schwab@suse.de> writes:
> >> +   (if (string-match "\\\\'" to-string)
> >> +       (let (to expr)
> >> +         (while (string-match "\\\\'" to-string)
> >
> > That needs more careful treatment, to handle cases like "\\\\'" where one
> > wants to substitute a backslash followed by a single quote.
> 
> It seems the regexp from David's version handles it right:
> 
> (string-match "\\(\\`\\|[^\\]\\)\\(\\\\\\\\\\)*\\\\`")
> 
> Do you see any problems with it?

Somebody has a pattern matching problem.  He says "I know, I'll use
regular expressions for it".  Now he has two problems.  SCNR.

In short: it is not beautiful, but I don't see how this could be
improved.  And a problem with the above is that \` only matches at
position 0 of a string, not at the point where you start matching.  So
you need to explicitly digest the string with "substring" while
parsing to keep this working.

Perhaps the starting index of a string match should match on \= in
analogy to the "starting index" of a buffer match?

But that's just an aside note.

-- 
David Kastrup, Kriemhildstr. 15, 44793 Bochum

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

* Re: query-replace-interactive not documented
  2004-06-16  8:17                               ` Juri Linkov
  2004-06-16  9:01                                 ` David Kastrup
@ 2004-06-16  9:02                                 ` Andreas Schwab
  1 sibling, 0 replies; 101+ messages in thread
From: Andreas Schwab @ 2004-06-16  9:02 UTC (permalink / raw)
  Cc: David Kastrup, emacs-devel

Juri Linkov <juri@jurta.org> writes:

> It seems the regexp from David's version handles it right:
>
> (string-match "\\(\\`\\|[^\\]\\)\\(\\\\\\\\\\)*\\\\`")
>
> Do you see any problems with it?

The only problem is that it's hard to grok. :-)

Andreas.

-- 
Andreas Schwab, SuSE Labs, schwab@suse.de
SuSE Linux AG, Maxfeldstraße 5, 90409 Nürnberg, Germany
Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."

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

* Re: query-replace-interactive not documented
  2004-06-16  8:08                                       ` Juri Linkov
@ 2004-06-16  9:23                                         ` David Kastrup
  0 siblings, 0 replies; 101+ messages in thread
From: David Kastrup @ 2004-06-16  9:23 UTC (permalink / raw)
  Cc: emacs-devel

Juri Linkov <juri@jurta.org> writes:

> David Kastrup <dak@gnu.org> writes:
> >> Another option may be
> >> \`read-expression optionally followed by ' which gives us
> >> 
> >> \\footnote{\\label{fn:\`replace-count'}}
> >> 
> >> as well as
> >> 
> >> \\footnote{\\label{fn:\`(or replace-count)}}
> >> 
> >> \` has somewhat more of a "will be evaluated later" scent and it has
> >> the advantage that it is somewhat natural to match it up with ' in
> >> case we need to explicitly end the read expression.
> 
> Perhaps \` is a better symbol than \', but having a special
> meaning of ' following the expression seems wrong.  This is
> an additional rule that the user should learn, and it may produce
> undesirable results when users forget this rule and put ' with
> the intention to use it in the replacement.

What about the \, proposal with a single optional additional space
following?  Most people are comfortable with such redundant spaces
and don't write things like
(format"%3d"27)
Sure, it is an extra rule, but more natural than the \`...' thing.

> > Ok, here is the whole ugly thing: it certainly won't interfere
> > with programming since it does all the work in the interactive
> > spec (see C-x ESC ESC for the show.  BTW, can anybody tell me how
> > the command history manages to record the last two arguments
> > unevaluated?  I can't for the life of me figure out how this
> > works), so certainly no security risk.
> 
> I think moving the code into the interactive spec is not needed.

It is what query-replace-regexp-eval does, too.

> There is no security risk in having it in the function body, because
> the `query-flag' argument of `perform-replace' is t, which means
> that even when the function `query-replace-regexp' is called
> non-interactively the user can see the replacement string and type
> `y' if he agrees with it.

At the time you see the replacement string, the evaluation has
already occured.

> > If somebody has a good suggestion how one could get rid of
> > replace-requote in the command history, it would be nice to hear.
> > But I really think that \`"\\3"' should deliver a _verbatim_ \3,
> > or we could have written \`\3' in the first place.
> 
> This imposes artificial restrictions on what the user can do.

No, it doesn't.

> The user may want to construct a replacement string with
> backreferences in the Lisp expression.

That's what the symbols \1 \2 \3 are for.

> I think that only the user should decide whether he wants a verbatim
> \3 or its replacement.

That's why he has both "\\3" and \3 at his disposal.

> He can add backslashes for the literal meaning and write \`"\\\\3"'
> instead of \`"\\3"'.

But he can't "add backslashes" for a string returned by (match-string)
or the equivalent \1: it is quite wrong to reinterpret backslashes in
a matched string if all I want is to use it as part of a replacement.

We had this discussion once already for query-replace-regexp-eval.
It was what prompted the change

2004-02-02  David Kastrup  <dak@gnu.org>

	* replace.el (perform-replace): Allow 'literal argument in
	regexp-flag to indicate literal replacement.
	(query-replace-regexp-eval): Use it.

-- 
David Kastrup, Kriemhildstr. 15, 44793 Bochum

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

* Re: query-replace-interactive not documented
  2004-06-16  9:00                             ` Juri Linkov
@ 2004-06-16  9:25                               ` Andreas Schwab
  2004-06-16  9:32                               ` David Kastrup
  1 sibling, 0 replies; 101+ messages in thread
From: Andreas Schwab @ 2004-06-16  9:25 UTC (permalink / raw)
  Cc: dak, emacs-devel, Kim F. Storm

Juri Linkov <juri@jurta.org> writes:

> So, instead of:
>
> C-M-% \\footnote{ RET \&\\label{fn:\,(+ replace-count)} RET
>
> to type:
>
> C-M-% \\footnote{ RET \&\\label{fn:\,(+ c)} RET
>
> or to add a special symbol for replace-count, e.g. \!:
>
> C-M-% \\footnote{ RET \&\\label{fn:\!} RET
>
> and make it possible to use it even in expressions:
>
> C-M-% \\footnote{ RET \&\\label{fn:\,(+ 1000 \!)} RET

IMHO this is much too obscure for a little used feature.  Use lisp symbol
completion instead.  Or you can add your own aliases yourself any time.

Andreas.

-- 
Andreas Schwab, SuSE Labs, schwab@suse.de
SuSE Linux AG, Maxfeldstraße 5, 90409 Nürnberg, Germany
Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."

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

* Re: query-replace-interactive not documented
  2004-06-16  9:00                             ` Juri Linkov
  2004-06-16  9:25                               ` Andreas Schwab
@ 2004-06-16  9:32                               ` David Kastrup
  2004-06-16 11:30                                 ` Kim F. Storm
  2004-06-17  5:07                                 ` Richard Stallman
  1 sibling, 2 replies; 101+ messages in thread
From: David Kastrup @ 2004-06-16  9:32 UTC (permalink / raw)
  Cc: schwab, emacs-devel, Kim F. Storm

Juri Linkov <juri@jurta.org> writes:

> storm@cua.dk (Kim F. Storm) writes:
> > Andreas Schwab <schwab@suse.de> writes:
> >> Juri Linkov <juri@jurta.org> writes:
> >> > To use a single variable inside a replacement string, one can use
> >> > a no-op function like `+':
> >> 
> >> Or even progn.
> >
> > Or or, which is even shorter...
> 
> Which is shorter only for non-numeric variables.
> But for numeric variables + is the shortest one.
> 
> But there is still one too long name that the user should type:
> `replace-count'.  WIBN to have aliases for this name?
> At least, `c' and `i' would make sense.
> 
> So, instead of:
> 
> C-M-% \\footnote{ RET \&\\label{fn:\,(+ replace-count)} RET
> 
> to type:
> 
> C-M-% \\footnote{ RET \&\\label{fn:\,(+ c)} RET

I'd rather say that since we already have special symbols
\1 \2 \3 \#1 \#2 \#3, that the most natural choice would probably be
just \# for the match number.  Then we'd have

\\label{fn:\,\# } RET

And it would probably make sense to define \# as a string component
on its own, too, so that we can just write
\\label{fn:\#} RET
if we want to.

-- 
David Kastrup, Kriemhildstr. 15, 44793 Bochum

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

* Re: query-replace-interactive not documented
  2004-06-16  9:32                               ` David Kastrup
@ 2004-06-16 11:30                                 ` Kim F. Storm
  2004-06-16 12:15                                   ` David Kastrup
  2004-06-17  5:07                                 ` Richard Stallman
  1 sibling, 1 reply; 101+ messages in thread
From: Kim F. Storm @ 2004-06-16 11:30 UTC (permalink / raw)
  Cc: Juri Linkov, schwab, emacs-devel

David Kastrup <dak@gnu.org> writes:

> Juri Linkov <juri@jurta.org> writes:
> 
> > storm@cua.dk (Kim F. Storm) writes:
> > > Andreas Schwab <schwab@suse.de> writes:
> > >> Juri Linkov <juri@jurta.org> writes:
> > >> > To use a single variable inside a replacement string, one can use
> > >> > a no-op function like `+':
> > >> 
> > >> Or even progn.
> > >
> > > Or or, which is even shorter...
> > 
> > Which is shorter only for non-numeric variables.
> > But for numeric variables + is the shortest one.
> > 
> > But there is still one too long name that the user should type:
> > `replace-count'.  WIBN to have aliases for this name?
> > At least, `c' and `i' would make sense.
> > 
> > So, instead of:
> > 
> > C-M-% \\footnote{ RET \&\\label{fn:\,(+ replace-count)} RET
> > 
> > to type:
> > 
> > C-M-% \\footnote{ RET \&\\label{fn:\,(+ c)} RET
> 
> I'd rather say that since we already have special symbols
> \1 \2 \3 \#1 \#2 \#3, that the most natural choice would probably be
> just \# for the match number.  Then we'd have
> 
> \\label{fn:\,\# } RET
> 
> And it would probably make sense to define \# as a string component
> on its own, too, so that we can just write
> \\label{fn:\#} RET
> if we want to.
> 

\, and \# both looks good to me.  

The extra space after the \, form should be optional, i.e. if there is
a space, remove it, if not, it's not an error.

I haven't studied the two proposed implementations in details,
but if there is an issue re. security and non-interactive calls,
it might make sense to simply not accept these formats if called
non-interactively.  After all, this function is called
QUERY-replace-regexp.


-- 
Kim F. Storm <storm@cua.dk> http://www.cua.dk

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

* Re: query-replace-interactive not documented
  2004-06-16 11:30                                 ` Kim F. Storm
@ 2004-06-16 12:15                                   ` David Kastrup
  2004-06-16 14:35                                     ` David Kastrup
  0 siblings, 1 reply; 101+ messages in thread
From: David Kastrup @ 2004-06-16 12:15 UTC (permalink / raw)
  Cc: Juri Linkov, schwab, emacs-devel

storm@cua.dk (Kim F. Storm) writes:

> David Kastrup <dak@gnu.org> writes:
> 
> > Juri Linkov <juri@jurta.org> writes:
> > 
> > I'd rather say that since we already have special symbols
> > \1 \2 \3 \#1 \#2 \#3, that the most natural choice would probably be
> > just \# for the match number.  Then we'd have
> > 
> > \\label{fn:\,\# } RET
> > 
> > And it would probably make sense to define \# as a string component
> > on its own, too, so that we can just write
> > \\label{fn:\#} RET
> > if we want to.
> > 
> 
> \, and \# both looks good to me.  
> 
> The extra space after the \, form should be optional, i.e. if there is
> a space, remove it, if not, it's not an error.

Quite so.  \# caters for the most frequent use of \' without matched
parens.  However, other possible uses are references to frequently
used constant expressions one does not want to type out, and things like
\,?x
to insert ASCII codes as numbers and so on, so I think that the
optional space is still worth the price to pay.

> I haven't studied the two proposed implementations in details,
> but if there is an issue re. security and non-interactive calls,
> it might make sense to simply not accept these formats if called
> non-interactively.  After all, this function is called
> QUERY-replace-regexp.

An advantage is that, like query-replace-regexp-eval, the command
history contains a nicely compiled expression that is quite more
appropriate for cut&paste purposes into Lisp programs (which usually
should not use things like perform-replace, anyway).

Just working on a newer version right now.

-- 
David Kastrup, Kriemhildstr. 15, 44793 Bochum

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

* Re: query-replace-interactive not documented
  2004-06-16 12:15                                   ` David Kastrup
@ 2004-06-16 14:35                                     ` David Kastrup
  2004-06-16 15:23                                       ` Juri Linkov
                                                         ` (2 more replies)
  0 siblings, 3 replies; 101+ messages in thread
From: David Kastrup @ 2004-06-16 14:35 UTC (permalink / raw)
  Cc: Juri Linkov, schwab, emacs-devel

[-- Attachment #1: Type: text/plain, Size: 876 bytes --]

David Kastrup <dak@gnu.org> writes:

> Just working on a newer version right now.

Ok, here is my current version (apart from documentation which needs
to get added to several places, of course).  I've stolen some
improvements from Juri in the course, but the pleasure's mutual.

I have not added the \? proposal yet as I feel it of dubious utility:
without a proper prompt string, it will probably feel unconvenient to
use in particular where several \? occur, and I don't see a good
syntax for prompt strings: mandating them to be LF-ended would
require C-q C-j even when you don't want them after all, and you can
easily do them with
\,(read-string "My prompt")
anyway.  Maybe a fixed space-terminated (not-escapable) prompt would
do, like
\? xxx
to get no particular prompt string and
\?veracity xxx
to get "veracity" as a prompt.

But I really don't like that too much.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: Type: text/x-patch, Size: 3544 bytes --]

--- replace.el	10 Jun 2004 09:36:09 +0200	1.172
+++ replace.el	16 Jun 2004 15:26:16 +0200	
@@ -165,16 +165,46 @@
   (interactive
    (let ((common
 	  (query-replace-read-args "Query replace regexp" t)))
-     (list (nth 0 common) (nth 1 common) (nth 2 common)
-	   ;; These are done separately here
-	   ;; so that command-history will record these expressions
-	   ;; rather than the values they had this time.
-	   (if (and transient-mark-mode mark-active)
-	       (region-beginning))
-	   (if (and transient-mark-mode mark-active)
-	       (region-end)))))
-
+     (list
+      (nth 0 common)
+      (if (string-match "\\(\\`\\|[^\\]\\)\\(\\\\\\\\\\)*\\\\[,#]"
+			(nth 1 common))
+	  (let ((to-string (nth 1 common)) pos to-expr char)
+	    (while (string-match
+		    "\\(\\`\\|[^\\]\\)\\(\\\\\\\\\\)*\\\\[,#]"
+		    to-string)
+	      (setq pos (match-end 0))
+	      (push (substring to-string 0 (- pos 2)) to-expr)
+	      (setq char (aref to-string (1- pos))
+		    to-string (substring to-string pos))
+	      (cond ((eq char ?\#)
+		     (push '(number-to-string replace-count) to-expr))
+		    ((eq char ?\,)
+		     (setq pos (read-from-string to-string))
+		     (push `(replace-quote ,(pop pos)) to-expr)
+		     (setq to-string
+			   (substring to-string
+				      (if (and (< pos (length to-string))
+					       (eq (aref to-string pos) ?\ ))
+					  (1+ pos)
+					pos))))))
+	    (setq to-expr (delete "" (nreverse (cons to-string to-expr))))
+	    (replace-match-string-symbols to-expr)
+	    (cons 'replace-eval-replacement 
+		  (if (> (length to-expr) 1)
+		      (cons 'concat to-expr)
+		    (car to-expr))))
+	(nth 1 common))
+      (nth 2 common)
+      ;; These are done separately here
+      ;; so that command-history will record these expressions
+      ;; rather than the values they had this time.
+      (if (and transient-mark-mode mark-active)
+	  (region-beginning))
+      (if (and transient-mark-mode mark-active)
+	  (region-end)))))
   (perform-replace regexp to-string t t delimited nil nil start end))
+
 (define-key esc-map [?\C-%] 'query-replace-regexp)
 
 (defun query-replace-regexp-eval (regexp to-expr &optional delimited start end)
@@ -1012,6 +1042,7 @@
 #N    (string-to-number (match-string N))
 &     (match-string 0)
 #&    (string-to-number (match-string 0))
+#     replace-count
 
 Note that these symbols must be preceeded by a backslash in order to
 type them."
@@ -1031,7 +1062,9 @@
          ((string= "&" name)
           (setcar n '(match-string 0)))
          ((string= "#&" name)
-          (setcar n '(string-to-number (match-string 0))))))))
+          (setcar n '(string-to-number (match-string 0))))
+	 ((string= "#" name)
+	  (setcar n 'replace-count))))))
     (setq n (cdr n))))
 
 (defun replace-eval-replacement (expression replace-count)
@@ -1040,6 +1073,21 @@
         replacement
       (prin1-to-string replacement t))))
 
+(defun replace-quote (replacement)
+  "Quote a replacement string.
+This just doubles all backslashes in REPLACEMENT and
+returns the resulting string.  If REPLACEMENT is not
+a string, it is first passed through `prin1-to-string'
+with the `noescape' argument set.
+
+`match-data' is preserved across the call."
+  (save-match-data
+    (replace-regexp-in-string "\\\\" "\\\\"
+			      (if (stringp replacement)
+				  replacement
+				(prin1-to-string replacement t))
+			      t t)))
+
 (defun replace-loop-through-replacements (data replace-count)
   ;; DATA is a vector contaning the following values:
   ;;   0 next-rotate-count

[-- Attachment #3: Type: text/plain, Size: 562 bytes --]


Since the change involved only the interactive usage, and apart from
\# as a symbol in replacement expressions only makes hitherto illegal
input legal, it should have no effect whatsoever on code stability.

I think that the functionality is user-accessible to a degree by now
that it would make sense mentioning it also in the Emacs manual, in
case people agree it is a worthwhile addition.

Personally, I think this functionality is the greatest thing since
sliced bread, but then I am obviously prejudiced.

-- 
David Kastrup, Kriemhildstr. 15, 44793 Bochum

[-- Attachment #4: Type: text/plain, Size: 142 bytes --]

_______________________________________________
Emacs-devel mailing list
Emacs-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/emacs-devel

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

* Re: query-replace-interactive not documented
  2004-06-16 14:35                                     ` David Kastrup
@ 2004-06-16 15:23                                       ` Juri Linkov
  2004-06-16 21:15                                         ` David Kastrup
  2004-06-16 15:27                                       ` Kim F. Storm
  2004-06-16 17:28                                       ` Juri Linkov
  2 siblings, 1 reply; 101+ messages in thread
From: Juri Linkov @ 2004-06-16 15:23 UTC (permalink / raw)
  Cc: schwab, emacs-devel, storm

David Kastrup <dak@gnu.org> writes:
> David Kastrup <dak@gnu.org> writes:
>> Just working on a newer version right now.
>
> Ok, here is my current version (apart from documentation which needs
> to get added to several places, of course).  I've stolen some
> improvements from Juri in the course, but the pleasure's mutual.

That's fine with me.  I like to cooperate and share code.

> I have not added the \? proposal yet as I feel it of dubious utility:
> without a proper prompt string, it will probably feel unconvenient to
> use in particular where several \? occur, and I don't see a good
> syntax for prompt strings: mandating them to be LF-ended would
> require C-q C-j even when you don't want them after all, and you can
> easily do them with
> \,(read-string "My prompt")
> anyway.  Maybe a fixed space-terminated (not-escapable) prompt would
> do, like
> \? xxx
> to get no particular prompt string and
> \?veracity xxx
> to get "veracity" as a prompt.
>
> But I really don't like that too much.

I think \? is really useful even without a proper prompt string.

Often there is a need to prompt only for one replacement string
in cases like:

   #define X 0x001
   #define Y 0x002
   #define Z 0x003

it would be easy to do it with a simple \?:

C-M-% ^ RET #define \? 0x\# RET

It is not important what question it asks.  It would work even for two
or three different \? in one replacement string.  In rare cases where
the user needs more \?, he can use \,(read-string "My prompt: ").

Or to let it to automatically enumerate prompt strings, i.e. to have
a counter in expression generating code in `query-replace-regexp'
that will convert several \? in the same string into prompts in a
fixed format with the prompt counter added to the prompt string:

(concat (read-string "Enter string 1: ") (read-string "Enter string 2: "))

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

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

* Re: query-replace-interactive not documented
  2004-06-16 14:35                                     ` David Kastrup
  2004-06-16 15:23                                       ` Juri Linkov
@ 2004-06-16 15:27                                       ` Kim F. Storm
  2004-06-16 17:28                                       ` Juri Linkov
  2 siblings, 0 replies; 101+ messages in thread
From: Kim F. Storm @ 2004-06-16 15:27 UTC (permalink / raw)
  Cc: Juri Linkov, schwab, emacs-devel

David Kastrup <dak@gnu.org> writes:

> David Kastrup <dak@gnu.org> writes:
> 
> > Just working on a newer version right now.
> 
> Ok, here is my current version (apart from documentation which needs
> to get added to several places, of course).  I've stolen some
> improvements from Juri in the course, but the pleasure's mutual.
> 
> I have not added the \? proposal yet as I feel it of dubious utility:
> without a proper prompt string, it will probably feel unconvenient to
> use in particular where several \? occur, and I don't see a good
> syntax for prompt strings: mandating them to be LF-ended would
> require C-q C-j even when you don't want them after all, and you can
> easily do them with
> \,(read-string "My prompt")

But just like \# is a shorthand for \,(+ repeat-count), 
then \? could be a shorthand for \,(read-string "String for \\?: ")

If users what something more advanced (I doubt it), they can use
read-string explicitly.

> anyway.  Maybe a fixed space-terminated (not-escapable) prompt would
> do, like
> \? xxx
> to get no particular prompt string and
> \?veracity xxx
> to get "veracity" as a prompt.
> 
> But I really don't like that too much.

Neither do I.

> I think that the functionality is user-accessible to a degree by now
> that it would make sense mentioning it also in the Emacs manual, in
> case people agree it is a worthwhile addition.

Yes.

> 
> Personally, I think this functionality is the greatest thing since
> sliced bread, but then I am obviously prejudiced.

Yes, it is really clever -- let's see if people will use it....


-- 
Kim F. Storm <storm@cua.dk> http://www.cua.dk

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

* Re: query-replace-interactive not documented
  2004-06-15 15:43                         ` David Kastrup
  2004-06-15 18:17                           ` Juri Linkov
  2004-06-16  1:41                           ` Miles Bader
@ 2004-06-16 16:57                           ` Richard Stallman
  2 siblings, 0 replies; 101+ messages in thread
From: Richard Stallman @ 2004-06-16 16:57 UTC (permalink / raw)
  Cc: juri, emacs-devel, storm

    If there are always to be parens around, then there would be no need for
    !.  One could just write

    \\footnote{\\label{fn:\(+ replace-count\)}

I prefer the \! syntax, since it does not mess up the parens.
! is used in many programs to mean "execute" (usually
with a shell command, but we can ignore that).

Using \' does not seem to make sense, since this is not quoting.

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

* Re: query-replace-interactive not documented
  2004-06-16  9:01                                 ` David Kastrup
@ 2004-06-16 17:06                                   ` Kevin Rodgers
  0 siblings, 0 replies; 101+ messages in thread
From: Kevin Rodgers @ 2004-06-16 17:06 UTC (permalink / raw)


David Kastrup wrote:
 > Perhaps the starting index of a string match should match on \= in
 > analogy to the "starting index" of a buffer match?

Yes, I asked for that years ago, so that \= could anchor the REGEXP to
avoid this idiom:

(equal (string-match REGEXP STRING START) START)

-- 
Kevin Rodgers

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

* Re: query-replace-interactive not documented
  2004-06-16 14:35                                     ` David Kastrup
  2004-06-16 15:23                                       ` Juri Linkov
  2004-06-16 15:27                                       ` Kim F. Storm
@ 2004-06-16 17:28                                       ` Juri Linkov
  2004-06-16 21:07                                         ` David Kastrup
  2 siblings, 1 reply; 101+ messages in thread
From: Juri Linkov @ 2004-06-16 17:28 UTC (permalink / raw)
  Cc: schwab, emacs-devel, storm

David Kastrup <dak@gnu.org> writes:
> I think that the functionality is user-accessible to a degree by now
> that it would make sense mentioning it also in the Emacs manual, in
> case people agree it is a worthwhile addition.

I tested the latest version.  All works fine except one thing:
removing the space after the \, expression is a really bad thing.
This is too unnatural and produces unexpected results.

The space definitely shouldn't be removed after the closing paren
(it doesn't need the space to enclose the expression).  And I think
it shouldn't be removed after variable names too.  In cases where
a variable name is not separated from the following text, users can
use additional separators like parentheses with a no-op function.

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

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

* Re: query-replace-interactive not documented
  2004-06-16 17:28                                       ` Juri Linkov
@ 2004-06-16 21:07                                         ` David Kastrup
  2004-06-17  0:47                                           ` David Kastrup
  2004-06-17 23:05                                           ` Richard Stallman
  0 siblings, 2 replies; 101+ messages in thread
From: David Kastrup @ 2004-06-16 21:07 UTC (permalink / raw)
  Cc: schwab, emacs-devel, storm

Juri Linkov <juri@jurta.org> writes:

> David Kastrup <dak@gnu.org> writes:
> > I think that the functionality is user-accessible to a degree by now
> > that it would make sense mentioning it also in the Emacs manual, in
> > case people agree it is a worthwhile addition.
> 
> I tested the latest version.  All works fine except one thing:
> removing the space after the \, expression is a really bad thing.
> This is too unnatural and produces unexpected results.
> 
> The space definitely shouldn't be removed after the closing paren
> (it doesn't need the space to enclose the expression).  And I think
> it shouldn't be removed after variable names too.  In cases where
> a variable name is not separated from the following text, users can
> use additional separators like parentheses with a no-op function.

xxx\(\) is a single word to the Lisp reader, unfortunately.  If you
can come up with a good no-op string to put into the DOC string, I'm
willing to let the space go.  But anything starting with a backslash
is out since it will become part of preceding identifiers.

And I feel that "\{0\} is decidedly too ugly an idiom for a DOC
string.  There must be something nicer, right?

-- 
David Kastrup, Kriemhildstr. 15, 44793 Bochum

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

* Re: query-replace-interactive not documented
  2004-06-16 15:23                                       ` Juri Linkov
@ 2004-06-16 21:15                                         ` David Kastrup
  2004-06-16 22:26                                           ` Kim F. Storm
  0 siblings, 1 reply; 101+ messages in thread
From: David Kastrup @ 2004-06-16 21:15 UTC (permalink / raw)
  Cc: schwab, storm, emacs-devel

Juri Linkov <juri@jurta.org> writes:

> It is not important what question it asks.  It would work even for
> two or three different \? in one replacement string.  In rare cases
> where the user needs more \?, he can use \,(read-string "My prompt:
> ").
> 
> Or to let it to automatically enumerate prompt strings, i.e. to have
> a counter in expression generating code in `query-replace-regexp'
> that will convert several \? in the same string into prompts in a
> fixed format with the prompt counter added to the prompt string:
> 
> (concat (read-string "Enter string 1: ") (read-string "Enter string
> 2: "))

Yes, I might do something like that.  What about the replacement
strings entered for \?, should they be passed through replace-quote
or not?  Where users enter the replacement themselves, maybe there is
some incentive to let it have the unquoted meaning, so that users may
also enter \1 \2 \3 in the replacement string?

-- 
David Kastrup, Kriemhildstr. 15, 44793 Bochum

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

* Re: query-replace-interactive not documented
  2004-06-16 21:15                                         ` David Kastrup
@ 2004-06-16 22:26                                           ` Kim F. Storm
  2004-06-17  0:56                                             ` David Kastrup
  0 siblings, 1 reply; 101+ messages in thread
From: Kim F. Storm @ 2004-06-16 22:26 UTC (permalink / raw)
  Cc: Juri Linkov, schwab, emacs-devel

David Kastrup <dak@gnu.org> writes:

> Juri Linkov <juri@jurta.org> writes:
> 
> > It is not important what question it asks.  It would work even for
> > two or three different \? in one replacement string.  In rare cases
> > where the user needs more \?, he can use \,(read-string "My prompt:
> > ").
> > 
> > Or to let it to automatically enumerate prompt strings, i.e. to have
> > a counter in expression generating code in `query-replace-regexp'
> > that will convert several \? in the same string into prompts in a
> > fixed format with the prompt counter added to the prompt string:
> > 
> > (concat (read-string "Enter string 1: ") (read-string "Enter string
> > 2: "))
> 
> Yes, I might do something like that.  

Maybe "Enter string: " for the first one, "Enter string 2:" etc for the
following strings.

>                                       What about the replacement
> strings entered for \?, should they be passed through replace-quote
> or not?  Where users enter the replacement themselves, maybe there is
> some incentive to let it have the unquoted meaning, so that users may
> also enter \1 \2 \3 in the replacement string?

This is mostly a non-issue in practice, but I think that whatever
the user enters should be inserted literally.

-- 
Kim F. Storm <storm@cua.dk> http://www.cua.dk

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

* Re: query-replace-interactive not documented
  2004-06-16 21:07                                         ` David Kastrup
@ 2004-06-17  0:47                                           ` David Kastrup
  2004-06-17 23:05                                           ` Richard Stallman
  1 sibling, 0 replies; 101+ messages in thread
From: David Kastrup @ 2004-06-17  0:47 UTC (permalink / raw)
  Cc: schwab, storm, emacs-devel

David Kastrup <dak@gnu.org> writes:

> Juri Linkov <juri@jurta.org> writes:
> 
> > I tested the latest version.  All works fine except one thing:
> > removing the space after the \, expression is a really bad thing.
> > This is too unnatural and produces unexpected results.
> > 
> > The space definitely shouldn't be removed after the closing paren
> > (it doesn't need the space to enclose the expression).  And I
> > think it shouldn't be removed after variable names too.  In cases
> > where a variable name is not separated from the following text,
> > users can use additional separators like parentheses with a no-op
> > function.
> 
> xxx\(\) is a single word to the Lisp reader, unfortunately.  If you
> can come up with a good no-op string to put into the DOC string, I'm
> willing to let the space go.  But anything starting with a backslash
> is out since it will become part of preceding identifiers.
> 
> And I feel that "\{0\} is decidedly too ugly an idiom for a DOC
> string.  There must be something nicer, right?

And "\{0\} does not work anyway, since we are talking about the
replacement string, not the matching string.  Brain was off.

In the replacement string, there is _absolutely_ nothing that could
end an identifier without impact.  So there is no way around the
reader except using \,(or identifier), at least as far as I can see.

Which is probably what you meant, anyway.

-- 
David Kastrup, Kriemhildstr. 15, 44793 Bochum

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

* Re: query-replace-interactive not documented
  2004-06-16 22:26                                           ` Kim F. Storm
@ 2004-06-17  0:56                                             ` David Kastrup
  2004-06-17 12:14                                               ` David Kastrup
  0 siblings, 1 reply; 101+ messages in thread
From: David Kastrup @ 2004-06-17  0:56 UTC (permalink / raw)
  Cc: Juri Linkov, schwab, emacs-devel

[-- Attachment #1: Type: text/plain, Size: 1329 bytes --]

storm@cua.dk (Kim F. Storm) writes:

> David Kastrup <dak@gnu.org> writes:
> 
> > Juri Linkov <juri@jurta.org> writes:
> > 
> > > It is not important what question it asks.  It would work even for
> > > two or three different \? in one replacement string.  In rare cases
> > > where the user needs more \?, he can use \,(read-string "My prompt:
> > > ").
> > > 
> > > Or to let it to automatically enumerate prompt strings, i.e. to have
> > > a counter in expression generating code in `query-replace-regexp'
> > > that will convert several \? in the same string into prompts in a
> > > fixed format with the prompt counter added to the prompt string:
> > > 
> > > (concat (read-string "Enter string 1: ") (read-string "Enter string
> > > 2: "))
> > 
> > Yes, I might do something like that.  
> 
> Maybe "Enter string: " for the first one, "Enter string 2:" etc for the
> following strings.

Ouch, I just realized that the dialog will basically be:

Enter string: xsxa RET
Query replace gfag with fdsfxsxa* (y/n)?

That's so weird that I don't really know if it should be a "feature"
with its own shortcut.  Entering the strings when they might not even
get used...

I'll just post the current untested diff (which might or might not
work) since I'm about to fall asleep.  In case it works, people have
something to play with.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: Type: text/x-patch, Size: 5171 bytes --]

--- replace.el	10 Jun 2004 09:36:09 +0200	1.172
+++ replace.el	17 Jun 2004 02:16:46 +0200	
@@ -81,14 +81,15 @@
 					 query-replace-from-history-variable
 					 nil t)))
       ;; Warn if user types \n or \t, but don't reject the input.
-      (if (string-match "\\\\[nt]" from)
-	  (let ((match (match-string 0 from)))
-	    (cond
-	     ((string= match "\\n")
-	      (message "Note: `\\n' here doesn't match a newline; to do that, type C-q C-j instead"))
-	     ((string= match "\\t")
-	      (message "Note: `\\t' here doesn't match a tab; to do that, just type TAB")))
-	    (sit-for 2))))
+      (and regexp-flag
+	   (string-match "\\(\\`\\|[^\\]\\)\\(\\\\\\\\\)*\\(\\\\[nt]\\)" from)
+	   (let ((match (match-string 3 from)))
+	     (cond
+	      ((string= match "\\n")
+	       (message "Note: `\\n' here doesn't match a newline; to do that, type C-q C-j instead"))
+	      ((string= match "\\t")
+	       (message "Note: `\\t' here doesn't match a tab; to do that, just type TAB")))
+	     (sit-for 2))))
 
     (save-excursion
       (setq to (read-from-minibuffer (format "%s %s with: " string from)
@@ -165,18 +166,65 @@
   (interactive
    (let ((common
 	  (query-replace-read-args "Query replace regexp" t)))
-     (list (nth 0 common) (nth 1 common) (nth 2 common)
-	   ;; These are done separately here
-	   ;; so that command-history will record these expressions
-	   ;; rather than the values they had this time.
-	   (if (and transient-mark-mode mark-active)
-	       (region-beginning))
-	   (if (and transient-mark-mode mark-active)
-	       (region-end)))))
-
+     (list
+      (nth 0 common)
+      (if (string-match "\\(\\`\\|[^\\]\\)\\(\\\\\\\\\\)*\\\\[,#?]"
+			(nth 1 common))
+	  (let ((to-string (nth 1 common)) pos to-expr char prompt)
+	    (while (string-match
+		    "\\(\\`\\|[^\\]\\)\\(\\\\\\\\\\)*\\\\[,#?]"
+		    to-string)
+	      (setq pos (match-end 0))
+	      (push (substring to-string 0 (- pos 2)) to-expr)
+	      (setq char (aref to-string (1- pos))
+		    to-string (substring to-string pos))
+	      (cond ((eq char ?\#)
+		     (push '(number-to-string replace-count) to-expr))
+		    ((eq char ?\,)
+		     (setq pos (read-from-string to-string))
+		     (push `(replace-quote ,(pop pos)) to-expr)
+		     (setq to-string
+			   (substring to-string
+				      (if (and (< pos (length to-string))
+					       (eq (aref to-string pos) ?\ ))
+					  (1+ pos)
+					pos))))
+		    ((eq char ?\?)
+		     (push `(replace-quote
+			     (replace-read-replacement
+			      ,(if prompt
+				   (progn
+				     (setq prompt (1+ prompt))
+				     (format "Replacement %d: " prompt))
+				 (setq prompt 1)
+				 "Replacement: ")))
+			   to-expr))))
+	    (setq to-expr (delete "" (nreverse (cons to-string to-expr))))
+	    (replace-match-string-symbols to-expr)
+	    (cons 'replace-eval-replacement 
+		  (if (> (length to-expr) 1)
+		      (cons 'concat to-expr)
+		    (car to-expr))))
+	(nth 1 common))
+      (nth 2 common)
+      ;; These are done separately here
+      ;; so that command-history will record these expressions
+      ;; rather than the values they had this time.
+      (if (and transient-mark-mode mark-active)
+	  (region-beginning))
+      (if (and transient-mark-mode mark-active)
+	  (region-end)))))
   (perform-replace regexp to-string t t delimited nil nil start end))
+
 (define-key esc-map [?\C-%] 'query-replace-regexp)
 
+(defun replace-read-replacement (prompt)
+  "Read a replacement string with PROMPT."
+  (read-from-minibuffer
+   prompt
+   nil nil t query-replace-to-history-variable
+   nil t))
+
 (defun query-replace-regexp-eval (regexp to-expr &optional delimited start end)
   "Replace some things after point matching REGEXP with the result of TO-EXPR.
 As each match is found, the user must type a character saying
@@ -1012,6 +1060,7 @@
 #N    (string-to-number (match-string N))
 &     (match-string 0)
 #&    (string-to-number (match-string 0))
+#     replace-count
 
 Note that these symbols must be preceeded by a backslash in order to
 type them."
@@ -1031,7 +1080,9 @@
          ((string= "&" name)
           (setcar n '(match-string 0)))
          ((string= "#&" name)
-          (setcar n '(string-to-number (match-string 0))))))))
+          (setcar n '(string-to-number (match-string 0))))
+	 ((string= "#" name)
+	  (setcar n 'replace-count))))))
     (setq n (cdr n))))
 
 (defun replace-eval-replacement (expression replace-count)
@@ -1040,6 +1091,21 @@
         replacement
       (prin1-to-string replacement t))))
 
+(defun replace-quote (replacement)
+  "Quote a replacement string.
+This just doubles all backslashes in REPLACEMENT and
+returns the resulting string.  If REPLACEMENT is not
+a string, it is first passed through `prin1-to-string'
+with the `noescape' argument set.
+
+`match-data' is preserved across the call."
+  (save-match-data
+    (replace-regexp-in-string "\\\\" "\\\\"
+			      (if (stringp replacement)
+				  replacement
+				(prin1-to-string replacement t))
+			      t t)))
+
 (defun replace-loop-through-replacements (data replace-count)
   ;; DATA is a vector contaning the following values:
   ;;   0 next-rotate-count

[-- Attachment #3: Type: text/plain, Size: 52 bytes --]



-- 
David Kastrup, Kriemhildstr. 15, 44793 Bochum

[-- Attachment #4: Type: text/plain, Size: 142 bytes --]

_______________________________________________
Emacs-devel mailing list
Emacs-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/emacs-devel

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

* Re: query-replace-interactive not documented
  2004-06-15 22:43                                 ` Kim F. Storm
  2004-06-15 23:13                                   ` David Kastrup
  2004-06-16  8:02                                   ` Juri Linkov
@ 2004-06-17  5:06                                   ` Richard Stallman
  2 siblings, 0 replies; 101+ messages in thread
From: Richard Stallman @ 2004-06-17  5:06 UTC (permalink / raw)
  Cc: juri, schwab, dak, emacs-devel

    Maybe \=(...) is better ?

I think that is as good as \!.

\, would also be appropriate, since this is substitution
of the result of evaluation, like , inside `.

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

* Re: query-replace-interactive not documented
  2004-06-16  9:32                               ` David Kastrup
  2004-06-16 11:30                                 ` Kim F. Storm
@ 2004-06-17  5:07                                 ` Richard Stallman
  1 sibling, 0 replies; 101+ messages in thread
From: Richard Stallman @ 2004-06-17  5:07 UTC (permalink / raw)
  Cc: juri, schwab, storm, emacs-devel

    I'd rather say that since we already have special symbols
    \1 \2 \3 \#1 \#2 \#3, that the most natural choice would probably be
    just \# for the match number.  Then we'd have

    \\label{fn:\,\# } RET

I am not sure \# makes sense to use inside \,.  It would also be
hard to implement.

    And it would probably make sense to define \# as a string component
    on its own, too, so that we can just write
    \\label{fn:\#} RET
    if we want to.

That is clean and natural, so I think it is a good feature.  However,
people will sometimes want to use the value in more complex
computations, rather than just substituting it.

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

* Re: query-replace-interactive not documented
  2004-06-17  0:56                                             ` David Kastrup
@ 2004-06-17 12:14                                               ` David Kastrup
  2004-06-17 13:05                                                 ` Kim F. Storm
  2004-06-17 14:56                                                 ` David Kastrup
  0 siblings, 2 replies; 101+ messages in thread
From: David Kastrup @ 2004-06-17 12:14 UTC (permalink / raw)
  Cc: Juri Linkov, schwab, emacs-devel

[-- Attachment #1: Type: text/plain, Size: 2295 bytes --]

David Kastrup <dak@gnu.org> writes:

> storm@cua.dk (Kim F. Storm) writes:
> 
> > David Kastrup <dak@gnu.org> writes:
> > 
> > > Juri Linkov <juri@jurta.org> writes:
> > > 
> > > > It is not important what question it asks.  It would work even for
> > > > two or three different \? in one replacement string.  In rare cases
> > > > where the user needs more \?, he can use \,(read-string "My prompt:
> > > > ").
> > > > 
> > > > (concat (read-string "Enter string 1: ") (read-string "Enter string
> > > > 2: "))
> > > 
> > > Yes, I might do something like that.  
> > 
> > Maybe "Enter string: " for the first one, "Enter string 2:" etc for the
> > following strings.
> 
> Ouch, I just realized that the dialog will basically be:
> 
> Enter string: xsxa RET
> Query replace gfag with fdsfxsxa* (y/n)?
> 
> That's so weird that I don't really know if it should be a "feature"
> with its own shortcut.  Entering the strings when they might not even
> get used...

And without any visual indication what is happening right now.

> I'll just post the current untested diff (which might or might not
> work) since I'm about to fall asleep.  In case it works, people have
> something to play with.

Ok, I just redid this.  I have completely thrown out \\? again: if one
wanted to implement it, the right place would not be in preparing the
replacement list where \, is implemented, but rather during
perform-replace.

And then it should be done _after_ the question
"replace woozle with heffalump\? (y/n)?" has been answered positively,
by using a while loop that removes the first proper \? in the string
(using the "\\(\\`\\|[^\\]\\)\\(\\\\\\\\\\)*\\\\\\?" pattern)
and calls the replacement string editor with the cursor at the specified
location, until there is no longer an unescaped \?.  After that, the
replacement can be performed.

This will give the context (so we don't need prompt strings), it will
be flexible and convenient.  Any volunteer to put this is?

Anyway, I fixed what I posted last night, removed the skip of the
optional space (the most prominent use would have been
\,replace-count, and there is a shorthand for that by now) and added
documentation strings.  If nobody protests, I'll check in the
following patch.  It also removes \n \t warnings where they are
nonsensical.


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: Type: text/x-patch, Size: 5985 bytes --]

--- replace.el	10 Jun 2004 09:36:09 +0200	1.172
+++ replace.el	17 Jun 2004 13:58:02 +0200	
@@ -81,14 +81,15 @@
 					 query-replace-from-history-variable
 					 nil t)))
       ;; Warn if user types \n or \t, but don't reject the input.
-      (if (string-match "\\\\[nt]" from)
-	  (let ((match (match-string 0 from)))
-	    (cond
-	     ((string= match "\\n")
-	      (message "Note: `\\n' here doesn't match a newline; to do that, type C-q C-j instead"))
-	     ((string= match "\\t")
-	      (message "Note: `\\t' here doesn't match a tab; to do that, just type TAB")))
-	    (sit-for 2))))
+      (and regexp-flag
+	   (string-match "\\(\\`\\|[^\\]\\)\\(\\\\\\\\\\)*\\(\\\\[nt]\\)" from)
+	   (let ((match (match-string 3 from)))
+	     (cond
+	      ((string= match "\\n")
+	       (message "Note: `\\n' here doesn't match a newline; to do that, type C-q C-j instead"))
+	      ((string= match "\\t")
+	       (message "Note: `\\t' here doesn't match a tab; to do that, just type TAB")))
+	     (sit-for 2))))
 
     (save-excursion
       (setq to (read-from-minibuffer (format "%s %s with: " string from)
@@ -161,20 +162,62 @@
 
 In TO-STRING, `\\&' stands for whatever matched the whole of REGEXP,
 and `\\=\\N' (where N is a digit) stands for
- whatever what matched the Nth `\\(...\\)' in REGEXP."
+whatever what matched the Nth `\\(...\\)' in REGEXP.
+
+When this function is called interactively, the replacement text
+can also contain `\\,' followed by a Lisp expression.  The escaped
+shorthands for `query-replace-regexp-eval' are also valid
+here: within the Lisp expression, you can use `\\&' for the whole
+match string, `\\N' for partial matches, `\\#&' and `\\#N' for
+the respective numeric values, and `\\#' for `replace-count'.
+
+If your Lisp expression is an identifier and the next
+letter in the replacement string would be interpreted as part of it,
+you can wrap it with an expression like `\\,(or \\#)'.  Incidentally,
+for this particular case you may also enter `\\#' in the replacement
+text directly.
+
+When you use `\\,' or `\\#' in the replacement, TO-STRING actually
+becomes a list with expanded shorthands.
+Use \\[repeat-complex-command] after this command to see details."
   (interactive
    (let ((common
 	  (query-replace-read-args "Query replace regexp" t)))
-     (list (nth 0 common) (nth 1 common) (nth 2 common)
-	   ;; These are done separately here
-	   ;; so that command-history will record these expressions
-	   ;; rather than the values they had this time.
-	   (if (and transient-mark-mode mark-active)
-	       (region-beginning))
-	   (if (and transient-mark-mode mark-active)
-	       (region-end)))))
-
+     (list
+      (nth 0 common)
+      (if (string-match "\\(\\`\\|[^\\]\\)\\(\\\\\\\\\\)*\\\\[,#]"
+			(nth 1 common))
+	  (let ((to-string (nth 1 common)) pos to-expr char prompt)
+	    (while (string-match
+		    "\\(\\`\\|[^\\]\\)\\(\\\\\\\\\\)*\\\\[,#]"
+		    to-string)
+	      (setq pos (match-end 0))
+	      (push (substring to-string 0 (- pos 2)) to-expr)
+	      (setq char (aref to-string (1- pos))
+		    to-string (substring to-string pos))
+	      (cond ((eq char ?\#)
+		     (push '(number-to-string replace-count) to-expr))
+		    ((eq char ?\,)
+		     (setq pos (read-from-string to-string))
+		     (push `(replace-quote ,(car pos)) to-expr)
+		     (setq to-string (substring to-string (cdr pos))))))
+	    (setq to-expr (nreverse (delete "" (cons to-string to-expr))))
+	    (replace-match-string-symbols to-expr)
+	    (cons 'replace-eval-replacement 
+		  (if (> (length to-expr) 1)
+		      (cons 'concat to-expr)
+		    (car to-expr))))
+	(nth 1 common))
+      (nth 2 common)
+      ;; These are done separately here
+      ;; so that command-history will record these expressions
+      ;; rather than the values they had this time.
+      (if (and transient-mark-mode mark-active)
+	  (region-beginning))
+      (if (and transient-mark-mode mark-active)
+	  (region-end)))))
   (perform-replace regexp to-string t t delimited nil nil start end))
+
 (define-key esc-map [?\C-%] 'query-replace-regexp)
 
 (defun query-replace-regexp-eval (regexp to-expr &optional delimited start end)
@@ -191,6 +234,7 @@
 `\\0' to stand for whatever matched the whole of REGEXP, and `\\N' (where
 N is a digit) to stand for whatever matched the Nth `\\(...\\)' in REGEXP.
 Use `\\#&' or `\\#N' if you want a number instead of a string.
+In interactive use, `\\#' in itself stands for `replace-count'.
 
 In Transient Mark mode, if the mark is active, operate on the contents
 of the region.  Otherwise, operate from point to the end of the buffer.
@@ -1012,6 +1056,7 @@
 #N    (string-to-number (match-string N))
 &     (match-string 0)
 #&    (string-to-number (match-string 0))
+#     replace-count
 
 Note that these symbols must be preceeded by a backslash in order to
 type them."
@@ -1031,7 +1076,9 @@
          ((string= "&" name)
           (setcar n '(match-string 0)))
          ((string= "#&" name)
-          (setcar n '(string-to-number (match-string 0))))))))
+          (setcar n '(string-to-number (match-string 0))))
+	 ((string= "#" name)
+	  (setcar n 'replace-count))))))
     (setq n (cdr n))))
 
 (defun replace-eval-replacement (expression replace-count)
@@ -1040,6 +1087,21 @@
         replacement
       (prin1-to-string replacement t))))
 
+(defun replace-quote (replacement)
+  "Quote a replacement string.
+This just doubles all backslashes in REPLACEMENT and
+returns the resulting string.  If REPLACEMENT is not
+a string, it is first passed through `prin1-to-string'
+with the `noescape' argument set.
+
+`match-data' is preserved across the call."
+  (save-match-data
+    (replace-regexp-in-string "\\\\" "\\\\"
+			      (if (stringp replacement)
+				  replacement
+				(prin1-to-string replacement t))
+			      t t)))
+
 (defun replace-loop-through-replacements (data replace-count)
   ;; DATA is a vector contaning the following values:
   ;;   0 next-rotate-count

[-- Attachment #3: Type: text/plain, Size: 51 bytes --]


-- 
David Kastrup, Kriemhildstr. 15, 44793 Bochum

[-- Attachment #4: Type: text/plain, Size: 142 bytes --]

_______________________________________________
Emacs-devel mailing list
Emacs-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/emacs-devel

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

* Re: query-replace-interactive not documented
  2004-06-17 12:14                                               ` David Kastrup
@ 2004-06-17 13:05                                                 ` Kim F. Storm
  2004-06-17 13:29                                                   ` David Kastrup
  2004-06-17 14:56                                                 ` David Kastrup
  1 sibling, 1 reply; 101+ messages in thread
From: Kim F. Storm @ 2004-06-17 13:05 UTC (permalink / raw)
  Cc: Juri Linkov, schwab, emacs-devel

David Kastrup <dak@gnu.org> writes:

> 
> Ok, I just redid this.  I have completely thrown out \\? again: if one
> wanted to implement it, the right place would not be in preparing the
> replacement list where \, is implemented, but rather during
> perform-replace.

Here's a wild idea:

If replace string contains \?, allow user to edit the replacement
string in the minibuffer [after confirming this replace] -- 

In the buffer, \? is removed, and but cursor is positioned at its position
in the string.

If string contains multiple \?, one option is just to ignore further
occurrences, another it to let TAB cycle between them in the minibuffer.

-- 
Kim F. Storm <storm@cua.dk> http://www.cua.dk

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

* Re: query-replace-interactive not documented
  2004-06-17 13:05                                                 ` Kim F. Storm
@ 2004-06-17 13:29                                                   ` David Kastrup
  2004-06-17 14:10                                                     ` Kim F. Storm
  0 siblings, 1 reply; 101+ messages in thread
From: David Kastrup @ 2004-06-17 13:29 UTC (permalink / raw)
  Cc: Juri Linkov, schwab, emacs-devel

storm@cua.dk (Kim F. Storm) writes:

> David Kastrup <dak@gnu.org> writes:
> 
> > 
> > Ok, I just redid this.  I have completely thrown out \\? again: if one
> > wanted to implement it, the right place would not be in preparing the
> > replacement list where \, is implemented, but rather during
> > perform-replace.
> 
> Here's a wild idea:

If you had bothered to read my mail to the end...

> If replace string contains \?, allow user to edit the replacement
> string in the minibuffer [after confirming this replace] -- 
> 
> In the buffer, \? is removed, and but cursor is positioned at its position
> in the string.
> 
> If string contains multiple \?, one option is just to ignore further
> occurrences, another it to let TAB cycle between them in the
> minibuffer.

What is wrong about my proposal to just keep further occurences of \?
in the string and repeat prompting for the remaining first one until
none of them remains?  You can either edit out everything at once, if
you so desire, or just enter stuff at the current location, press
return, and get the next \? trigger operated on.

-- 
David Kastrup, Kriemhildstr. 15, 44793 Bochum

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

* Re: query-replace-interactive not documented
  2004-06-17 13:29                                                   ` David Kastrup
@ 2004-06-17 14:10                                                     ` Kim F. Storm
  0 siblings, 0 replies; 101+ messages in thread
From: Kim F. Storm @ 2004-06-17 14:10 UTC (permalink / raw)
  Cc: Juri Linkov, schwab, emacs-devel

David Kastrup <dak@gnu.org> writes:

> storm@cua.dk (Kim F. Storm) writes:
> 
> > David Kastrup <dak@gnu.org> writes:
> > 
> > > 
> > > Ok, I just redid this.  I have completely thrown out \\? again: if one
> > > wanted to implement it, the right place would not be in preparing the
> > > replacement list where \, is implemented, but rather during
> > > perform-replace.
> > 
> > Here's a wild idea:
> 
> If you had bothered to read my mail to the end...

Sorry, I stopped reading at "\\(\\`\\|[^\\]\\)\\(\\\\\\\\\\)*\\\\\\?"  
in the fourth line of the relevant paragraph:

,------
| And then it should be done _after_ the question
| "replace woozle with heffalump\? (y/n)?" has been answered positively,
| by using a while loop that removes the first proper \? in the string
| (using the "\\(\\`\\|[^\\]\\)\\(\\\\\\\\\\)*\\\\\\?" pattern)
| and calls the replacement string editor with the cursor at the specified
| location, until there is no longer an unescaped \?.  After that, the
| replacement can be performed.
`------


> What is wrong about my proposal to just keep further occurences of \?
> in the string and repeat prompting for the remaining first one until
> none of them remains?  You can either edit out everything at once, if
> you so desire, or just enter stuff at the current location, press
> return, and get the next \? trigger operated on.

Nothing wrong -- Your idea is excellent.

-- 
Kim F. Storm <storm@cua.dk> http://www.cua.dk

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

* Re: query-replace-interactive not documented
  2004-06-17 12:14                                               ` David Kastrup
  2004-06-17 13:05                                                 ` Kim F. Storm
@ 2004-06-17 14:56                                                 ` David Kastrup
  2004-06-17 15:33                                                   ` Juri Linkov
  1 sibling, 1 reply; 101+ messages in thread
From: David Kastrup @ 2004-06-17 14:56 UTC (permalink / raw)
  Cc: Juri Linkov, schwab, emacs-devel

David Kastrup <dak@gnu.org> writes:

> Ok, I just redid this.  I have completely thrown out \\? again: if
> one wanted to implement it, the right place would not be in
> preparing the replacement list where \, is implemented, but rather
> during perform-replace.
> 
> This will give the context (so we don't need prompt strings), it
> will be flexible and convenient.  Any volunteer to put this is?

I'll take another look, maybe it's not difficult.

> Anyway, I fixed what I posted last night, removed the skip of the
> optional space (the most prominent use would have been
> \,replace-count, and there is a shorthand for that by now) and added
> documentation strings.  If nobody protests, I'll check in the
> following patch.  It also removes \n \t warnings where they are
> nonsensical.

I have checked in that change now.  While I have not given much of a
time for protests, I want to have a starting point for thinking about
\?.

I have not done any manual and NEWS entries yet but would want to have
a few more days for people to protest.  In my book, this added
functionality pretty much kills the main motivation for
query-replace-regexp-eval, except maybe that the latter could offer
lisp-mode in the replacement string, to give identifier completion and
stuff (which I don't think it does currently).  But I don't think that
it warrants a keybinding of its own anymore, now that \, is in place.

-- 
David Kastrup, Kriemhildstr. 15, 44793 Bochum

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

* Re: query-replace-interactive not documented
  2004-06-17 14:56                                                 ` David Kastrup
@ 2004-06-17 15:33                                                   ` Juri Linkov
  2004-06-17 17:03                                                     ` David Kastrup
  0 siblings, 1 reply; 101+ messages in thread
From: Juri Linkov @ 2004-06-17 15:33 UTC (permalink / raw)
  Cc: emacs-devel

David Kastrup <dak@gnu.org> writes:
> David Kastrup <dak@gnu.org> writes:
>
>> Ok, I just redid this.  I have completely thrown out \\? again: if
>> one wanted to implement it, the right place would not be in
>> preparing the replacement list where \, is implemented, but rather
>> during perform-replace.
>> 
>> This will give the context (so we don't need prompt strings), it
>> will be flexible and convenient.  Any volunteer to put this is?
>
> I'll take another look, maybe it's not difficult.
>
> I have checked in that change now.  While I have not given much of a
> time for protests, I want to have a starting point for thinking about
> \?.

I think your idea about using the replacement string editor for \? is
very good.  I hope you will not encounter any obstacles in implementing it.

> I have not done any manual and NEWS entries yet but would want to have
> a few more days for people to protest.  In my book, this added
> functionality pretty much kills the main motivation for
> query-replace-regexp-eval, except maybe that the latter could offer
> lisp-mode in the replacement string, to give identifier completion and
> stuff (which I don't think it does currently).  But I don't think that
> it warrants a keybinding of its own anymore, now that \, is in place.

Yes, we can completely forget about `query-replace-regexp-eval' from now.

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

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

* Re: query-replace-interactive not documented
  2004-06-17 15:33                                                   ` Juri Linkov
@ 2004-06-17 17:03                                                     ` David Kastrup
  2004-06-18  6:43                                                       ` Juri Linkov
  0 siblings, 1 reply; 101+ messages in thread
From: David Kastrup @ 2004-06-17 17:03 UTC (permalink / raw)
  Cc: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 737 bytes --]

Juri Linkov <juri@jurta.org> writes:

> David Kastrup <dak@gnu.org> writes:
>
> > I have checked in that change now.  While I have not given much of a
> > time for protests, I want to have a starting point for thinking about
> > \?.
> 
> I think your idea about using the replacement string editor for \?
> is very good.  I hope you will not encounter any obstacles in
> implementing it.

Here is a sketch.  I am calling it a sketch since the string-match for
\? should not be done for every replacement again if the replacement
string did not contain \? in the first place.  This is a performance
hog otherwise when doing lots of replacements automatically.

If people like it, maybe somebody will volunteer to make it more
efficient?


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: Type: text/x-patch, Size: 3040 bytes --]

--- replace.el	17 Jun 2004 16:36:17 +0200	1.173
+++ replace.el	17 Jun 2004 18:55:27 +0200	
@@ -1115,6 +1115,24 @@
           (aset data 2 (if (consp next) next (aref data 3))))))
   (car (aref data 2)))
 
+(defun replace-match-maybe-edit (newtext fixedcase literal &optional match-data)
+  "Make a replacement with `replace-match', editing `\\?'.
+NEXTEXT, FIXEDCASE, LITERAL are just passed on.  If MATCH-DATA is handed
+in, it is used for the replacement, otherwise the current MATCH-DATA is
+used (and saved during editing)."
+  (unless literal
+    (unless match-data
+      (setq match-data (match-data)))
+    (while (string-match "\\(\\`\\|[^\\]\\)\\(\\\\\\\\\\)*\\(\\\\\\?\\)"
+			 newtext)
+      (setq newtext
+	    (read-input "Edit replacement string: "
+			(cons
+			 (replace-match "" t t newtext 3)
+			 (1+ (match-beginning 3)))))))
+  (if match-data (set-match-data match-data))
+  (replace-match newtext fixedcase literal))
+
 (defun perform-replace (from-string replacements
 		        query-flag regexp-flag delimited-flag
 			&optional repeat-count map start end)
@@ -1252,8 +1270,8 @@
 			     replace-count)))
 	    (if (not query-flag)
 		(let ((inhibit-read-only query-replace-skip-read-only))
-		  (set-match-data real-match-data)
-		  (replace-match next-replacement nocasify literal)
+		  (replace-match-maybe-edit next-replacement nocasify literal
+					    real-match-data)
 		  (setq replace-count (1+ replace-count)))
 	      (undo-boundary)
 	      (let (done replaced key def)
@@ -1300,26 +1318,30 @@
 			((eq def 'act)
 			 (or replaced
 			     (progn
-			       (replace-match next-replacement nocasify literal)
+			       (replace-match-maybe-edit
+				next-replacement nocasify literal)
 			       (setq replace-count (1+ replace-count))))
 			 (setq done t replaced t))
 			((eq def 'act-and-exit)
 			 (or replaced
 			     (progn
-			       (replace-match next-replacement nocasify literal)
+			       (replace-match-maybe-edit 
+				next-replacement nocasify literal)
 			       (setq replace-count (1+ replace-count))))
 			 (setq keep-going nil)
 			 (setq done t replaced t))
 			((eq def 'act-and-show)
 			 (if (not replaced)
 			     (progn
-			       (replace-match next-replacement nocasify literal)
+			       (replace-match-maybe-edit
+				next-replacement nocasify literal)
 			       (setq replace-count (1+ replace-count))
 			       (setq replaced t))))
 			((eq def 'automatic)
 			 (or replaced
 			     (progn
-			       (replace-match next-replacement nocasify literal)
+			       (replace-match-maybe-edit
+				next-replacement nocasify literal)
 			       (setq replace-count (1+ replace-count))))
 			 (setq done t query-flag nil replaced t))
 			((eq def 'skip)
@@ -1350,7 +1372,8 @@
 			       (read-input "Edit replacement string: "
 					   next-replacement))
 			 (or replaced
-			     (replace-match next-replacement nocasify literal))
+			     (replace-match-maybe-edit
+			      next-replacement nocasify literal))
 			 (setq done t))
 
 			((eq def 'delete-and-edit)

[-- Attachment #3: Type: text/plain, Size: 51 bytes --]


-- 
David Kastrup, Kriemhildstr. 15, 44793 Bochum

[-- Attachment #4: Type: text/plain, Size: 142 bytes --]

_______________________________________________
Emacs-devel mailing list
Emacs-devel@gnu.org
http://lists.gnu.org/mailman/listinfo/emacs-devel

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

* Re: query-replace-interactive not documented
  2004-06-16 21:07                                         ` David Kastrup
  2004-06-17  0:47                                           ` David Kastrup
@ 2004-06-17 23:05                                           ` Richard Stallman
  2004-06-18  6:55                                             ` Juri Linkov
  1 sibling, 1 reply; 101+ messages in thread
From: Richard Stallman @ 2004-06-17 23:05 UTC (permalink / raw)
  Cc: juri, schwab, storm, emacs-devel

Using a space to end a variable name after `\,' is a clean solution.

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

* Re: query-replace-interactive not documented
  2004-06-17 17:03                                                     ` David Kastrup
@ 2004-06-18  6:43                                                       ` Juri Linkov
  2004-06-18  7:13                                                         ` David Kastrup
  0 siblings, 1 reply; 101+ messages in thread
From: Juri Linkov @ 2004-06-18  6:43 UTC (permalink / raw)
  Cc: emacs-devel

David Kastrup <dak@gnu.org> writes:
> Here is a sketch.  I am calling it a sketch since the string-match for
> \? should not be done for every replacement again if the replacement
> string did not contain \? in the first place.  This is a performance
> hog otherwise when doing lots of replacements automatically.

You can match it once in the beginning of the main while-loop and
store the result into a variable which would be given as an argument
of `replace-match-maybe-edit'.  There are only two places where the
next-replacement string is changed inside the loop.  One place is
where the replacement expression is evaluated.  But since evaluation
results are always quoted now, and unquoted \? can't be returned from
evaluation, so no need to re-check for \? here.  And another place is
where the user types `e' to edit the replacement string.  Since the
user can add \? to the replacement string (not in `replace-match-maybe-edit'
but in `perform-replace' in the case with (eq def 'edit-replacement)),
it should be re-checked for \? here.

But generally your changes work fine.  I only want to propose some
improvements: when the user types ! to replace all matches and the
replacement string contains \?, then matches are not highlighted in
the buffer when the user edits the replacement.  This could be
highlighted before reading the replacement string in
`replace-match-maybe-edit' by calling `replace-highlight'.

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

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

* Re: query-replace-interactive not documented
  2004-06-17 23:05                                           ` Richard Stallman
@ 2004-06-18  6:55                                             ` Juri Linkov
  2004-06-19  3:19                                               ` Richard Stallman
  0 siblings, 1 reply; 101+ messages in thread
From: Juri Linkov @ 2004-06-18  6:55 UTC (permalink / raw)
  Cc: David Kastrup, emacs-devel

Richard Stallman <rms@gnu.org> writes:
> Using a space to end a variable name after `\,' is a clean solution.

Using a space is fine, but not deleting it.

When the user wants to get a replacement like "value text" with the
space in it and writes the replacement expression "\,variable text",
and Emacs eats the space character and produces the replacement
"valuetext", this might be too annoying.

Instead of deleting the space, in cases where the user DON'T want a
space between a variable value and the followed text, he can add
separators like the close paren in "\,(or variable)text".

If such cases where users don't want a space are really too frequent,
we might find more complicated solution like for example, reading
from "\,variabletext" the whole symbol "variabletext" and chopping
characters from the end of the symbol: "variabletex", "variablete",
etc. and checking with `boundp' until we find a bound symbol.  This
works for all variables except locally bound in `perform-replace'
and `replace-eval-replacement'.  But the most frequently used local
variable is `replace-count' which now has a special symbol \#, so this
is not a big problem.

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

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

* Re: query-replace-interactive not documented
  2004-06-18  6:43                                                       ` Juri Linkov
@ 2004-06-18  7:13                                                         ` David Kastrup
  0 siblings, 0 replies; 101+ messages in thread
From: David Kastrup @ 2004-06-18  7:13 UTC (permalink / raw)
  Cc: emacs-devel

Juri Linkov <juri@jurta.org> writes:

> David Kastrup <dak@gnu.org> writes:
> > Here is a sketch.  I am calling it a sketch since the string-match for
> > \? should not be done for every replacement again if the replacement
> > string did not contain \? in the first place.  This is a performance
> > hog otherwise when doing lots of replacements automatically.
> 
> You can match it once in the beginning of the main while-loop and
> store the result into a variable which would be given as an argument
> of `replace-match-maybe-edit'.

Which is more or less what I do now in the current code.  However, I
am still trying to get a hang on the match-data: it needs to be in
markers when editing functions are called since the user might then
change buffers end edit stuff behind the back of the program.  Quite
ugly.

I am trying to get this both correct and efficient at the same time.
Strictly speaking, one needs markers for every non-made change in the
stack when user-editing is allowed.  Perhaps one should allow only a
certain number of unmade replacements and kill off all markers
further back in the history.

> But generally your changes work fine.  I only want to propose some
> improvements: when the user types ! to replace all matches and the
> replacement string contains \?, then matches are not highlighted in
> the buffer when the user edits the replacement.  This could be
> highlighted before reading the replacement string in
> `replace-match-maybe-edit' by calling `replace-highlight'.

I am still trying to get the code to do the right think which it
doesn't.  Of course, not just the fault of \? here.

-- 
David Kastrup, Kriemhildstr. 15, 44793 Bochum

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

* isearch hooks (was: query-replace-interactive not documented)
  2004-06-12  1:50           ` Richard Stallman
@ 2004-06-18 20:00             ` Juri Linkov
  2004-06-19  1:10               ` Miles Bader
                                 ` (2 more replies)
  0 siblings, 3 replies; 101+ messages in thread
From: Juri Linkov @ 2004-06-18 20:00 UTC (permalink / raw)
  Cc: emacs-devel

Juri Linkov <juri@jurta.org> writes:
> I noticed that the commentary section of isearch.el has the following
> TODO item:
>
> ;; - Think about incorporating query-replace.

isearch.el has also another TODO item:

;; - Hooks and options for failed search.

I remember there was a discussion on emacs-devel two months ago about
searching across several buffers or Info nodes.  Adding hooks for
failed and wrapped search will allow to implement these features.

The patch below adds two hooks `isearch-wrapped-hook' and
`isearch-failed-hook'.  When these hooks are not specified, isearch
keeps its current behavior: when failed, it displays "Failing
I-search" message; and when wrapped, it moves the point to the
beginning/end of the buffer.

But with using these hooks many useful things are possible.
For example, to search across Info nodes `isearch-wrapped-hook' can
use `Info-search' to move between Info nodes, and `isearch-failed-hook'
to move to the next Info node immediately:

(add-hook 'Info-mode-hook
 (lambda ()
   (set (make-local-variable 'isearch-wrapped-hook)
        (lambda ()
          (Info-search isearch-string (unless isearch-forward 'backward))
          (goto-char (if isearch-forward (point-min) (point-max)))
          (setq isearch-cmds nil)))
   (set (make-local-variable 'isearch-failed-hook)
        (lambda ()
          (isearch-repeat (if isearch-forward 'forward 'backward))))))

Another example is isearching multiple buffers:

(defvar my-buffer-list nil)

(add-hook 'isearch-mode-hook
          (lambda () (setq my-buffer-list (cdr (buffer-list)))))

(add-hook 'isearch-wrapped-hook
          (lambda ()
            ;; skip buffers with no isearch-string
            (while (and my-buffer-list
                        (progn
                          (switch-to-buffer (car my-buffer-list))
                          (goto-char (point-min))
                          (prog1 (not (re-search-forward isearch-string nil t))
                            (setq my-buffer-list (cdr my-buffer-list))))))
            (goto-char (if isearch-forward (point-min) (point-max)))
            (setq isearch-cmds nil)))

These examples could be developed further to include them into info.el etc.
and to make options to enable hooks.

Anyway, I think the change which allows to call hooks can be installed
now, since it doesn't change the current behavior.

Index: lisp/isearch.el
===================================================================
RCS file: /cvsroot/emacs/emacs/lisp/isearch.el,v
retrieving revision 1.228
diff -u -r1.228 isearch.el
--- lisp/isearch.el	6 Jun 2004 13:57:39 -0000	1.228
+++ lisp/isearch.el	18 Jun 2004 16:15:25 -0000
@@ -57,48 +57,6 @@
 ;; keep the behavior.  No point in forcing nonincremental search until
 ;; the last possible moment.
 
-;; TODO
-;; - Integrate the emacs 19 generalized command history.
-;; - Think about incorporating query-replace.
-;; - Hooks and options for failed search.
 
 ;;; Change Log:
 
@@ -199,6 +157,15 @@
 (defvar isearch-mode-end-hook nil
   "Function(s) to call after terminating an incremental search.")
 
+(defvar isearch-wrapped-hook nil
+  "Function(s) to call when search is wrapped.
+If nil, move point to the beginning of the buffer for forward search,
+or to the end of the buffer for reverse search.")
+
+(defvar isearch-failed-hook nil
+  "Function(s) to call when search is failed.
+If nil, ding.")
+
 ;; Search ring.
 
 (defvar search-ring nil
@@ -990,7 +968,9 @@
 	;; If already have what to search for, repeat it.
 	(or isearch-success
 	    (progn
-	      (goto-char (if isearch-forward (point-min) (point-max)))
+	      (if isearch-wrapped-hook
+                  (run-hooks 'isearch-wrapped-hook)
+                (goto-char (if isearch-forward (point-min) (point-max))))
 	      (setq isearch-wrapped t))))
     ;; C-s in reverse or C-r in forward, change direction.
     (setq isearch-forward (not isearch-forward)))
@@ -1786,6 +1867,7 @@
   (or isearch-success (setq ellipsis nil))
   (let ((m (concat (if isearch-success "" "failing ")
 		   (if (and isearch-wrapped
+			    (not isearch-wrapped-hook)
 			    (if isearch-forward
 				(> (point) isearch-opoint)
 			      (< (point) isearch-opoint)))
@@ -1876,9 +1961,9 @@
   (if isearch-success
       nil
     ;; Ding if failed this time after succeeding last time.
-    (and (nth 3 (car isearch-cmds))
-	 (ding))
-    (goto-char (nth 2 (car isearch-cmds)))))
+    (and (nth 3 (car isearch-cmds)) (or isearch-failed-hook (ding)))
+    (goto-char (nth 2 (car isearch-cmds)))
+    (if isearch-failed-hook (run-hooks 'isearch-failed-hook))))
 
 
 ;; Called when opening an overlay, and we are still in isearch.

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

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

* Re: isearch hooks (was: query-replace-interactive not documented)
  2004-06-18 20:00             ` isearch hooks (was: query-replace-interactive not documented) Juri Linkov
@ 2004-06-19  1:10               ` Miles Bader
  2004-06-19 18:09                 ` isearch hooks Juri Linkov
  2004-06-19  3:19               ` isearch hooks (was: query-replace-interactive not documented) Richard Stallman
  2004-06-29  0:25               ` isearch hooks (was: query-replace-interactive not documented) Stefan
  2 siblings, 1 reply; 101+ messages in thread
From: Miles Bader @ 2004-06-19  1:10 UTC (permalink / raw)
  Cc: rms, emacs-devel

On Fri, Jun 18, 2004 at 11:00:09PM +0300, Juri Linkov wrote:
> The patch below adds two hooks `isearch-wrapped-hook' and
> `isearch-failed-hook'.

I like the idea, but a few comments:

 (1) I'm a bit confused about why there should be two hooks -- both are
     really instances of search failure, right?  Can they be combined?

 (2) The name `isearch-wrapped-hook' seems wrong anyway: the hook appears to
     be an _alternative_ to wrapping, not something that runs _after_
     wrapping, so something like `isearch-wrap-hook' seems more appropriate,
     (if this hook cannot be combined with the other hook).

 (3) It seems that these should be `-function' variables, not `-hook'
     variables, as they modify behavior instead of merely extending it, and
     multiple entries don't seem likely to work correctly.

 (4) Should the code set `isearch-wrapped' even when the user-function is
     run instead of the default code?

Thanks,

-Miles
-- 
`...the Soviet Union was sliding in to an economic collapse so comprehensive
 that in the end its factories produced not goods but bads: finished products
 less valuable than the raw materials they were made from.'  [The Economist]

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

* Re: query-replace-interactive not documented
  2004-06-18  6:55                                             ` Juri Linkov
@ 2004-06-19  3:19                                               ` Richard Stallman
  2004-06-19  7:00                                                 ` David Kastrup
  0 siblings, 1 reply; 101+ messages in thread
From: Richard Stallman @ 2004-06-19  3:19 UTC (permalink / raw)
  Cc: dak, emacs-devel

    > Using a space to end a variable name after `\,' is a clean solution.

    Using a space is fine, but not deleting it.

Yes, it should delete the space.  Users will find this natural once
they know about it.  Many other programs have had such interfaces.

    Instead of deleting the space, in cases where the user DON'T want a
    space between a variable value and the followed text, he can add
    separators like the close paren in "\,(or variable)text".

That is much less convenient.

    If such cases where users don't want a space are really too frequent,
    we might find more complicated solution like for example, reading
    from "\,variabletext" the whole symbol "variabletext" and chopping
    characters from the end of the symbol: "variabletex", "variablete",
    etc. and checking with `boundp' until we find a bound symbol.

That is unpredictable.   Swallowing a space is much better.

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

* Re: isearch hooks (was: query-replace-interactive not documented)
  2004-06-18 20:00             ` isearch hooks (was: query-replace-interactive not documented) Juri Linkov
  2004-06-19  1:10               ` Miles Bader
@ 2004-06-19  3:19               ` Richard Stallman
  2004-06-19 18:36                 ` isearch hooks Juri Linkov
  2004-06-29  0:25               ` isearch hooks (was: query-replace-interactive not documented) Stefan
  2 siblings, 1 reply; 101+ messages in thread
From: Richard Stallman @ 2004-06-19  3:19 UTC (permalink / raw)
  Cc: emacs-devel

    The patch below adds two hooks `isearch-wrapped-hook' and
    `isearch-failed-hook'.

Thanks for working on it.

However, I have a feeling that `isearch-failed-hook' is not
implemented properly for the intended use.  If isearch should move
between info nodes, the natural way is that a failing search should
switch nodes and then try again.  To do that, this hook should run
shortly after the actual search primitive, and it should be run with
run-hook-with-args-until-success, and if it succeeds then
isearch-success should be t--as if the search primitive had succeeded.
So it won't put "Failed " in the echo area, for instance.

I just looked at isearch.el and came across isearch-search-fun-function.
I have a feeling that the right way to make isearch search through
multiple nodes or buffers is to define a new low-level search function
and interface it through isearch-search-fun-function.

Does that look right to you?

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

* Re: query-replace-interactive not documented
  2004-06-19  3:19                                               ` Richard Stallman
@ 2004-06-19  7:00                                                 ` David Kastrup
  2004-06-20 19:18                                                   ` Richard Stallman
  0 siblings, 1 reply; 101+ messages in thread
From: David Kastrup @ 2004-06-19  7:00 UTC (permalink / raw)
  Cc: Juri Linkov, emacs-devel

Richard Stallman <rms@gnu.org> writes:

>     > Using a space to end a variable name after `\,' is a clean solution.
> 
>     Using a space is fine, but not deleting it.
> 
> Yes, it should delete the space.  Users will find this natural once
> they know about it.  Many other programs have had such interfaces.

Wel, optional spaces in the middle of regexp are something that needs
extra explaining.  And the question is how to make that rule
consistent.  There are some Lisp expressions that are
"self-sufficient", like everything enclosed in parens or quotes, and
some that are ended by an incompatible character following, like
symbols.  Actually, I can't think about much except symbols here, and
maybe forms like 'symbol which end up as a list.

It does feel somewhat strange that the replacement expression
x + \,(1+ \#) + y;
would swallow a space, and even requiring something like
x + \,replace-count  + y;
is not particularly pretty.

>     Instead of deleting the space, in cases where the user DON'T want a
>     space between a variable value and the followed text, he can add
>     separators like the close paren in "\,(or variable)text".
> 
> That is much less convenient.

Somewhat (4 more letters), but it is also rarely needed.  The only
_variable_ identifier that is really defined in replacements is
replace-count, and I added the shorthand \# for what would amount to
\'replace-count already.  So we are basically just talking about
constants stored in Lisp symbols, and there is not much of an
incentive for using those: you can just write the contents in the
replacement string instead.

So I think we are talking about an additional rule that would be
required rather rarely in practice, has an easily available workaround
available, and that would either need to have special exceptions again
or would also impact expressions that are already properly bracketed
and don't need additional spaces, by far the most common occurence.

Have you taken a look at the DOC-string of the currently checked-in
version of query-replace-regexp?  I think the current behavior is, all
in all, clear, convenient and easily explained.

-- 
David Kastrup, Kriemhildstr. 15, 44793 Bochum

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

* Re: isearch hooks
  2004-06-19  1:10               ` Miles Bader
@ 2004-06-19 18:09                 ` Juri Linkov
  0 siblings, 0 replies; 101+ messages in thread
From: Juri Linkov @ 2004-06-19 18:09 UTC (permalink / raw)
  Cc: rms, emacs-devel

Miles Bader <miles@gnu.org> writes:
> On Fri, Jun 18, 2004 at 11:00:09PM +0300, Juri Linkov wrote:
>> The patch below adds two hooks `isearch-wrapped-hook' and
>> `isearch-failed-hook'.
>
> I like the idea, but a few comments:
>
>  (1) I'm a bit confused about why there should be two hooks -- both are
>      really instances of search failure, right?  Can they be combined?

I initially thought two hooks might be useful because that allows to
put into hooks something more than planned switching buffers or Info nodes.
But perhaps one hook and one variable which enables wrapping immediately
after failing is enough.

>  (2) The name `isearch-wrapped-hook' seems wrong anyway: the hook appears to
>      be an _alternative_ to wrapping, not something that runs _after_
>      wrapping, so something like `isearch-wrap-hook' seems more appropriate,
>      (if this hook cannot be combined with the other hook).

Yes, `isearch-wrap-hook' is a better name, even for a combined hook.

>  (3) It seems that these should be `-function' variables, not `-hook'
>      variables, as they modify behavior instead of merely extending it, and
>      multiple entries don't seem likely to work correctly.

Perhaps the plural form `isearch-wrap-functions' is better when using
`run-hook-with-args-until-success', as Richard suggested, to try
multiple functions until one of them returns a non-nil value.

>  (4) Should the code set `isearch-wrapped' even when the user-function is
>      run instead of the default code?

I think `isearch-wrapped' should be set to t even when the
user-function is run.  As I can see from isearch.el, the variable
`isearch-wrapped' is used only to display the proper message
(either "wrapped" or "overwrapped").  I already added the condition
in the previous patch I sent that if `isearch-wrapped-hook' is defined,
to not display the prefix "over" since this makes no sense for cases
with switching buffers.  But the message "wrapped" still seems
appropriate to indicate that the search was moved into another buffer
or Info node.

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

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

* Re: isearch hooks
  2004-06-19  3:19               ` isearch hooks (was: query-replace-interactive not documented) Richard Stallman
@ 2004-06-19 18:36                 ` Juri Linkov
  2004-06-20 19:18                   ` Richard Stallman
  0 siblings, 1 reply; 101+ messages in thread
From: Juri Linkov @ 2004-06-19 18:36 UTC (permalink / raw)
  Cc: emacs-devel

Richard Stallman <rms@gnu.org> writes:
>     The patch below adds two hooks `isearch-wrapped-hook' and
>     `isearch-failed-hook'.
>
> Thanks for working on it.
>
> However, I have a feeling that `isearch-failed-hook' is not
> implemented properly for the intended use.  If isearch should move
> between info nodes, the natural way is that a failing search should
> switch nodes and then try again.  To do that, this hook should run
> shortly after the actual search primitive, and it should be run with
> run-hook-with-args-until-success, and if it succeeds then
> isearch-success should be t--as if the search primitive had succeeded.
> So it won't put "Failed " in the echo area, for instance.

This seems to be the right place to call the hook.

> I just looked at isearch.el and came across isearch-search-fun-function.
> I have a feeling that the right way to make isearch search through
> multiple nodes or buffers is to define a new low-level search function
> and interface it through isearch-search-fun-function.
>
> Does that look right to you?

It doesn't look right since `isearch-search-fun' is used to specify
the function to call for the search different from the default
`search-forward' or `re-search-forward'.  But in the intended cases
default functions are suitable to search the text in the buffer.
What is needed is to switch locations on the search when the search
in the current buffers is failed.

In the newest version I added a new variable `isearch-wrap-failed'.
If it is set to non-nil the search will not pause for displaying the
message "Failing I-search..." but will immediately wrap the search
to the location found by `isearch-wrap-functions'.

If `isearch-wrap-failed' is nil and `isearch-wrap-functions' are
specified, these hooks are called in another place, where currently
the point is moved to the beginning/end of the buffer.

And below is the hook which works for moving between Info nodes.
It sets isearch-cmds to nil, because it's impossible to restore
previous positions in visited Info nodes by typing DEL in isearch mode.

If it is ok, it could be added to info.el to be activated by some option
or minor mode.

(add-hook 'isearch-wrap-functions
          (lambda ()
            (Info-search isearch-string (unless isearch-forward 'backward))
            (goto-char (if isearch-forward (point-min) (point-max)))
            (setq isearch-cmds nil)
            t)
          nil t)

(set (make-local-variable 'isearch-wrap-failed) t)

There is also the patch to info.el below after isearch.el
which implements a backward search in Info mode.

Index: lisp/isearch.el
===================================================================
RCS file: /cvsroot/emacs/emacs/lisp/isearch.el,v
retrieving revision 1.228
diff -u -r1.228 isearch.el
--- lisp/isearch.el	6 Jun 2004 13:57:39 -0000	1.228
+++ lisp/isearch.el	19 Jun 2004 18:02:39 -0000
@@ -199,6 +157,14 @@
 (defvar isearch-mode-end-hook nil
   "Function(s) to call after terminating an incremental search.")
 
+(defvar isearch-wrap-functions nil
+  "Function(s) to call to wrap the search when search is failed.
+If nil, move point to the beginning of the buffer for a forward search,
+or to the end of the buffer for a backward search.")
+
+(defvar isearch-wrap-failed nil
+  "If non-nil, search is wrapped immediately after failing.")
+
 ;; Search ring.
 
 (defvar search-ring nil
@@ -990,8 +967,12 @@
 	;; If already have what to search for, repeat it.
 	(or isearch-success
 	    (progn
-	      (goto-char (if isearch-forward (point-min) (point-max)))
-	      (setq isearch-wrapped t))))
+             ;; `isearch-search' takes care of the following condition
+	      (when (not (and isearch-wrap-functions isearch-wrap-failed))
+                (if isearch-wrap-functions
+                    (run-hook-with-args-until-success 'isearch-wrap-functions)
+                  (goto-char (if isearch-forward (point-min) (point-max))))
+                (setq isearch-wrapped t)))))
     ;; C-s in reverse or C-r in forward, change direction.
     (setq isearch-forward (not isearch-forward)))
 
@@ -1786,6 +1885,7 @@
   (or isearch-success (setq ellipsis nil))
   (let ((m (concat (if isearch-success "" "failing ")
 		   (if (and isearch-wrapped
+			    (not isearch-wrap-functions)
 			    (if isearch-forward
 				(> (point) isearch-opoint)
 			      (< (point) isearch-opoint)))
@@ -1836,7 +1939,8 @@
       (let ((inhibit-point-motion-hooks search-invisible)
 	    (inhibit-quit nil)
 	    (case-fold-search isearch-case-fold-search)
-	    (retry t))
+	    (retry t)
+	    (m nil))
 	(if isearch-regexp (setq isearch-invalid-regexp nil))
 	(setq isearch-within-brackets nil)
 	(while retry
@@ -1852,7 +1956,15 @@
 		  (= (match-beginning 0) (match-end 0))
 		  (not (isearch-range-invisible
 			(match-beginning 0) (match-end 0))))
-	      (setq retry nil)))
+	      (setq retry nil))
+          (if (and isearch-wrap-failed isearch-wrap-functions
+		   (not isearch-success)
+		   (not (and (markerp m)
+			     (eq (marker-buffer m) (current-buffer))
+			     (eq (marker-position m) (point))))
+		   (run-hook-with-args-until-success
+		    'isearch-wrap-functions))
+	      (setq retry t m (point-marker) isearch-wrapped t)))
 	(setq isearch-just-started nil)
 	(if isearch-success
 	    (setq isearch-other-end
@@ -1878,7 +1990,8 @@
     ;; Ding if failed this time after succeeding last time.
     (and (nth 3 (car isearch-cmds))
 	 (ding))
-    (goto-char (nth 2 (car isearch-cmds)))))
+    (and (nth 2 (car isearch-cmds))
+	 (goto-char (nth 2 (car isearch-cmds))))))
 
 
 ;; Called when opening an overlay, and we are still in isearch.

Index: lisp/info.el
===================================================================
RCS file: /cvsroot/emacs/emacs/lisp/info.el,v
retrieving revision 1.398
diff -u -r1.398 info.el
--- lisp/info.el	12 Jun 2004 05:54:43 -0000	1.398
+++ lisp/info.el	19 Jun 2004 18:31:05 -0000
@@ -1442,8 +1442,9 @@
 (defvar Info-search-case-fold nil
   "The value of `case-fold-search' from previous `Info-search' command.")
 
-(defun Info-search (regexp)
-  "Search for REGEXP, starting from point, and select node it's found in."
+(defun Info-search (regexp &optional direction)
+  "Search for REGEXP, starting from point, and select node it's found in.
+If DIRECTION is `backward', search in the reverse direction."
   (interactive (list (read-string
 		      (if Info-search-history
 			  (format "Regexp search%s (default `%s'): "
@@ -1458,6 +1459,7 @@
     (setq regexp (car Info-search-history)))
   (when regexp
     (let (found beg-found give-up
+	  (backward (eq direction 'backward))
 	  (onode Info-current-node)
 	  (ofile Info-current-file)
 	  (opoint (point))
@@ -1472,14 +1474,21 @@
 	  (widen)
 	  (while (and (not give-up)
 		      (or (null found)
-			  (isearch-range-invisible beg-found found)))
-	    (if (re-search-forward regexp nil t)
-		(setq found (point) beg-found (match-beginning 0))
+			  (if backward
+                              (isearch-range-invisible found beg-found)
+                            (isearch-range-invisible beg-found found))))
+	    (if (if backward
+                    (re-search-backward regexp nil t)
+                  (re-search-forward regexp nil t))
+		(setq found (point) beg-found (if backward (match-end 0)
+                                                (match-beginning 0)))
 	      (setq give-up t)))))
       ;; If no subfiles, give error now.
       (if give-up
 	  (if (null Info-current-subfile)
-	      (re-search-forward regexp)
+	      (if backward
+                  (re-search-backward regexp)
+                (re-search-forward regexp))
 	    (setq found nil)))
 
       (unless found
@@ -1498,29 +1507,39 @@
 		  ;; Find the subfile we just searched.
 		  (search-forward (concat "\n" osubfile ": "))
 		  ;; Skip that one.
-		  (forward-line 1)
+		  (forward-line (if backward 0 1))
 		  ;; Make a list of all following subfiles.
 		  ;; Each elt has the form (VIRT-POSITION . SUBFILENAME).
-		  (while (not (eobp))
-		    (re-search-forward "\\(^.*\\): [0-9]+$")
+		  (while (not (if backward (bobp) (eobp)))
+		    (if backward
+		        (re-search-backward "\\(^.*\\): [0-9]+$")
+		      (re-search-forward "\\(^.*\\): [0-9]+$"))
 		    (goto-char (+ (match-end 1) 2))
 		    (setq list (cons (cons (+ (point-min)
 					      (read (current-buffer)))
 					   (match-string-no-properties 1))
 				     list))
-		    (goto-char (1+ (match-end 0))))
+		    (goto-char (if backward
+                                   (1- (match-beginning 0))
+                                 (1+ (match-end 0)))))
 		  ;; Put in forward order
 		  (setq list (nreverse list))))
 	      (while list
 		(message "Searching subfile %s..." (cdr (car list)))
 		(Info-read-subfile (car (car list)))
+                (if backward (goto-char (point-max)))
 		(setq list (cdr list))
 		(setq give-up nil found nil)
 		(while (and (not give-up)
 			    (or (null found)
-				(isearch-range-invisible beg-found found)))
-		  (if (re-search-forward regexp nil t)
-		      (setq found (point) beg-found (match-beginning 0))
+				(if backward
+                                    (isearch-range-invisible found beg-found)
+                                  (isearch-range-invisible beg-found found))))
+		  (if (if backward
+                          (re-search-backward regexp nil t)
+                        (re-search-forward regexp nil t))
+		      (setq found (point) beg-found (if backward (match-end 0)
+                                                      (match-beginning 0)))
 		    (setq give-up t)))
 		(if give-up
 		    (setq found nil))
@@ -1556,6 +1575,19 @@
     (if Info-search-history
         (Info-search (car Info-search-history))
       (call-interactively 'Info-search))))
+
+(defun Info-search-backward (regexp)
+  "Search for REGEXP in the reverse direction."
+  (interactive (list (read-string
+		      (if Info-search-history
+			  (format "Regexp search%s backward (default `%s'): "
+                                  (if case-fold-search "" " case-sensitively")
+				  (car Info-search-history))
+			(format "Regexp search%s backward: "
+                                (if case-fold-search "" " case-sensitively")))
+		      nil 'Info-search-history)))
+  (Info-search regexp 'backward))
+
 \f
 (defun Info-extract-pointer (name &optional errorname)
   "Extract the value of the node-pointer named NAME.

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

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

* Re: query-replace-interactive not documented
  2004-06-19  7:00                                                 ` David Kastrup
@ 2004-06-20 19:18                                                   ` Richard Stallman
  2004-06-20 21:05                                                     ` David Kastrup
  0 siblings, 1 reply; 101+ messages in thread
From: Richard Stallman @ 2004-06-20 19:18 UTC (permalink / raw)
  Cc: juri, emacs-devel

    Wel, optional spaces in the middle of regexp are something that
    needs extra explaining....Actually, I can't think about much
    except symbols here, and maybe forms like 'symbol which end up as
    a list.

I think that is simple enough to explain.

    It does feel somewhat strange that the replacement expression
    x + \,(1+ \#) + y;
    would swallow a space,

It would not swallow a space; the reader would stop after the
close paren.

    Have you taken a look at the DOC-string of the currently checked-in
    version of query-replace-regexp?

No.  Did you check something in that doesn't agree with what
I've said?


These two paragraphs of doc string

    When this function is called interactively, the replacement text
    can also contain `\\,' followed by a Lisp expression.  The escaped
    shorthands for `query-replace-regexp-eval' are also valid
    here: within the Lisp expression, you can use `\\&' for the whole
    match string, `\\N' for partial matches, `\\#&' and `\\#N' for
    the respective numeric values, and `\\#' for `replace-count'.

    If your Lisp expression is an identifier and the next
    letter in the replacement string would be interpreted as part of it,
    you can wrap it with an expression like `\\,(or \\#)'.  Incidentally,
    for this particular case you may also enter `\\#' in the replacement
    text directly.

would be clearer as follows:

    When this function is called interactively, the replacement text
    can also contain `\\,' followed by a Lisp expression.  Each
    replacement evaluates that expression to compute the replacement
    string.  In the expression, you can use `\\&' for the whole
    match string, `\\N' for partial matches, and `\\#' for the
    sequence number (origin-zero) of this replacement.

    If the replacement expression is a symbol, write a space after it
    to terminate it.

I left out the part about `\\#&' and `\\#N' because I don't understand
what they do.  I am not sure what "respective numeric values" means.
When I tried \#&, it seemed to insert the replacement count followed
by an &.


*** replace.el	17 Jun 2004 19:28:37 -0400	1.173
--- replace.el	19 Jun 2004 21:26:16 -0400	
***************
*** 165,181 ****
  whatever what matched the Nth `\\(...\\)' in REGEXP.
  
  When this function is called interactively, the replacement text
! can also contain `\\,' followed by a Lisp expression.  The escaped
! shorthands for `query-replace-regexp-eval' are also valid
! here: within the Lisp expression, you can use `\\&' for the whole
! match string, `\\N' for partial matches, `\\#&' and `\\#N' for
! the respective numeric values, and `\\#' for `replace-count'.
  
! If your Lisp expression is an identifier and the next
! letter in the replacement string would be interpreted as part of it,
! you can wrap it with an expression like `\\,(or \\#)'.  Incidentally,
! for this particular case you may also enter `\\#' in the replacement
! text directly.
  
  When you use `\\,' or `\\#' in the replacement, TO-STRING actually
  becomes a list with expanded shorthands.
--- 165,178 ----
  whatever what matched the Nth `\\(...\\)' in REGEXP.
  
  When this function is called interactively, the replacement text
! can also contain `\\,' followed by a Lisp expression.  Each
! replacement evaluates that expression to compute the replacement
! string.  In the expression, you can use `\\&' for the whole
! match string, `\\N' for partial matches, and `\\#' for the
! sequence number (origin-zero) of this replacement.
  
! If the replacement expression is a symbol, write a space after it
! to terminate it.
  
  When you use `\\,' or `\\#' in the replacement, TO-STRING actually
  becomes a list with expanded shorthands.
***************
*** 200,206 ****
  		    ((eq char ?\,)
  		     (setq pos (read-from-string to-string))
  		     (push `(replace-quote ,(car pos)) to-expr)
! 		     (setq to-string (substring to-string (cdr pos))))))
  	    (setq to-expr (nreverse (delete "" (cons to-string to-expr))))
  	    (replace-match-string-symbols to-expr)
  	    (cons 'replace-eval-replacement 
--- 197,211 ----
  		    ((eq char ?\,)
  		     (setq pos (read-from-string to-string))
  		     (push `(replace-quote ,(car pos)) to-expr)
! 		     (let ((end
! 			    ;; Swallow a space after a symbol
! 			    ;; if there is a space.
! 			    (if (and (symbolp (car pos))
! 				     (equal " " (substring to-string (cdr pos)
! 							   (1+ (cdr pos)))))
! 				(1+ (cdr pos))
! 			      (cdr pos))))
! 		       (setq to-string (substring to-string end))))))
  	    (setq to-expr (nreverse (delete "" (cons to-string to-expr))))
  	    (replace-match-string-symbols to-expr)
  	    (cons 'replace-eval-replacement 

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

* Re: isearch hooks
  2004-06-19 18:36                 ` isearch hooks Juri Linkov
@ 2004-06-20 19:18                   ` Richard Stallman
  2004-06-21 21:56                     ` Juri Linkov
  0 siblings, 1 reply; 101+ messages in thread
From: Richard Stallman @ 2004-06-20 19:18 UTC (permalink / raw)
  Cc: emacs-devel

    It doesn't look right since `isearch-search-fun' is used to specify
    the function to call for the search different from the default
    `search-forward' or `re-search-forward'.  But in the intended cases
    default functions are suitable to search the text in the buffer.
    What is needed is to switch locations on the search when the search
    in the current buffers is failed.

The function that isearch-search-fun specifies can do all of those jobs.
Do you see what I mean?

    In the newest version I added a new variable `isearch-wrap-failed'.
    If it is set to non-nil the search will not pause for displaying the
    message "Failing I-search..." but will immediately wrap the search
    to the location found by `isearch-wrap-functions'.

This is the wrong way to do it.  Wrapping should NEVER happen
immediately after the basic search fails.  You might want to do something
else after the basic search fails, but that thing is not wrapping!

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

* Re: query-replace-interactive not documented
  2004-06-20 19:18                                                   ` Richard Stallman
@ 2004-06-20 21:05                                                     ` David Kastrup
  2004-06-21  9:31                                                       ` Richard Stallman
  2004-06-21  9:31                                                       ` Richard Stallman
  0 siblings, 2 replies; 101+ messages in thread
From: David Kastrup @ 2004-06-20 21:05 UTC (permalink / raw)
  Cc: juri, emacs-devel

Richard Stallman <rms@gnu.org> writes:

>     Wel, optional spaces in the middle of regexp are something that
>     needs extra explaining....Actually, I can't think about much
>     except symbols here, and maybe forms like 'symbol which end up as
>     a list.
> 
> I think that is simple enough to explain.
> 
>     It does feel somewhat strange that the replacement expression
>     x + \,(1+ \#) + y;
>     would swallow a space,
> 
> It would not swallow a space; the reader would stop after the
> close paren.

So what is the rule?  The problem is that currently I just use
read-from-string, and that can't distinguish between
'symbol
and
(quote symbol)
even though it sounds as though both should be treated differently.

>     Have you taken a look at the DOC-string of the currently checked-in
>     version of query-replace-regexp?
> 
> No.  Did you check something in that doesn't agree with what
> I've said?

You are quoting it.

> These two paragraphs of doc string
> 
>     When this function is called interactively, the replacement text
>     can also contain `\\,' followed by a Lisp expression.  The escaped
>     shorthands for `query-replace-regexp-eval' are also valid
>     here: within the Lisp expression, you can use `\\&' for the whole
>     match string, `\\N' for partial matches, `\\#&' and `\\#N' for
>     the respective numeric values, and `\\#' for `replace-count'.
> 
>     If your Lisp expression is an identifier and the next
>     letter in the replacement string would be interpreted as part of it,
>     you can wrap it with an expression like `\\,(or \\#)'.  Incidentally,
>     for this particular case you may also enter `\\#' in the replacement
>     text directly.
> 
> would be clearer as follows:
> 
>     When this function is called interactively, the replacement text
>     can also contain `\\,' followed by a Lisp expression.  Each
>     replacement evaluates that expression to compute the replacement
>     string.  In the expression, you can use `\\&' for the whole
>     match string, `\\N' for partial matches, and `\\#' for the
>     sequence number (origin-zero) of this replacement.
> 
>     If the replacement expression is a symbol, write a space after it
>     to terminate it.

That's cheating.  It does not tell that this space will actually get
gobbled and won't appear in the replacement.  It does not tell just
_when_ such spaces will get gobbled.  It does not tell how many of
them might get gobbled.  So it is too easy.

I don't think you can do this much shorter than:

    If the replacement expression is a symbol, then it may be followed
    by one optional space that won't appear in the actual replacement.

> I left out the part about `\\#&' and `\\#N' because I don't
> understand what they do.  I am not sure what "respective numeric
> values" means.  When I tried \#&, it seemed to insert the
> replacement count followed by an &.

Not _within_ a Lisp expression, namely something like
\,(format "%d %d" \#& \#2).  And if you had a match like
\([0-9]+\), then you can do arithmetic on it with something like
\,(1+ \#1).

-- 
David Kastrup, Kriemhildstr. 15, 44793 Bochum

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

* Re: query-replace-interactive not documented
  2004-06-20 21:05                                                     ` David Kastrup
@ 2004-06-21  9:31                                                       ` Richard Stallman
  2004-06-21  9:50                                                         ` David Kastrup
  2004-06-25 23:12                                                         ` Juri Linkov
  2004-06-21  9:31                                                       ` Richard Stallman
  1 sibling, 2 replies; 101+ messages in thread
From: Richard Stallman @ 2004-06-21  9:31 UTC (permalink / raw)
  Cc: juri, emacs-devel

    So what is the rule?  The problem is that currently I just use
    read-from-string, and that can't distinguish between
    'symbol
    and
    (quote symbol)

I had not been thinking about that because I was assuming that the
reader itself would swallow the space.  However, in writing my code
I found it does not.  Indeed I forgot to handle this distinction.

Since the value is supposed to be a string, perhaps neither of these
cases matters much.  However, I think it would be easy to distinguish
them by testing whether the expression began with an open-paren.

			    ;; Swallow a space after a symbol
			    ;; if there is a space.
			    (if (and (or (symbolp (car pos))
					 ;; Swallow a space after 'foo
					 ;; but not after (quote foo).
					 (and (eq (car-safe (car pos)) 'quote)
					      (= ?\( (aref to-string 0))))
				     (equal " " (substring to-string (cdr pos)
							   (1+ (cdr pos)))))

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

* Re: query-replace-interactive not documented
  2004-06-20 21:05                                                     ` David Kastrup
  2004-06-21  9:31                                                       ` Richard Stallman
@ 2004-06-21  9:31                                                       ` Richard Stallman
  2004-06-21  9:38                                                         ` David Kastrup
  1 sibling, 1 reply; 101+ messages in thread
From: Richard Stallman @ 2004-06-21  9:31 UTC (permalink / raw)
  Cc: juri, emacs-devel

    > I left out the part about `\\#&' and `\\#N' because I don't
    > understand what they do.  I am not sure what "respective numeric
    > values" means.  When I tried \#&, it seemed to insert the
    > replacement count followed by an &.

    Not _within_ a Lisp expression, namely something like
    \,(format "%d %d" \#& \#2).  And if you had a match like
    \([0-9]+\), then you can do arithmetic on it with something like
    \,(1+ \#1).

I have a general idea now, but, what's the difference in meaning
between \#& and \&?  Between \#N and \N?

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

* Re: query-replace-interactive not documented
  2004-06-21  9:31                                                       ` Richard Stallman
@ 2004-06-21  9:38                                                         ` David Kastrup
  2004-06-22 23:17                                                           ` Richard Stallman
  0 siblings, 1 reply; 101+ messages in thread
From: David Kastrup @ 2004-06-21  9:38 UTC (permalink / raw)
  Cc: juri, emacs-devel

Richard Stallman <rms@gnu.org> writes:

>     > I left out the part about `\\#&' and `\\#N' because I don't
>     > understand what they do.  I am not sure what "respective numeric
>     > values" means.  When I tried \#&, it seemed to insert the
>     > replacement count followed by an &.
> 
>     Not _within_ a Lisp expression, namely something like
>     \,(format "%d %d" \#& \#2).  And if you had a match like
>     \([0-9]+\), then you can do arithmetic on it with something like
>     \,(1+ \#1).
> 
> I have a general idea now, but, what's the difference in meaning
> between \#& and \&?  Between \#N and \N?

\#& is short for (number-to-string \&).  There is no real difference
between
\,(\#&) and \,(\&) since the result is used with prin1-to-string, but
\,(1+ \&) would throw an error.

-- 
David Kastrup, Kriemhildstr. 15, 44793 Bochum

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

* Re: query-replace-interactive not documented
  2004-06-21  9:31                                                       ` Richard Stallman
@ 2004-06-21  9:50                                                         ` David Kastrup
  2004-06-22 23:16                                                           ` Richard Stallman
  2004-06-25 23:12                                                         ` Juri Linkov
  1 sibling, 1 reply; 101+ messages in thread
From: David Kastrup @ 2004-06-21  9:50 UTC (permalink / raw)
  Cc: juri, emacs-devel

Richard Stallman <rms@gnu.org> writes:

>     So what is the rule?  The problem is that currently I just use
>     read-from-string, and that can't distinguish between
>     'symbol
>     and
>     (quote symbol)
> 
> I had not been thinking about that because I was assuming that the
> reader itself would swallow the space.  However, in writing my code
> I found it does not.  Indeed I forgot to handle this distinction.
> 
> Since the value is supposed to be a string, perhaps neither of these
> cases matters much.  However, I think it would be easy to distinguish
> them by testing whether the expression began with an open-paren.
> 
> 			    ;; Swallow a space after a symbol
> 			    ;; if there is a space.
> 			    (if (and (or (symbolp (car pos))
> 					 ;; Swallow a space after 'foo
> 					 ;; but not after (quote foo).
> 					 (and (eq (car-safe (car pos)) 'quote)
> 					      (= ?\( (aref to-string 0))))
> 				     (equal " " (substring to-string (cdr pos)
> 							   (1+ (cdr pos)))))

Well, and then we have vectors and strings (which again usually are
properly matched).  In order to allow an optional space only where it
"is needed", one would probably have to use one's own STREAM function
by using `read' instead of `read-from-string':

read is a built-in function in `C source code'.
(read &optional STREAM)

Read one Lisp expression as text from STREAM, return as Lisp object.
If STREAM is nil, use the value of `standard-input' (which see).
STREAM or the value of `standard-input' may be:
[...]
 a function (call it with no arguments for each character,
     call it with a char as argument to push a char back)
[...]

and record when a trailing space gets unread again.  And then one
still has to explain the behavior in the DOC string.

I just doubt that the gain in convenience is worth the trouble.

-- 
David Kastrup, Kriemhildstr. 15, 44793 Bochum

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

* Re: isearch hooks
  2004-06-20 19:18                   ` Richard Stallman
@ 2004-06-21 21:56                     ` Juri Linkov
  2004-06-22 23:17                       ` Richard Stallman
  0 siblings, 1 reply; 101+ messages in thread
From: Juri Linkov @ 2004-06-21 21:56 UTC (permalink / raw)
  Cc: emacs-devel

Richard Stallman <rms@gnu.org> writes:
> The function that isearch-search-fun specifies can do all of those jobs.
> Do you see what I mean?

I see what you mean.  The difference basically boils down to two
questions: what is the scope of the search without failing, and
what is wrapping?

In the initial proposal the search scope is restricted to the current
Info node, and wrapping is going to the next Info node with the search
result.

In the solution you suggested with `isearch-search-fun' the search
scope is the whole Info manual.  But even in this case a wrapping
hook is still needed: it should wrap the failed search to the
top/final Info node.

So basically settings for Info mode could look like this:

(progn
  (set (make-local-variable 'isearch-search-fun-function)
       (lambda ()
         (lambda (regexp bound noerror)
           (condition-case nil
               (progn
                 (Info-search regexp bound noerror nil
                              (unless isearch-forward 'backward))
                 (setq isearch-cmds nil isearch-opoint (point))
                 (point))
             (error nil)))))
  (add-hook 'isearch-wrap-functions
            (lambda () (if isearch-forward (Info-top-node) (Info-final-node)))
            nil t))

There were some problems with this approach: lazy highlighting uses
the same function `isearch-search-fun' to highlight other matches.
I modified `Info-search' to accept the `bound' argument to restrict
the highlighting search to the window bounds, and made it faster by
not refontifying the current Info node if the next search result is
in the same node.

Other problems like with `Info-final-node' that returns the node which
is not quite final for `Info-search', could be fixed later if this
solution is ok.

There are some inconveniences: the user can't delete the last input
by DEL and can't return the point to the search beginning by cancelling
the search with C-g.  But that's not a big problem: the user can use
C-r to return to the previous search results.

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

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

* Re: query-replace-interactive not documented
  2004-06-21  9:50                                                         ` David Kastrup
@ 2004-06-22 23:16                                                           ` Richard Stallman
  0 siblings, 0 replies; 101+ messages in thread
From: Richard Stallman @ 2004-06-22 23:16 UTC (permalink / raw)
  Cc: juri, emacs-devel

    Well, and then we have vectors and strings (which again usually are
    properly matched).

There is no problem for vectors and strings.
Those cases should work with no special attention.

Would you show me the case in which you think my latest code fails?

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

* Re: query-replace-interactive not documented
  2004-06-21  9:38                                                         ` David Kastrup
@ 2004-06-22 23:17                                                           ` Richard Stallman
  2004-06-22 23:20                                                             ` David Kastrup
  0 siblings, 1 reply; 101+ messages in thread
From: Richard Stallman @ 2004-06-22 23:17 UTC (permalink / raw)
  Cc: juri, emacs-devel

    > I have a general idea now, but, what's the difference in meaning
    > between \#& and \&?  Between \#N and \N?

    \#& is short for (number-to-string \&).  There is no real difference
    between
    \,(\#&) and \,(\&) since the result is used with prin1-to-string, but
    \,(1+ \&) would throw an error.

Did you mean string-to-number?

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

* Re: isearch hooks
  2004-06-21 21:56                     ` Juri Linkov
@ 2004-06-22 23:17                       ` Richard Stallman
  2004-06-25 18:07                         ` Juri Linkov
  0 siblings, 1 reply; 101+ messages in thread
From: Richard Stallman @ 2004-06-22 23:17 UTC (permalink / raw)
  Cc: emacs-devel

    In the initial proposal the search scope is restricted to the current
    Info node, and wrapping is going to the next Info node with the search
    result.

That would be a coherent kind of extension, but we would
not want to call it "wrapping".  "Wrapping" means going up to the top
and searching the same material.

    In the solution you suggested with `isearch-search-fun' the search
    scope is the whole Info manual.  But even in this case a wrapping
    hook is still needed: it should wrap the failed search to the
    top/final Info node.

I agree.

    There were some problems with this approach: lazy highlighting uses
    the same function `isearch-search-fun' to highlight other matches.

It could well be that the existing hook isearch-search-fun is not adequate.
An additional hook for searching other places, before "failing" but
not used by lazy highlighting, could be useful.

    There are some inconveniences: the user can't delete the last input
    by DEL and can't return the point to the search beginning by cancelling
    the search with C-g.

Can you design the hooks to fix all these problems?

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

* Re: query-replace-interactive not documented
  2004-06-22 23:17                                                           ` Richard Stallman
@ 2004-06-22 23:20                                                             ` David Kastrup
  0 siblings, 0 replies; 101+ messages in thread
From: David Kastrup @ 2004-06-22 23:20 UTC (permalink / raw)
  Cc: juri, emacs-devel

Richard Stallman <rms@gnu.org> writes:

>     > I have a general idea now, but, what's the difference in meaning
>     > between \#& and \&?  Between \#N and \N?
> 
>     \#& is short for (number-to-string \&).  There is no real difference
>     between
>     \,(\#&) and \,(\&) since the result is used with prin1-to-string, but
>     \,(1+ \&) would throw an error.
> 
> Did you mean string-to-number?

You bet.  Some day I'll be able to just say what I mean.

-- 
David Kastrup, Kriemhildstr. 15, 44793 Bochum

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

* Re: isearch hooks
  2004-06-22 23:17                       ` Richard Stallman
@ 2004-06-25 18:07                         ` Juri Linkov
  2004-06-27 17:41                           ` Richard Stallman
  0 siblings, 1 reply; 101+ messages in thread
From: Juri Linkov @ 2004-06-25 18:07 UTC (permalink / raw)
  Cc: emacs-devel

Richard Stallman <rms@gnu.org> writes:
>     There were some problems with this approach: lazy highlighting uses
>     the same function `isearch-search-fun' to highlight other matches.
>
> It could well be that the existing hook isearch-search-fun is not adequate.
> An additional hook for searching other places, before "failing" but
> not used by lazy highlighting, could be useful.

The existing hook `isearch-search-fun-function' seems adequate for lazy
highlighting because the same search function should be used to highlight
other possible matches which will be visited by the same search
function (and in case of `Info-search' its matches are different from
matches found by the default `isearch-search-fun' because `Info-search'
ignores whitespace chars).  The search function should be responsible
for interpreting the `bound' argument (which is set by lazy highlighting
to window boundaries) and restricting the search to these boundaries.

>     There are some inconveniences: the user can't delete the last input
>     by DEL and can't return the point to the search beginning by cancelling
>     the search with C-g.
>
> Can you design the hooks to fix all these problems?

I added two new hooks: `isearch-push-state-function' and
`isearch-pop-state-function' to save/restore the current Info file
and node names in the search status stack.  With changes in
`isearch-cancel', `isearch-abort', `isearch-top-state' and
`isearch-push-state' search locations are restored on typing
`DEL', `C-g', `ESC ESC ESC'.

The patch below for info.el sets four isearch functions in Info-mode
by default, and `Info-isearch-search-function' uses `Info-search' only
for regexp search.  This makes sense because Info search is a regexp
search already.  So to search only within a Info node users can use
C-s (non-regexp), and to search across the whole Info manual C-M-s.
I think this is a good default behavior since the cases when users
might want to restrict a regexp search only to the current Info node
are very rare.

Index: lisp/isearch.el
===================================================================
RCS file: /cvsroot/emacs/emacs/lisp/isearch.el,v
retrieving revision 1.229
diff -u -r1.229 isearch.el
--- lisp/isearch.el	21 Jun 2004 03:15:43 -0000	1.229
+++ lisp/isearch.el	25 Jun 2004 17:26:12 -0000
@@ -199,6 +157,17 @@
 (defvar isearch-mode-end-hook nil
   "Function(s) to call after terminating an incremental search.")
 
+(defvar isearch-wrap-function nil
+  "Function to call to wrap the search when search is failed.
+If nil, move point to the beginning of the buffer for a forward search,
+or to the end of the buffer for a backward search.")
+
+(defvar isearch-push-state-function nil
+  "Function to save additional information to the search status stack.")
+
+(defvar isearch-pop-state-function nil
+  "Function to restore additional information from the search status stack.")
+
 ;; Search ring.
 
 (defvar search-ring nil
@@ -946,10 +926,12 @@
 (defun isearch-cancel ()
   "Terminate the search and go back to the starting point."
   (interactive)
-  (goto-char isearch-opoint)
-  (isearch-done t)
+  (if isearch-pop-state-function
+      (funcall isearch-pop-state-function (car (last isearch-cmds)))
+    (goto-char isearch-opoint))
+  (isearch-done t)                      ; exit isearch
   (isearch-clean-overlays)
-  (signal 'quit nil))  ; and pass on quit signal
+  (signal 'quit nil))                   ; and pass on quit signal
 
 (defun isearch-abort ()
   "Abort incremental search mode if searching is successful, signaling quit.
@@ -961,11 +943,9 @@
   (if isearch-success
       ;; If search is successful, move back to starting point
       ;; and really do quit.
-      (progn (goto-char isearch-opoint)
-	     (setq isearch-success nil)
-	     (isearch-done t)   ; exit isearch
-	     (isearch-clean-overlays)
-	     (signal 'quit nil))  ; and pass on quit signal
+      (progn
+        (setq isearch-success nil)
+        (isearch-cancel))
     ;; If search is failing, or has an incomplete regexp,
     ;; rub out until it is once more successful.
     (while (or (not isearch-success) isearch-invalid-regexp)
@@ -990,7 +970,9 @@
 	;; If already have what to search for, repeat it.
 	(or isearch-success
 	    (progn
-	      (goto-char (if isearch-forward (point-min) (point-max)))
+	      (if isearch-wrap-function
+		  (funcall isearch-wrap-function)
+	        (goto-char (if isearch-forward (point-min) (point-max))))
 	      (setq isearch-wrapped t))))
     ;; C-s in reverse or C-r in forward, change direction.
     (setq isearch-forward (not isearch-forward)))
@@ -1742,7 +1762,9 @@
 	  isearch-barrier (nth 9 cmd)
 	  isearch-within-brackets (nth 10 cmd)
 	  isearch-case-fold-search (nth 11 cmd))
-    (goto-char (car (cdr (cdr cmd))))))
+    (if isearch-pop-state-function
+        (funcall isearch-pop-state-function cmd)
+      (goto-char (car (cdr (cdr cmd)))))))
 
 (defun isearch-pop-state ()
   (setq isearch-cmds (cdr isearch-cmds))
@@ -1750,11 +1772,14 @@
 
 (defun isearch-push-state ()
   (setq isearch-cmds
-	(cons (list isearch-string isearch-message (point)
-		    isearch-success isearch-forward isearch-other-end
-		    isearch-word
-		    isearch-invalid-regexp isearch-wrapped isearch-barrier
-		    isearch-within-brackets isearch-case-fold-search)
+	(cons (append
+               (list isearch-string isearch-message (point)
+                     isearch-success isearch-forward isearch-other-end
+                     isearch-word
+                     isearch-invalid-regexp isearch-wrapped isearch-barrier
+                     isearch-within-brackets isearch-case-fold-search)
+               (if isearch-push-state-function
+                   (list (funcall isearch-push-state-function))))
 	      isearch-cmds)))
 
 \f
@@ -1793,6 +1818,7 @@
   (or isearch-success (setq ellipsis nil))
   (let ((m (concat (if isearch-success "" "failing ")
 		   (if (and isearch-wrapped
+			    (not isearch-wrap-function)
 			    (if isearch-forward
 				(> (point) isearch-opoint)
 			      (< (point) isearch-opoint)))

Index: lisp/info.el
===================================================================
RCS file: /cvsroot/emacs/emacs/lisp/info.el,v
retrieving revision 1.398
diff -u -r1.398 info.el
--- lisp/info.el	12 Jun 2004 05:54:43 -0000	1.398
+++ lisp/info.el	25 Jun 2004 17:33:41 -0000
@@ -1442,8 +1442,9 @@
 (defvar Info-search-case-fold nil
   "The value of `case-fold-search' from previous `Info-search' command.")
 
-(defun Info-search (regexp)
-  "Search for REGEXP, starting from point, and select node it's found in."
+(defun Info-search (regexp &optional bound noerror count direction)
+  "Search for REGEXP, starting from point, and select node it's found in.
+If DIRECTION is `backward', search in the reverse direction."
   (interactive (list (read-string
 		      (if Info-search-history
 			  (format "Regexp search%s (default `%s'): "
@@ -1458,31 +1459,42 @@
     (setq regexp (car Info-search-history)))
   (when regexp
     (let (found beg-found give-up
+	  (backward (eq direction 'backward))
 	  (onode Info-current-node)
 	  (ofile Info-current-file)
 	  (opoint (point))
+	  (opoint-min (point-min))
+	  (opoint-max (point-max))
 	  (ostart (window-start))
 	  (osubfile Info-current-subfile))
       (when Info-search-whitespace-regexp
         (setq regexp (replace-regexp-in-string
                       "[ \t\n]+" Info-search-whitespace-regexp regexp)))
       (setq Info-search-case-fold case-fold-search)
       (save-excursion
 	(save-restriction
 	  (widen)
 	  (while (and (not give-up)
 		      (or (null found)
-			  (isearch-range-invisible beg-found found)))
-	    (if (re-search-forward regexp nil t)
-		(setq found (point) beg-found (match-beginning 0))
+			  (if backward
+                              (isearch-range-invisible found beg-found)
+                            (isearch-range-invisible beg-found found))))
+	    (if (if backward
+                    (re-search-backward regexp bound t)
+                  (re-search-forward regexp bound t))
+		(setq found (point) beg-found (if backward (match-end 0)
+                                                (match-beginning 0)))
 	      (setq give-up t)))))
       ;; If no subfiles, give error now.
       (if give-up
 	  (if (null Info-current-subfile)
-	      (re-search-forward regexp)
+	      (if backward
+                  (re-search-backward regexp)
+                (re-search-forward regexp))
 	    (setq found nil)))
 
-      (unless found
+      (unless (or found bound)
 	(unwind-protect
 	    ;; Try other subfiles.
 	    (let ((list ()))
@@ -1498,29 +1510,39 @@
 		  ;; Find the subfile we just searched.
 		  (search-forward (concat "\n" osubfile ": "))
 		  ;; Skip that one.
-		  (forward-line 1)
+		  (forward-line (if backward 0 1))
 		  ;; Make a list of all following subfiles.
 		  ;; Each elt has the form (VIRT-POSITION . SUBFILENAME).
-		  (while (not (eobp))
-		    (re-search-forward "\\(^.*\\): [0-9]+$")
+		  (while (not (if backward (bobp) (eobp)))
+		    (if backward
+		        (re-search-backward "\\(^.*\\): [0-9]+$")
+		      (re-search-forward "\\(^.*\\): [0-9]+$"))
 		    (goto-char (+ (match-end 1) 2))
 		    (setq list (cons (cons (+ (point-min)
 					      (read (current-buffer)))
 					   (match-string-no-properties 1))
 				     list))
-		    (goto-char (1+ (match-end 0))))
+		    (goto-char (if backward
+                                   (1- (match-beginning 0))
+                                 (1+ (match-end 0)))))
 		  ;; Put in forward order
 		  (setq list (nreverse list))))
 	      (while list
 		(message "Searching subfile %s..." (cdr (car list)))
 		(Info-read-subfile (car (car list)))
+                (if backward (goto-char (point-max)))
 		(setq list (cdr list))
 		(setq give-up nil found nil)
 		(while (and (not give-up)
 			    (or (null found)
-				(isearch-range-invisible beg-found found)))
-		  (if (re-search-forward regexp nil t)
-		      (setq found (point) beg-found (match-beginning 0))
+				(if backward
+                                    (isearch-range-invisible found beg-found)
+                                  (isearch-range-invisible beg-found found))))
+		  (if (if backward
+                          (re-search-backward regexp nil t)
+                        (re-search-forward regexp nil t))
+		      (setq found (point) beg-found (if backward (match-end 0)
+                                                      (match-beginning 0)))
 		    (setq give-up t)))
 		(if give-up
 		    (setq found nil))
@@ -1534,9 +1556,15 @@
 		     (goto-char opoint)
 		     (Info-select-node)
 		     (set-window-start (selected-window) ostart)))))
-      (widen)
-      (goto-char found)
-      (Info-select-node)
+      (if (and (string= ofile Info-current-file)
+               (string= onode Info-current-node)
+               (> found opoint-min)
+               (< found opoint-max))
+          (goto-char found)
+        (widen)
+        (goto-char found)
+        (save-match-data (Info-select-node)))
+
       ;; Use string-equal, not equal, to ignore text props.
       (or (and (string-equal onode Info-current-node)
 	       (equal ofile Info-current-file))
@@ -1556,6 +1584,50 @@
     (if Info-search-history
         (Info-search (car Info-search-history))
       (call-interactively 'Info-search))))
+
+(defun Info-search-backward (regexp &optional bound noerror count)
+  "Search for REGEXP in the reverse direction."
+  (interactive (list (read-string
+		      (if Info-search-history
+			  (format "Regexp search%s backward (default `%s'): "
+                                  (if case-fold-search "" " case-sensitively")
+				  (car Info-search-history))
+			(format "Regexp search%s backward: "
+                                (if case-fold-search "" " case-sensitively")))
+		      nil 'Info-search-history)))
+  (Info-search regexp bound noerror count 'backward))
+
+(defun Info-isearch-search-function ()
+  (cond
+   (isearch-word
+    (if isearch-forward 'word-search-forward 'word-search-backward))
+   (isearch-regexp
+    (lambda (regexp bound noerror)
+      (condition-case nil
+          (progn
+            (Info-search regexp bound noerror nil
+                         (unless isearch-forward 'backward))
+            (point))
+        (error nil))))
+   (t
+    (if isearch-forward 'search-forward 'search-backward))))
+
+(defun Info-isearch-wrap-function ()
+  (if isearch-regexp
+      (if isearch-forward (Info-top-node) (Info-final-node))
+    (goto-char (if isearch-forward (point-min) (point-max)))))
+
+(defun Info-isearch-push-state-function ()
+  (list Info-current-file Info-current-node))
+
+(defun Info-isearch-pop-state-function (cmd)
+  (let ((file (car (nth 12 cmd)))
+        (node (cadr (nth 12 cmd))))
+    (or (and (string= Info-current-file file)
+             (string= Info-current-node node))
+        (Info-find-node file node)))
+  (goto-char (car (cdr (cdr cmd)))))
+
 \f
 (defun Info-extract-pointer (name &optional errorname)
   "Extract the value of the node-pointer named NAME.
@@ -3064,6 +3136,16 @@
   (setq desktop-save-buffer 'Info-desktop-buffer-misc-data)
   (add-hook 'clone-buffer-hook 'Info-clone-buffer-hook nil t)
   (add-hook 'change-major-mode-hook 'font-lock-defontify nil t)
+  (set (make-local-variable 'isearch-search-fun-function)
+       'Info-isearch-search-function)
+  (set (make-local-variable 'isearch-wrap-function)
+       'Info-isearch-wrap-function)
+  (set (make-local-variable 'isearch-push-state-function)
+       'Info-isearch-push-state-function)
+  (set (make-local-variable 'isearch-pop-state-function)
+       'Info-isearch-pop-state-function)
   (Info-set-mode-line)
   (run-hooks 'Info-mode-hook))

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

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

* Re: query-replace-interactive not documented
  2004-06-21  9:31                                                       ` Richard Stallman
  2004-06-21  9:50                                                         ` David Kastrup
@ 2004-06-25 23:12                                                         ` Juri Linkov
  2004-06-26  7:34                                                           ` David Kastrup
  2004-06-27 17:41                                                           ` Richard Stallman
  1 sibling, 2 replies; 101+ messages in thread
From: Juri Linkov @ 2004-06-25 23:12 UTC (permalink / raw)
  Cc: David Kastrup, emacs-devel

Richard Stallman <rms@gnu.org> writes:
> 			    ;; Swallow a space after a symbol
> 			    ;; if there is a space.
> 			    (if (and (or (symbolp (car pos))
> 					 ;; Swallow a space after 'foo
> 					 ;; but not after (quote foo).
> 					 (and (eq (car-safe (car pos)) 'quote)
> 					      (= ?\( (aref to-string 0))))
> 				     (equal " " (substring to-string (cdr pos)
> 							   (1+ (cdr pos)))))

This code doesn't work in `query-replace-read-args' since this
function uses the variable `to' instead of `to-string'.  Moreover,
I noticed that comments don't correspond to the code: it swallows
a space after (quote foo) but not after 'foo.

I regret spending time on this useless issue (there are no symbols
useful in the replacement string other than `replace-count' which
already has an abbreviation \#) but if swallowing a space is so
needed I think more appropriate condition would be to swallow a space
after any character except close-paren.

Index: lisp/replace.el
===================================================================
RCS file: /cvsroot/emacs/emacs/lisp/replace.el,v
retrieving revision 1.175
diff -u -r1.175 replace.el
--- lisp/replace.el	24 Jun 2004 23:33:59 -0000	1.175
+++ lisp/replace.el	25 Jun 2004 18:22:33 -0000
@@ -112,20 +121,16 @@
 		     (let ((end
 			    ;; Swallow a space after a symbol
 			    ;; if there is a space.
-			    (if (and (or (symbolp (car pos))
-					 ;; Swallow a space after 'foo
-					 ;; but not after (quote foo).
-					 (and (eq (car-safe (car pos)) 'quote)
-					      (= ?\( (aref to-string 0))))
-				     (equal " " (substring to-string (cdr pos)
-							   (1+ (cdr pos)))))
+			    (if (string-match
+                                 "[^])] " (substring to (1- (cdr pos))
+                                                        (1+ (cdr pos))))
 				(1+ (cdr pos))
 			      (cdr pos))))
 		       (setq to (substring to end)))))

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

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

* Re: query-replace-interactive not documented
  2004-06-25 23:12                                                         ` Juri Linkov
@ 2004-06-26  7:34                                                           ` David Kastrup
  2004-06-26 16:18                                                             ` Juri Linkov
  2004-06-27 17:41                                                           ` Richard Stallman
  1 sibling, 1 reply; 101+ messages in thread
From: David Kastrup @ 2004-06-26  7:34 UTC (permalink / raw)
  Cc: rms, emacs-devel

Juri Linkov <juri@jurta.org> writes:

> Richard Stallman <rms@gnu.org> writes:
> > 			    ;; Swallow a space after a symbol
> > 			    ;; if there is a space.
> > 			    (if (and (or (symbolp (car pos))
> > 					 ;; Swallow a space after 'foo
> > 					 ;; but not after (quote foo).
> > 					 (and (eq (car-safe (car pos)) 'quote)
> > 					      (= ?\( (aref to-string 0))))
> > 				     (equal " " (substring to-string (cdr pos)
> > 							   (1+ (cdr pos)))))
> 
> This code doesn't work in `query-replace-read-args' since this
> function uses the variable `to' instead of `to-string'.

Oh, come on.  You can't blame Richard for proposing a change to code
I changed afterwards.

> Moreover, I noticed that comments don't correspond to the code: it
> swallows a space after (quote foo) but not after 'foo.
> 
> I regret spending time on this useless issue (there are no symbols
> useful in the replacement string other than `replace-count' which
> already has an abbreviation \#) but if swallowing a space is so
> needed I think more appropriate condition would be to swallow a space
> after any character except close-paren.

Symbols may look like \)...  So it is clear that we won't get both
"correct", "convenient" and "easy to explain" behavior.

"correct" would be, in my opinion "an optional space is gobbled where
the Lisp parser actually looks forward a character".

That would mean:

\,?\)  gobble
\,"xx" don't gobble
\,?"  gobble
\,() don't gobble (note that (symbolp '()) -> t)
(xxx) don't gobble
\(xxx\) gobble

But it would be near to impossible to explain this behavior such that
people would actually be easily able to predict it.  So if we try
something like conditional gobbling, we should rather try for "caters
for most cases and is easy to explain" rule, like allowing an
optional space after everything except ) " ], regardless of whether
the last three characters my happen to be part of a symbol or not.

-- 
David Kastrup, Kriemhildstr. 15, 44793 Bochum

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

* Re: query-replace-interactive not documented
  2004-06-26  7:34                                                           ` David Kastrup
@ 2004-06-26 16:18                                                             ` Juri Linkov
  0 siblings, 0 replies; 101+ messages in thread
From: Juri Linkov @ 2004-06-26 16:18 UTC (permalink / raw)
  Cc: rms, emacs-devel

David Kastrup <dak@gnu.org> writes:
> Juri Linkov <juri@jurta.org> writes:
>> Richard Stallman <rms@gnu.org> writes:
>> > 			    ;; Swallow a space after a symbol
>> > 			    ;; if there is a space.
>> > 			    (if (and (or (symbolp (car pos))
>> > 					 ;; Swallow a space after 'foo
>> > 					 ;; but not after (quote foo).
>> > 					 (and (eq (car-safe (car pos)) 'quote)
>> > 					      (= ?\( (aref to-string 0))))
>> > 				     (equal " " (substring to-string (cdr pos)
>> > 							   (1+ (cdr pos)))))
>> 
>> This code doesn't work in `query-replace-read-args' since this
>> function uses the variable `to' instead of `to-string'.
>
> Oh, come on.  You can't blame Richard for proposing a change to code
> I changed afterwards.

I don't blame Richard.  I know Richard has very little time to test
code before installing to CVS.  But I tested it from CVS and reported
problems.

Another problem with this code is that it fails on final symbols
in the replacement string (which have no characters after the symbol
read by `read-from-string') because `substring' with (1+ (cdr pos))
signals an error.

> \,?\)  gobble
> \,"xx" don't gobble
> \,?"  gobble
> \,() don't gobble (note that (symbolp '()) -> t)
> (xxx) don't gobble
> \(xxx\) gobble
>
> But it would be near to impossible to explain this behavior such that
> people would actually be easily able to predict it.  So if we try
> something like conditional gobbling, we should rather try for "caters
> for most cases and is easy to explain" rule, like allowing an
> optional space after everything except ) " ], regardless of whether
> the last three characters my happen to be part of a symbol or not.

The simplest solution is not to mess with swallowing spaces at all
and to let users to add artificial separators like `(or variable)text'.
In this case users should learn no additional rules other than rules
of reading symbols by `read'.  IMHO.


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

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

* Re: isearch hooks
  2004-06-25 18:07                         ` Juri Linkov
@ 2004-06-27 17:41                           ` Richard Stallman
  2004-06-27 22:34                             ` Juri Linkov
  0 siblings, 1 reply; 101+ messages in thread
From: Richard Stallman @ 2004-06-27 17:41 UTC (permalink / raw)
  Cc: emacs-devel

    I added two new hooks: `isearch-push-state-function' and
    `isearch-pop-state-function' to save/restore the current Info file
    and node names in the search status stack.

I don't understand the motivation for these two hooks.
Would you please explain the idea of this design?
Why is this the right way to extend Isearch?

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

* Re: query-replace-interactive not documented
  2004-06-25 23:12                                                         ` Juri Linkov
  2004-06-26  7:34                                                           ` David Kastrup
@ 2004-06-27 17:41                                                           ` Richard Stallman
  1 sibling, 0 replies; 101+ messages in thread
From: Richard Stallman @ 2004-06-27 17:41 UTC (permalink / raw)
  Cc: dak, emacs-devel

    This code doesn't work in `query-replace-read-args' since this
    function uses the variable `to' instead of `to-string'.

Someone else moved that code after I wrote my patch.
I'm sorry I didn't see all the places that need adaptation.

Would you please install your patch?

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

* Re: isearch hooks
  2004-06-27 17:41                           ` Richard Stallman
@ 2004-06-27 22:34                             ` Juri Linkov
  2004-06-28 14:57                               ` Richard Stallman
  0 siblings, 1 reply; 101+ messages in thread
From: Juri Linkov @ 2004-06-27 22:34 UTC (permalink / raw)
  Cc: emacs-devel

Richard Stallman <rms@gnu.org> writes:
>     I added two new hooks: `isearch-push-state-function' and
>     `isearch-pop-state-function' to save/restore the current Info file
>     and node names in the search status stack.
>
> I don't understand the motivation for these two hooks.
> Would you please explain the idea of this design?
> Why is this the right way to extend Isearch?

The commands that move the point back to the previous search result
restore the previous point by setting it by `goto-char' to the
position saved in the search status stack `isearch-cmds'.  But this
doesn't work when the current search buffer switches during the search
like with changing the current Info node.

There is a need to save additional information to the search stack
to be able to restore the current search buffer to its previous state.
In case of Info this means going to the Info node where the previous
search point was located.  The hook `isearch-push-state-function'
returns additional information appended to the element of the
search status stack.  And `isearch-pop-state-function' calls the
function to restore the current buffer to its previous state.

Perhaps even one hook that adds to the stack a function to restore
the current search buffer would be enough.  For example,

(defun Info-isearch-push-state-function ()
 `(lambda ()
   (Info-find-node ,Info-current-file ,Info-current-node)
   (goto-char (car (cdr (cdr cmd))))))

will add a lambda expression as 12-th element of the list pushed to the
stack and which can be called later to restore the previous Info node.

I don't know what is more preferable: two hooks or one hook with lambda.

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

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

* Re: isearch hooks
  2004-06-27 22:34                             ` Juri Linkov
@ 2004-06-28 14:57                               ` Richard Stallman
  0 siblings, 0 replies; 101+ messages in thread
From: Richard Stallman @ 2004-06-28 14:57 UTC (permalink / raw)
  Cc: emacs-devel

    The commands that move the point back to the previous search result
    restore the previous point by setting it by `goto-char' to the
    position saved in the search status stack `isearch-cmds'.  But this
    doesn't work when the current search buffer switches during the search
    like with changing the current Info node.

I see.  Yes, that makes sense.

    I don't know what is more preferable: two hooks or one hook with lambda.

I think one hook with lambda is more elegant.

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

* Re: isearch hooks (was: query-replace-interactive not documented)
  2004-06-18 20:00             ` isearch hooks (was: query-replace-interactive not documented) Juri Linkov
  2004-06-19  1:10               ` Miles Bader
  2004-06-19  3:19               ` isearch hooks (was: query-replace-interactive not documented) Richard Stallman
@ 2004-06-29  0:25               ` Stefan
  2004-06-29  1:17                 ` isearch hooks Juri Linkov
  2 siblings, 1 reply; 101+ messages in thread
From: Stefan @ 2004-06-29  0:25 UTC (permalink / raw)
  Cc: rms, emacs-devel

> +	      (if isearch-wrapped-hook
> +                  (run-hooks 'isearch-wrapped-hook)
> +                (goto-char (if isearch-forward (point-min) (point-max))))

If the hook was made buffer local it might be non-nil and yet empty.
So the test for nil-ness of isearch-wrapped-hook is wrong.


        Stefan

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

* Re: isearch hooks
  2004-06-29  0:25               ` isearch hooks (was: query-replace-interactive not documented) Stefan
@ 2004-06-29  1:17                 ` Juri Linkov
  0 siblings, 0 replies; 101+ messages in thread
From: Juri Linkov @ 2004-06-29  1:17 UTC (permalink / raw)
  Cc: rms, emacs-devel

Stefan <monnier@iro.umontreal.ca> writes:
>> +	      (if isearch-wrapped-hook
>> +                  (run-hooks 'isearch-wrapped-hook)
>> +                (goto-char (if isearch-forward (point-min) (point-max))))
>
> If the hook was made buffer local it might be non-nil and yet empty.
> So the test for nil-ness of isearch-wrapped-hook is wrong.

In the latest version posted 2004-06-25 I changed this into funcall:

-	      (goto-char (if isearch-forward (point-min) (point-max)))
+	      (if isearch-wrap-function
+		  (funcall isearch-wrap-function)
+	        (goto-char (if isearch-forward (point-min) (point-max))))

So in this case there is no problem with buffer local hooks.

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

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

end of thread, other threads:[~2004-06-29  1:17 UTC | newest]

Thread overview: 101+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-05-28 16:16 query-replace-interactive not documented Werner LEMBERG
2004-05-29 17:02 ` Richard Stallman
2004-05-29 17:37   ` Luc Teirlinck
2004-05-29 20:33     ` Juri Linkov
2004-06-11  8:19       ` Juri Linkov
2004-06-11  8:39         ` Kim F. Storm
2004-06-11  9:00         ` David Kastrup
2004-06-12  8:21           ` Juri Linkov
2004-06-12  1:50         ` Richard Stallman
2004-06-12  8:16           ` Juri Linkov
2004-06-13  0:01             ` Richard Stallman
2004-06-13  0:46               ` Miles Bader
2004-06-13  9:03               ` David Kastrup
2004-06-14 18:50                 ` Richard Stallman
2004-06-14 20:49                   ` Kim F. Storm
2004-06-14 21:20                     ` David Kastrup
2004-06-15 14:29                       ` Juri Linkov
2004-06-15 15:43                         ` David Kastrup
2004-06-15 18:17                           ` Juri Linkov
2004-06-15 20:23                             ` David Kastrup
2004-06-15 22:30                             ` Andreas Schwab
2004-06-15 22:36                               ` David Kastrup
2004-06-15 22:43                                 ` Kim F. Storm
2004-06-15 23:13                                   ` David Kastrup
2004-06-16  1:16                                     ` David Kastrup
2004-06-16  8:08                                       ` Juri Linkov
2004-06-16  9:23                                         ` David Kastrup
2004-06-16  8:02                                   ` Juri Linkov
2004-06-17  5:06                                   ` Richard Stallman
2004-06-16  8:17                               ` Juri Linkov
2004-06-16  9:01                                 ` David Kastrup
2004-06-16 17:06                                   ` Kevin Rodgers
2004-06-16  9:02                                 ` Andreas Schwab
2004-06-16  1:41                           ` Miles Bader
2004-06-16  2:01                             ` David Kastrup
2004-06-16  2:11                               ` Miles Bader
2004-06-16 16:57                           ` Richard Stallman
2004-06-15 22:25                         ` Andreas Schwab
2004-06-15 22:28                           ` Kim F. Storm
2004-06-16  9:00                             ` Juri Linkov
2004-06-16  9:25                               ` Andreas Schwab
2004-06-16  9:32                               ` David Kastrup
2004-06-16 11:30                                 ` Kim F. Storm
2004-06-16 12:15                                   ` David Kastrup
2004-06-16 14:35                                     ` David Kastrup
2004-06-16 15:23                                       ` Juri Linkov
2004-06-16 21:15                                         ` David Kastrup
2004-06-16 22:26                                           ` Kim F. Storm
2004-06-17  0:56                                             ` David Kastrup
2004-06-17 12:14                                               ` David Kastrup
2004-06-17 13:05                                                 ` Kim F. Storm
2004-06-17 13:29                                                   ` David Kastrup
2004-06-17 14:10                                                     ` Kim F. Storm
2004-06-17 14:56                                                 ` David Kastrup
2004-06-17 15:33                                                   ` Juri Linkov
2004-06-17 17:03                                                     ` David Kastrup
2004-06-18  6:43                                                       ` Juri Linkov
2004-06-18  7:13                                                         ` David Kastrup
2004-06-16 15:27                                       ` Kim F. Storm
2004-06-16 17:28                                       ` Juri Linkov
2004-06-16 21:07                                         ` David Kastrup
2004-06-17  0:47                                           ` David Kastrup
2004-06-17 23:05                                           ` Richard Stallman
2004-06-18  6:55                                             ` Juri Linkov
2004-06-19  3:19                                               ` Richard Stallman
2004-06-19  7:00                                                 ` David Kastrup
2004-06-20 19:18                                                   ` Richard Stallman
2004-06-20 21:05                                                     ` David Kastrup
2004-06-21  9:31                                                       ` Richard Stallman
2004-06-21  9:50                                                         ` David Kastrup
2004-06-22 23:16                                                           ` Richard Stallman
2004-06-25 23:12                                                         ` Juri Linkov
2004-06-26  7:34                                                           ` David Kastrup
2004-06-26 16:18                                                             ` Juri Linkov
2004-06-27 17:41                                                           ` Richard Stallman
2004-06-21  9:31                                                       ` Richard Stallman
2004-06-21  9:38                                                         ` David Kastrup
2004-06-22 23:17                                                           ` Richard Stallman
2004-06-22 23:20                                                             ` David Kastrup
2004-06-17  5:07                                 ` Richard Stallman
2004-06-14 16:59               ` Juri Linkov
2004-06-12  8:21           ` David Kastrup
2004-05-30 19:41     ` Richard Stallman
2004-05-30 22:00       ` Luc Teirlinck
2004-06-08  6:55       ` Juri Linkov
2004-06-11  8:22         ` Juri Linkov
2004-06-12  1:50           ` Richard Stallman
2004-06-18 20:00             ` isearch hooks (was: query-replace-interactive not documented) Juri Linkov
2004-06-19  1:10               ` Miles Bader
2004-06-19 18:09                 ` isearch hooks Juri Linkov
2004-06-19  3:19               ` isearch hooks (was: query-replace-interactive not documented) Richard Stallman
2004-06-19 18:36                 ` isearch hooks Juri Linkov
2004-06-20 19:18                   ` Richard Stallman
2004-06-21 21:56                     ` Juri Linkov
2004-06-22 23:17                       ` Richard Stallman
2004-06-25 18:07                         ` Juri Linkov
2004-06-27 17:41                           ` Richard Stallman
2004-06-27 22:34                             ` Juri Linkov
2004-06-28 14:57                               ` Richard Stallman
2004-06-29  0:25               ` isearch hooks (was: query-replace-interactive not documented) Stefan
2004-06-29  1:17                 ` isearch hooks 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).