Subject: bug#8161: 24.0.50; query-replace-regexp fails with interactive replacement text

From: Lawrence Mitchell <[email-masked]>
Date: Thu, 03 Mar 2011 16:21:47 +0000

Suvayu Ali wrote:
> Hi Emacs devs,

> I wanted to replace interactively all numbers in the text of an document
> with the number in words, so I tried:

> `C-M-% [0-9]+ RET \? RET'

> But this gives me an error like this:

>> Debugger entered--Lisp error: (error "Invalid use of `\\' in
>> replacement text") replace-match("\\?" nil nil #("1" 0 1 (fontified
>> t)) nil) match-substitute-replacement("\\?" nil nil)
>>   perform-replace("[0-9]+" "\\?" t t nil nil nil nil nil)
>>   query-replace-regexp("[0-9]+" "\\?" nil nil nil)
>>   call-interactively(query-replace-regexp nil nil)

> Since the doc string of `query-replace-regexp' says the following:

This has been broken since

Author: Juri Linkov <[email-masked]>
Date:   Sat Nov 10 21:48:46 2007 +0000

    (query-replace-show-replacement): New defcustom.
    (perform-replace): Use `match-substitute-replacement' if
    `query-replace-show-replacement' is non-nil.

replace-match (used by match-substitute-replacement) doesn't know
about \? and therefore barfs.

This patch just passes \\? unchanged through replace-match.  I'm
not sure if this is a reasonable fix, although minimal testing
suggests it all works correctly.

diff --git a/src/search.c b/src/search.c
index 1e2036f..c9fd71b 100644
--- a/src/search.c
+++ b/src/search.c
@@ -2373,6 +2373,7 @@ Otherwise treat `\\' as special:
   `\\N' means substitute what matched the Nth `\\(...\\)'.
        If Nth parens didn't match, substitute nothing.
   `\\\\' means insert one `\\'.
+  `\\?' (as in `query-replace-regexp') is passed through unchanged.
 Case conversion does not apply to these substitutions.
 
 FIXEDCASE and LITERAL are optional arguments.
@@ -2575,6 +2576,8 @@ since only regular expressions have distinguished subexpressions.  */)
 		    }
 		  else if (c == '\\')
 		    delbackslash = 1;
+                  else if (c == '?')
+                      ;         /* do nothing (dealt with at lisp level) */
 		  else
 		    error ("Invalid use of `\\' in replacement text");
 		}

Lawrence
-- 
Lawrence Mitchell <[email-masked]>