unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
* bug#31492: 26.1; query-replace-regexp undo fails in regexps w/o printable chars
@ 2018-05-18 13:27 Tino Calancha
  2018-05-18 14:16 ` Eli Zaretskii
  0 siblings, 1 reply; 17+ messages in thread
From: Tino Calancha @ 2018-05-18 13:27 UTC (permalink / raw)
  To: 31492


emacs -Q

< C-M-% \b RET foo RET TAB TAB TAB
U ; undo all replacements
;; Nothing is undid :-(

--8<-----------------------------cut here---------------start------------->8---
commit f1ee02d0c0bef4534c895559eb53b1ac0ecfb752
Author: Tino Calancha <tino.calancha@gmail.com>
Date:   Fri May 18 22:19:18 2018 +0900

    Fix corner case in query-replace-regexp undo
    
    * lisp/replace.el (perform-replace): Handle the case of a regexp
    not having printable characters (Bug#31492).
    
    * test/lisp/replace-tests.el (query-replace-undo-bug31492): Add test.

diff --git a/lisp/replace.el b/lisp/replace.el
index 3503b656d9..526a40d230 100644
--- a/lisp/replace.el
+++ b/lisp/replace.el
@@ -2692,7 +2692,9 @@ perform-replace
                                    (setq real-match-data
                                          (save-excursion
                                            (goto-char (match-beginning 0))
-                                           (looking-at search-string)
+                                           (if (/= (match-beginning 0) (match-end 0))
+					       (looking-at search-string)
+					     (looking-back search-string (- (point) (length search-string))))
                                            (match-data t (nth 2 elt)))
                                          noedit
                                          (replace-match-maybe-edit
diff --git a/test/lisp/replace-tests.el b/test/lisp/replace-tests.el
index 40a1a31cf7..5c0ec2aa1c 100644
--- a/test/lisp/replace-tests.el
+++ b/test/lisp/replace-tests.el
@@ -399,5 +399,25 @@ replace-tests--query-replace-undo
       ;; After undo text must be the same.
       (should (string= text (buffer-string))))))
 
+(ert-deftest query-replace-undo-bug31492 ()
+  "Test for https://debbugs.gnu.org/31492 ."
+  (let ((text "a\nb\nc\n")
+        (count 0)
+        (inhibit-message t))
+    (with-temp-buffer
+      (insert text)
+      (goto-char 1)
+      (cl-letf (((symbol-function 'read-event)
+                 (lambda (&rest args)
+                   (cl-incf count)
+                   (let ((val (pcase count
+                                ((or 1 2) ?\s) ; replace current and go next
+                                (3 ?U) ; undo-all
+                                (_ ?q)))) ; exit
+                     val))))
+        (perform-replace "^\\|\b\\|$" "foo" t t nil))
+      ;; After undo text must be the same.
+      (should (string= text (buffer-string))))))
+
 
 ;;; replace-tests.el ends here
--8<-----------------------------cut here---------------end--------------->8---

In GNU Emacs 26.1 (build 6, x86_64-pc-linux-gnu, GTK+ Version 3.22.11)
 of 2018-05-18 built on calancha-pc
Repository revision: 73bc6f8693fcbb98b41ee67ab35a4dd8c3940355





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

* bug#31492: 26.1; query-replace-regexp undo fails in regexps w/o printable chars
  2018-05-18 13:27 bug#31492: 26.1; query-replace-regexp undo fails in regexps w/o printable chars Tino Calancha
@ 2018-05-18 14:16 ` Eli Zaretskii
  2018-05-18 14:22   ` Tino Calancha
  0 siblings, 1 reply; 17+ messages in thread
From: Eli Zaretskii @ 2018-05-18 14:16 UTC (permalink / raw)
  To: Tino Calancha; +Cc: 31492

> From: Tino Calancha <tino.calancha@gmail.com>
> Date: Fri, 18 May 2018 22:27:36 +0900
> 
> emacs -Q
> 
> < C-M-% \b RET foo RET TAB TAB TAB
> U ; undo all replacements
> ;; Nothing is undid :-(

I'm probably missing something, because I cannot reproduce the problem
(and therefore don't understand the solution).  When I repeat what you
show above, I get "replaced 0 occurrences", and therefore there's
nothing to undo in the first place...

I guess the explanation is in what does "<" mean and, more
importantly, what did you actually type instead of "\b".

Or maybe some command is missing before the recipe begins?

TIA





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

* bug#31492: 26.1; query-replace-regexp undo fails in regexps w/o printable chars
  2018-05-18 14:16 ` Eli Zaretskii
@ 2018-05-18 14:22   ` Tino Calancha
  2018-05-18 15:07     ` Eli Zaretskii
  0 siblings, 1 reply; 17+ messages in thread
From: Tino Calancha @ 2018-05-18 14:22 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: 31492, Tino Calancha



On Fri, 18 May 2018, Eli Zaretskii wrote:

>> From: Tino Calancha <tino.calancha@gmail.com>
>> Date: Fri, 18 May 2018 22:27:36 +0900
>>
>> emacs -Q
>>
>> < C-M-% \b RET foo RET TAB TAB TAB
>> U ; undo all replacements
>> ;; Nothing is undid :-(
>
> I'm probably missing something, because I cannot reproduce the problem
> I guess the explanation is in what does "<" mean and, more
'<' stands for `beginning-of-buffer'.  Then you have text to replace in 
the *scratch* buffer.  Otherwise you at the end of the buffer and my
regexp cannot match.





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

* bug#31492: 26.1; query-replace-regexp undo fails in regexps w/o printable chars
  2018-05-18 14:22   ` Tino Calancha
@ 2018-05-18 15:07     ` Eli Zaretskii
  2018-05-19  1:46       ` Tino Calancha
  0 siblings, 1 reply; 17+ messages in thread
From: Eli Zaretskii @ 2018-05-18 15:07 UTC (permalink / raw)
  To: Tino Calancha; +Cc: 31492

> From: Tino Calancha <tino.calancha@gmail.com>
> Date: Fri, 18 May 2018 23:22:13 +0900 (JST)
> cc: Tino Calancha <tino.calancha@gmail.com>, 31492@debbugs.gnu.org
> 
> >> emacs -Q
> >>
> >> < C-M-% \b RET foo RET TAB TAB TAB
> >> U ; undo all replacements
> >> ;; Nothing is undid :-(
> >
> > I'm probably missing something, because I cannot reproduce the problem
> > I guess the explanation is in what does "<" mean and, more
> '<' stands for `beginning-of-buffer'.  Then you have text to replace in 
> the *scratch* buffer.  Otherwise you at the end of the buffer and my
> regexp cannot match.

Sorry, I'm still in the dark.  After "emacs -Q", the current buffer is
*scratch*, and in that buffer, typing '<' inserts that character into
the buffer, it doesn't invoke beginning-of-buffer.  And 'U' doesn't
undo, either.  These are self-inserting characters in Lisp Interaction
mode.

What am I missing?





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

* bug#31492: 26.1; query-replace-regexp undo fails in regexps w/o printable chars
  2018-05-18 15:07     ` Eli Zaretskii
@ 2018-05-19  1:46       ` Tino Calancha
  2018-05-19  7:50         ` Eli Zaretskii
  0 siblings, 1 reply; 17+ messages in thread
From: Tino Calancha @ 2018-05-19  1:46 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: 31492, Tino Calancha



On Fri, 18 May 2018, Eli Zaretskii wrote:

>> From: Tino Calancha <tino.calancha@gmail.com>
>> Date: Fri, 18 May 2018 23:22:13 +0900 (JST)
>> cc: Tino Calancha <tino.calancha@gmail.com>, 31492@debbugs.gnu.org
>>
>>>> emacs -Q
>>>>
>>>> < C-M-% \b RET foo RET TAB TAB TAB
>>>> U ; undo all replacements
>>>> ;; Nothing is undid :-(
>>>
>> '<' stands for `beginning-of-buffer'.
> Sorry, I'm still in the dark. Typing '<' inserts that character
Opps... Sorry!  That should read 'M-<'.
And the TAB's should read SPC.

The correct recipe is:

M-<
C-M-% \b RET foo RET SPC SPC
U
;; All 'foo' keep there :-(

This happen because the regexp "\b" has any printable character.
If we try instead:

M-<
C-M-% is\b RET foo RET SPC SPC
U
;; Now all 'foo' are gone :-)






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

* bug#31492: 26.1; query-replace-regexp undo fails in regexps w/o printable chars
  2018-05-19  1:46       ` Tino Calancha
@ 2018-05-19  7:50         ` Eli Zaretskii
  2018-05-19 14:28           ` Tino Calancha
  0 siblings, 1 reply; 17+ messages in thread
From: Eli Zaretskii @ 2018-05-19  7:50 UTC (permalink / raw)
  To: Tino Calancha; +Cc: 31492

> From: Tino Calancha <tino.calancha@gmail.com>
> Date: Sat, 19 May 2018 10:46:10 +0900 (JST)
> cc: Tino Calancha <tino.calancha@gmail.com>, 31492@debbugs.gnu.org
> 
> The correct recipe is:
> 
> M-<
> C-M-% \b RET foo RET SPC SPC
> U
> ;; All 'foo' keep there :-(

Thanks, I see the problem now.

However, isn't the root cause in replace--push-stack?  The relevant
element of the replacement stack (whose structure, btw, seems not to
be documented anywhere), is (4 4 *scratch*), whereas I'd expect to see
(1 4 *scratch) instead, because the replacement was at position 1;
then setting match-data from this would DTRT.

IOW, I'm afraid the looking-back solution is ad-hoc, and might not
work in general, because the real problem is elsewhere.  WDYT?

> This happen because the regexp "\b" has any printable character.

Why does it matter for \b to match a non-empty string?  The undo-all
command matches text against the _replacement_ string, not against the
original search string.  And the replacement string, "foo", is not
empty.  The problem here, AFAICT, is that we are looking for it in the
wrong place, and that happens because the replacement stack tells us
to look at position 4 instead of position 1.  Right?

> If we try instead:
> 
> M-<
> C-M-% is\b RET foo RET SPC SPC
> U
> ;; Now all 'foo' are gone :-)

Yes, because in this case the replacement stack has the correct data.





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

* bug#31492: 26.1; query-replace-regexp undo fails in regexps w/o printable chars
  2018-05-19  7:50         ` Eli Zaretskii
@ 2018-05-19 14:28           ` Tino Calancha
  2018-05-20  9:29             ` Eli Zaretskii
  0 siblings, 1 reply; 17+ messages in thread
From: Tino Calancha @ 2018-05-19 14:28 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: 31492

Eli Zaretskii <eliz@gnu.org> writes:

> Thanks, I see the problem now.
>
> However, isn't the root cause in replace--push-stack?
I am not sure; there is something else (see below).

> The relevant
> element of the replacement stack (whose structure, btw, seems not to
> be documented anywhere), is (4 4 *scratch*), whereas I'd expect to see
> (1 4 *scratch) instead, because the replacement was at position 1;
> then setting match-data from this would DTRT.
Yes, that is the logic.  The thing is, for some unknown reason to me,
the reported match-data is inexact when there are no printable chars
in the regexp (maybe it's expected and I am wrong on my assumptions).

> IOW, I'm afraid the looking-back solution is ad-hoc, and might not
> work in general, because the real problem is elsewhere.  WDYT?
Look what happen in these examples:

(with-temp-buffer
  (insert "foo")
  (goto-char 1)
  (progn (re-search-forward "o$" nil t)
	 (save-match-data (replace-match "oZZZ"))
	 (list (point) (match-beginning 0) (match-end 0))))
=> (7 3 7)

;; Now, a regexp with no printable chars

(with-temp-buffer
  (insert "foo")
  (goto-char 1)
  (progn (re-search-forward "$" nil t)
	 (save-match-data (replace-match "ZZZ"))
	 (list (point) (match-beginning 0) (match-end 0))))
=> (7 7 7)
;; If this would be (7 4 7), then we could use `looking-at'; we are to
;; the right of the replacement, then we use `looking-back'.
  

;; But the match was at 4 not at 7
(with-temp-buffer
  (insert "foo")
  (goto-char 1)
  (progn (re-search-forward "$" nil t)
	 (list (point) (match-beginning 0) (match-end 0))))
=> (4 4 4)
;; We lost the information about the beginning of the match when
;; the regexps lack of printable characters.





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

* bug#31492: 26.1; query-replace-regexp undo fails in regexps w/o printable chars
  2018-05-19 14:28           ` Tino Calancha
@ 2018-05-20  9:29             ` Eli Zaretskii
  2018-05-20 11:51               ` Tino Calancha
  0 siblings, 1 reply; 17+ messages in thread
From: Eli Zaretskii @ 2018-05-20  9:29 UTC (permalink / raw)
  To: Tino Calancha; +Cc: 31492

> From: Tino Calancha <tino.calancha@gmail.com>
> Cc: 31492@debbugs.gnu.org
> Date: Sat, 19 May 2018 23:28:35 +0900
> 
> > The relevant
> > element of the replacement stack (whose structure, btw, seems not to
> > be documented anywhere), is (4 4 *scratch*), whereas I'd expect to see
> > (1 4 *scratch) instead, because the replacement was at position 1;
> > then setting match-data from this would DTRT.
> Yes, that is the logic.  The thing is, for some unknown reason to me,
> the reported match-data is inexact when there are no printable chars
> in the regexp (maybe it's expected and I am wrong on my assumptions).

The reason for that is that match-data is recorded as markers, and so
the positions move if text is inserted.  In your example, the position
of $ moved due to insertion, so the marker's position was updated as
part of the replacement.

> (with-temp-buffer
>   (insert "foo")
>   (goto-char 1)
>   (progn (re-search-forward "$" nil t)
> 	 (save-match-data (replace-match "ZZZ"))
> 	 (list (point) (match-beginning 0) (match-end 0))))
> => (7 7 7)
> ;; If this would be (7 4 7), then we could use `looking-at'; we are to
> ;; the right of the replacement, then we use `looking-back'.
>   
> 
> ;; But the match was at 4 not at 7
> (with-temp-buffer
>   (insert "foo")
>   (goto-char 1)
>   (progn (re-search-forward "$" nil t)
> 	 (list (point) (match-beginning 0) (match-end 0))))
> => (4 4 4)

Right, and so I submit that the problem is where the replacement stack
is updated: it should account for these subtleties and adjust the
stack positions accordingly, since it has the opportunity to look at
the match position before the matched text is replaced.  It is IMO
suboptimal to make these adjustments where the stack is used, because
you've lost the information about the actual match point, and you are
deducing it using heuristics, which I'm not sure is 100% reliable.

Thanks.





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

* bug#31492: 26.1; query-replace-regexp undo fails in regexps w/o printable chars
  2018-05-20  9:29             ` Eli Zaretskii
@ 2018-05-20 11:51               ` Tino Calancha
  2018-05-20 11:59                 ` Eli Zaretskii
  0 siblings, 1 reply; 17+ messages in thread
From: Tino Calancha @ 2018-05-20 11:51 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: 31492

Eli Zaretskii <eliz@gnu.org> writes:

>> > The relevant
>> > element of the replacement stack (whose structure, btw, seems not to
>> > be documented anywhere), is (4 4 *scratch*), whereas I'd expect to see
>> > (1 4 *scratch) instead, because the replacement was at position 1;
>> > then setting match-data from this would DTRT.
>> Yes, that is the logic.  The thing is, for some unknown reason to me,
>> the reported match-data is inexact when there are no printable chars
>> in the regexp (maybe it's expected and I am wrong on my assumptions).
>
> The reason for that is that match-data is recorded as markers, and so
> the positions move if text is inserted.  In your example, the position
> of $ moved due to insertion, so the marker's position was updated as
> part of the replacement.
Yeah, I have noticed that this afternoon.

> Right, and so I submit that the problem is where the replacement stack
> is updated: it should account for these subtleties and adjust the
> stack positions accordingly, since it has the opportunity to look at
> the match position before the matched text is replaced.
I have a different approach:
If the problem arise from using markers istead of integers, then how
about we just use integers?

Please take a look:
--8<-----------------------------cut here---------------start------------->8---
commit cf13cb2dff040571b289e2ba8dcc0008394ffe3d
Author: Tino Calancha <tino.calancha@gmail.com>
Date:   Sun May 20 20:43:30 2018 +0900

    Fix corner case in query-replace-regexp undo
    
    This commit fixes Bug#31492.
    * lisp/replace.el(replace-save-match-data): New macro.
    (replace-match-maybe-edit): Preserve match data.
    
    * test/lisp/replace-tests.el (query-replace-undo-bug31492): Add test.

diff --git a/lisp/replace.el b/lisp/replace.el
index 3503b656d9..7d49b977fd 100644
--- a/lisp/replace.el
+++ b/lisp/replace.el
@@ -2184,6 +2184,16 @@ replace-match-data
 		  new)))
       (match-data integers reuse t)))
 
+(defmacro replace-save-match-data (&rest body)
+  "Like `save-match-data', but it uses integers instead of markers.
+The value returned is the value of the last form in BODY."
+  (declare (indent 0) (debug t))
+  (let ((match (gensym "match-data")))
+    `(let ((,match (match-data 'integers)))
+       (unwind-protect
+           ,@body
+         (set-match-data ,match)))))
+
 (defun replace-match-maybe-edit (newtext fixedcase literal noedit match-data
                                  &optional backward)
   "Make a replacement with `replace-match', editing `\\?'.
@@ -2213,7 +2223,7 @@ replace-match-maybe-edit
                                   nil match-data match-data))))
 	    noedit nil)))
   (set-match-data match-data)
-  (replace-match newtext fixedcase literal)
+  (replace-save-match-data (replace-match newtext fixedcase literal))
   ;; `replace-match' leaves point at the end of the replacement text,
   ;; so move point to the beginning when replacing backward.
   (when backward (goto-char (nth 0 match-data)))
diff --git a/test/lisp/replace-tests.el b/test/lisp/replace-tests.el
index 40a1a31cf7..40ee838e67 100644
--- a/test/lisp/replace-tests.el
+++ b/test/lisp/replace-tests.el
@@ -399,5 +399,25 @@ replace-tests--query-replace-undo
       ;; After undo text must be the same.
       (should (string= text (buffer-string))))))
 
+(ert-deftest query-replace-undo-bug31492 ()
+  "Test for https://debbugs.gnu.org/31492 ."
+  (let ((text "a\nb\nc\n")
+        (count 0)
+        (inhibit-message t))
+    (with-temp-buffer
+      (insert text)
+      (goto-char 1)
+      (cl-letf (((symbol-function 'read-event)
+                 (lambda (&rest args)
+                   (cl-incf count)
+                   (let ((val (pcase count
+                                ((or 1 2) ?\s) ; replace current and go next
+                                (3 ?U) ; undo-all
+                                (_ ?q)))) ; exit
+                     val))))
+        (perform-replace "^\\|\b\\|$" "foo" t t nil))
+      ;; After undo text must be the same.
+      (should (string= text (buffer-string))))))
+
 
 ;;; replace-tests.el ends here

--8<-----------------------------cut here---------------end--------------->8---





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

* bug#31492: 26.1; query-replace-regexp undo fails in regexps w/o printable chars
  2018-05-20 11:51               ` Tino Calancha
@ 2018-05-20 11:59                 ` Eli Zaretskii
  2018-05-20 12:06                   ` Tino Calancha
  0 siblings, 1 reply; 17+ messages in thread
From: Eli Zaretskii @ 2018-05-20 11:59 UTC (permalink / raw)
  To: Tino Calancha; +Cc: 31492

> From: Tino Calancha <tino.calancha@gmail.com>
> Cc: 31492@debbugs.gnu.org
> Date: Sun, 20 May 2018 20:51:10 +0900
> 
> If the problem arise from using markers istead of integers, then how
> about we just use integers?

Does this work with '^' and 'C-e', if they change text before a match
that was already replaced and recorded?





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

* bug#31492: 26.1; query-replace-regexp undo fails in regexps w/o printable chars
  2018-05-20 11:59                 ` Eli Zaretskii
@ 2018-05-20 12:06                   ` Tino Calancha
  2018-05-20 12:48                     ` Eli Zaretskii
  0 siblings, 1 reply; 17+ messages in thread
From: Tino Calancha @ 2018-05-20 12:06 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: 31492, Tino Calancha



On Sun, 20 May 2018, Eli Zaretskii wrote:

>> From: Tino Calancha <tino.calancha@gmail.com>
>> Cc: 31492@debbugs.gnu.org
>> Date: Sun, 20 May 2018 20:51:10 +0900
>>
>> If the problem arise from using markers istead of integers, then how
>> about we just use integers?
>
> Does this work with '^' and 'C-e', if they change text before a match
> that was already replaced and recorded?
I don't understand.  Do you have a recipe?

BTW, I found another issue in this feature.
I will open another report.





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

* bug#31492: 26.1; query-replace-regexp undo fails in regexps w/o printable chars
  2018-05-20 12:06                   ` Tino Calancha
@ 2018-05-20 12:48                     ` Eli Zaretskii
  2018-05-20 13:46                       ` Tino Calancha
  0 siblings, 1 reply; 17+ messages in thread
From: Eli Zaretskii @ 2018-05-20 12:48 UTC (permalink / raw)
  To: Tino Calancha; +Cc: 31492

> From: Tino Calancha <tino.calancha@gmail.com>
> Date: Sun, 20 May 2018 21:06:21 +0900 (JST)
> cc: Tino Calancha <tino.calancha@gmail.com>, 31492@debbugs.gnu.org
> 
> >> If the problem arise from using markers istead of integers, then how
> >> about we just use integers?
> >
> > Does this work with '^' and 'C-e', if they change text before a match
> > that was already replaced and recorded?
> I don't understand.  Do you have a recipe?

Not a recipe, an idea: I'm bothered by the possibility of the saved
positions becoming outdated if something changes text before the saved
positions.  Markers would move with the text, but positions won't.

The question is: is such a situation possible?





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

* bug#31492: 26.1; query-replace-regexp undo fails in regexps w/o printable chars
  2018-05-20 12:48                     ` Eli Zaretskii
@ 2018-05-20 13:46                       ` Tino Calancha
  2018-05-20 15:47                         ` Eli Zaretskii
  0 siblings, 1 reply; 17+ messages in thread
From: Tino Calancha @ 2018-05-20 13:46 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: 31492, Tino Calancha



On Sun, 20 May 2018, Eli Zaretskii wrote:

> Not a recipe, an idea: I'm bothered by the possibility of the saved
> positions becoming outdated if something changes text before the saved
> positions.  Markers would move with the text, but positions won't.
>
> The question is: is such a situation possible?
Everything is possible (except, possibly, that I find a new job).

You know what they say: In the risk is the pleasure. Otherwise we
can use the first patch; the one with the test:
(/= (match-beginning 0) (match-end 0))





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

* bug#31492: 26.1; query-replace-regexp undo fails in regexps w/o printable chars
  2018-05-20 13:46                       ` Tino Calancha
@ 2018-05-20 15:47                         ` Eli Zaretskii
  2018-05-21  1:51                           ` Tino Calancha
  0 siblings, 1 reply; 17+ messages in thread
From: Eli Zaretskii @ 2018-05-20 15:47 UTC (permalink / raw)
  To: Tino Calancha; +Cc: 31492, tino.calancha

> From: Tino Calancha <tino.calancha@gmail.com>
> Date: Sun, 20 May 2018 22:46:05 +0900 (JST)
> cc: Tino Calancha <tino.calancha@gmail.com>, 31492@debbugs.gnu.org
> 
> > The question is: is such a situation possible?
> Everything is possible (except, possibly, that I find a new job).

Actually, I know a few things that are even less possible than that.

> You know what they say: In the risk is the pleasure. Otherwise we
> can use the first patch; the one with the test:
> (/= (match-beginning 0) (match-end 0))

No, I like the 2nd one better.

Thanks.





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

* bug#31492: 26.1; query-replace-regexp undo fails in regexps w/o printable chars
  2018-05-20 15:47                         ` Eli Zaretskii
@ 2018-05-21  1:51                           ` Tino Calancha
  2018-05-21 15:05                             ` Eli Zaretskii
  0 siblings, 1 reply; 17+ messages in thread
From: Tino Calancha @ 2018-05-21  1:51 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: 31492

Eli Zaretskii <eliz@gnu.org> writes:


>> we can use the first patch; the one with the test:
>> (/= (match-beginning 0) (match-end 0))
>
> No, I like the 2nd one better.
Following patch is equivalent to the 2nd and its 1-liner
(excluded clarification comments):
--8<-----------------------------cut here---------------start------------->8---
commit 565c30caa8d5b015fd34446bd8900c55b2f67544
Author: Tino Calancha <tino.calancha@gmail.com>
Date:   Mon May 21 10:46:50 2018 +0900

    Fix corner case in query-replace-regexp undo
    
    This commit fixes Bug#31492.
    * lisp/replace.el (replace-match-maybe-edit): Preserve match data.
    
    * test/lisp/replace-tests.el (query-replace-undo-bug31492): Add test.

diff --git a/lisp/replace.el b/lisp/replace.el
index 3503b656d9..a17dd19b0d 100644
--- a/lisp/replace.el
+++ b/lisp/replace.el
@@ -2214,6 +2214,10 @@ replace-match-maybe-edit
 	    noedit nil)))
   (set-match-data match-data)
   (replace-match newtext fixedcase literal)
+  ;; `query-replace' undo feature needs the beginning of the match position,
+  ;; but `replace-match' may change it, for instance, with a regexp like "^".
+  ;; Ensure that this function preserves the match data (Bug#31492).
+  (set-match-data match-data)
   ;; `replace-match' leaves point at the end of the replacement text,
   ;; so move point to the beginning when replacing backward.
   (when backward (goto-char (nth 0 match-data)))
diff --git a/test/lisp/replace-tests.el b/test/lisp/replace-tests.el
index 40a1a31cf7..40ee838e67 100644
--- a/test/lisp/replace-tests.el
+++ b/test/lisp/replace-tests.el
@@ -399,5 +399,25 @@ replace-tests--query-replace-undo
       ;; After undo text must be the same.
       (should (string= text (buffer-string))))))
 
+(ert-deftest query-replace-undo-bug31492 ()
+  "Test for https://debbugs.gnu.org/31492 ."
+  (let ((text "a\nb\nc\n")
+        (count 0)
+        (inhibit-message t))
+    (with-temp-buffer
+      (insert text)
+      (goto-char 1)
+      (cl-letf (((symbol-function 'read-event)
+                 (lambda (&rest args)
+                   (cl-incf count)
+                   (let ((val (pcase count
+                                ((or 1 2) ?\s) ; replace current and go next
+                                (3 ?U) ; undo-all
+                                (_ ?q)))) ; exit
+                     val))))
+        (perform-replace "^\\|\b\\|$" "foo" t t nil))
+      ;; After undo text must be the same.
+      (should (string= text (buffer-string))))))
+
 
 ;;; replace-tests.el ends here

--8<-----------------------------cut here---------------end--------------->8---





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

* bug#31492: 26.1; query-replace-regexp undo fails in regexps w/o printable chars
  2018-05-21  1:51                           ` Tino Calancha
@ 2018-05-21 15:05                             ` Eli Zaretskii
  2018-05-23  9:22                               ` Tino Calancha
  0 siblings, 1 reply; 17+ messages in thread
From: Eli Zaretskii @ 2018-05-21 15:05 UTC (permalink / raw)
  To: Tino Calancha; +Cc: 31492

> From: Tino Calancha <tino.calancha@gmail.com>
> Cc: 31492@debbugs.gnu.org
> Date: Mon, 21 May 2018 10:51:43 +0900
> 
> Eli Zaretskii <eliz@gnu.org> writes:
> 
> 
> >> we can use the first patch; the one with the test:
> >> (/= (match-beginning 0) (match-end 0))
> >
> > No, I like the 2nd one better.
> Following patch is equivalent to the 2nd and its 1-liner
> (excluded clarification comments):

Thanks, LGTM.  If no comments emerge in a couple of days, please push.





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

* bug#31492: 26.1; query-replace-regexp undo fails in regexps w/o printable chars
  2018-05-21 15:05                             ` Eli Zaretskii
@ 2018-05-23  9:22                               ` Tino Calancha
  0 siblings, 0 replies; 17+ messages in thread
From: Tino Calancha @ 2018-05-23  9:22 UTC (permalink / raw)
  To: 31492-done

Eli Zaretskii <eliz@gnu.org> writes:

>> From: Tino Calancha <tino.calancha@gmail.com>
>> Cc: 31492@debbugs.gnu.org
>> Date: Mon, 21 May 2018 10:51:43 +0900
>> Following patch is equivalent to the 2nd and its 1-liner
>> (excluded clarification comments):
>
> Thanks, LGTM.  If no comments emerge in a couple of days, please push.
Pushed into master branch as 'Fix corner case in query-replace-regexp
undo'
(bab73230d1be1fe394b7269c1365ef6fb1a5d9b3)





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

end of thread, other threads:[~2018-05-23  9:22 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-05-18 13:27 bug#31492: 26.1; query-replace-regexp undo fails in regexps w/o printable chars Tino Calancha
2018-05-18 14:16 ` Eli Zaretskii
2018-05-18 14:22   ` Tino Calancha
2018-05-18 15:07     ` Eli Zaretskii
2018-05-19  1:46       ` Tino Calancha
2018-05-19  7:50         ` Eli Zaretskii
2018-05-19 14:28           ` Tino Calancha
2018-05-20  9:29             ` Eli Zaretskii
2018-05-20 11:51               ` Tino Calancha
2018-05-20 11:59                 ` Eli Zaretskii
2018-05-20 12:06                   ` Tino Calancha
2018-05-20 12:48                     ` Eli Zaretskii
2018-05-20 13:46                       ` Tino Calancha
2018-05-20 15:47                         ` Eli Zaretskii
2018-05-21  1:51                           ` Tino Calancha
2018-05-21 15:05                             ` Eli Zaretskii
2018-05-23  9:22                               ` Tino Calancha

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