GNU bug report logs - #19383
25.0.50; query-replace-regexp becomes unusable when using lisp expressions for replacement

Previous Next

Package: emacs;

Reported by: Dima Kogan <dima <at> secretsauce.net>

Date: Mon, 15 Dec 2014 09:20:02 UTC

Severity: normal

Found in version 25.0.50

Done: Juri Linkov <juri <at> linkov.net>

Bug is archived. No further changes may be made.

Full log


Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Dima Kogan <dima <at> secretsauce.net>
To: bug-gnu-emacs <at> gnu.org
Subject: 25.0.50;
 query-replace-regexp becomes unusable when using lisp expressions for
 replacement
Date: Mon, 15 Dec 2014 01:01:28 -0800
Hi.

I'm using a bleeding-edge emacs build, compiled from latest source as of
Dec 14. There's a regression in query-replace-regexp where under some
conditions it becomes unable to parse its history, and becomes unusable.

Here's a recipe. Deviating from the exact steps can make the failure not
occur, but I do see this in everyday use, so this isn't exactly a corner
case.

1. Create a file called /tmp/dat. I don't think the contents are super
important. I have

0001
0002
0003
0004
0005
0006
0007
0008

2. emacs -Q /tmp/dat

3. C-M-%
   ^.
   <return>
   \,(concat \#&)
   <return>

   Here we try to do a replacement, but there's an error: (concat ...)
   expects a string, but \#& is a number, and emacs complains. This is
   fine.

4. C-M-%
   <up>
   <end>
   <left>
   <left>
   <backspace>
   <return>
   SPC

   We run another replacement. We pull the previous one from the
   history, and manually remove the # to fix the complaint. \& is a
   string, as desired. We then replace the first match by presing SPC

5. M-%

   Error!

After step 5, trying to M-% or C-M-% always fails with

 mapconcat: Wrong type argument: number-or-marker-p, replace-eval-replacement

This is irreparable without dipping into lisp. Resetting the history
fixes it for the session: (setq query-replace-defaults nil)

When broken, the value of query-replace-defaults is

 (("" replace-eval-replacement replace-quote (concat (match-string 0))) ("^." . "\\,(concat \\#&)"))

and the value of query-replace-history is

 ((replace-eval-replacement replace-quote (concat (match-string 0))) "" "\\,(concat \\#&)" "^.")

The backtrace looks like this:

 Debugger entered--Lisp error: (wrong-type-argument number-or-marker-p replace-eval-replacement)
   isearch-text-char-description(replace-eval-replacement)
   mapconcat(isearch-text-char-description (replace-eval-replacement replace-quote (concat (match-string 0))) "")
   query-replace-descr((replace-eval-replacement replace-quote (concat (match-string 0))))
   #[(from-to) "\302@!	\302A!Q\207" [from-to separator query-replace-descr] 4](("" replace-eval-replacement replace-quote (concat (match-string 0))))
   mapcar(#[(from-to) "\302@!	\302A!Q\207" [from-to separator query-replace-descr] 4] (("" replace-eval-replacement replace-quote (concat (match-string 0))) ("^." . "\\,(concat \\#&)")))
   query-replace-read-from("Query replace" nil)
   query-replace-read-args("Query replace" nil)
   (let ((common (query-replace-read-args (concat "Query replace" (if current-prefix-arg (if (eq current-prefix-arg ...) " backward" " word") "") (if (and transient-mark-mode mark-active) " in region" "")) nil))) (list (nth 0 common) (nth 1 common) (nth 2 common) (if (and transient-mark-mode mark-active) (region-beginning)) (if (and transient-mark-mode mark-active) (region-end)) (nth 3 common)))
   call-interactively(query-replace nil nil)
   command-execute(query-replace)

The issue is that isearch-text-char-description expects a string
argument, but it's getting bits of that s-expression; specifically
'replace-eval-replacement. I haven't looked further, and I don't know if
this value of the history variables is wrong, or if their parsing is
incorrect in some way.

Thanks




This bug report was last modified 10 years and 164 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.