* bug#21663: 25.0.50; isearch-edit-string dont resume multi isearches
[not found] ` <handler.21663.B.144453929427612.ack@debbugs.gnu.org>
@ 2015-10-13 5:18 ` Tino Calancha
2015-10-13 22:04 ` Juri Linkov
0 siblings, 1 reply; 27+ messages in thread
From: Tino Calancha @ 2015-10-13 5:18 UTC (permalink / raw)
To: 21663; +Cc: Tino Calancha
[-- Attachment #1: Type: text/plain, Size: 400 bytes --]
In previous patch (isearch_3.patch) the variables are not
restored because they were bind to the same symbol name, and
multi-isearch-end will set them to nil.
In addition, multi-isearch-end need to be added again to
isearch-mode-end-hook, otherwise, even after exiting with C-g, C-s will
start a multisearch instead of a normal isearch in the current buffer.
See attached patch: isearch_4.patch
[-- Attachment #2: Type: text/plain, Size: 2034 bytes --]
diff --git a/lisp/isearch.el b/lisp/isearch.el
index 4fc9b38..617f3e7 100644
--- a/lisp/isearch.el
+++ b/lisp/isearch.el
@@ -1242,6 +1242,15 @@ with-isearch-suspended
(isearch-adjusted isearch-adjusted)
(isearch-yank-flag isearch-yank-flag)
(isearch-error isearch-error)
+ ;; multi isearch variables
+ (is-multi-isearch (or multi-isearch-buffer-list multi-isearch-file-list))
+ (multi-isearch-file-list-new multi-isearch-file-list)
+ (multi-isearch-buffer-list-new multi-isearch-buffer-list)
+ (multi-isearch-next-buffer-current-function-new multi-isearch-next-buffer-current-function)
+ (multi-isearch-current-buffer-new multi-isearch-current-buffer)
+ (isearch-push-state-function isearch-push-state-function)
+ (isearch-wrap-function isearch-wrap-function)
+ (isearch-search-fun-function isearch-search-fun-function)
;;; Don't bind this. We want isearch-search, below, to set it.
;;; And the old value won't matter after that.
;;; (isearch-other-end isearch-other-end)
@@ -1298,12 +1307,17 @@ with-isearch-suspended
nil
isearch-word)
+ (when is-multi-isearch (add-hook 'isearch-mode-end-hook 'multi-isearch-end))
;; Copy new local values to isearch globals
(setq isearch-string isearch-new-string
isearch-message isearch-new-message
isearch-forward isearch-new-forward
isearch-word isearch-new-word
- isearch-case-fold-search isearch-new-case-fold))
+ isearch-case-fold-search isearch-new-case-fold
+ multi-isearch-file-list multi-isearch-file-list-new
+ multi-isearch-buffer-list multi-isearch-buffer-list-new
+ multi-isearch-current-buffer multi-isearch-current-buffer-new
+ multi-isearch-next-buffer-current-function multi-isearch-next-buffer-current-function-new))
;; Empty isearch-string means use default.
(when (= 0 (length isearch-string))
^ permalink raw reply related [flat|nested] 27+ messages in thread
* bug#21663: 25.0.50; isearch-edit-string dont resume multi isearches
2015-10-13 5:18 ` bug#21663: " Tino Calancha
@ 2015-10-13 22:04 ` Juri Linkov
2015-10-14 6:48 ` Tino Calancha
0 siblings, 1 reply; 27+ messages in thread
From: Juri Linkov @ 2015-10-13 22:04 UTC (permalink / raw)
To: Tino Calancha; +Cc: 21663
> In previous patch (isearch_3.patch) the variables are not
> restored because they were bind to the same symbol name, and
> multi-isearch-end will set them to nil.
Thanks, it's a safer approach to restore them explicitly.
> In addition, multi-isearch-end need to be added again to
> isearch-mode-end-hook, otherwise, even after exiting with C-g, C-s will
> start a multisearch instead of a normal isearch in the current buffer.
To avoid the need to add multi-isearch-end to isearch-mode-end-hook,
you could try to restore saved variables before calling isearch-mode.
Then multi-isearch-setup called from isearch-mode should take care of
adding multi-isearch-end to isearch-mode-end-hook when necessary
variables are already restored, i.e. when you save the variable
multi-isearch-next-buffer-function instead of
multi-isearch-next-buffer-current-function. But OTOH
multi-isearch-current-buffer still needs to be restored after
isearch-mode in the same place where you already added it in your patch.
This way restarting isearch will emulate binding local variables
multi-isearch-next-buffer-function and multi-isearch-buffer-list in
multi-isearch-buffers before starting multi-buffer search.
^ permalink raw reply [flat|nested] 27+ messages in thread
* bug#21663: 25.0.50; isearch-edit-string dont resume multi isearches
2015-10-13 22:04 ` Juri Linkov
@ 2015-10-14 6:48 ` Tino Calancha
2015-10-14 16:17 ` Juri Linkov
0 siblings, 1 reply; 27+ messages in thread
From: Tino Calancha @ 2015-10-14 6:48 UTC (permalink / raw)
To: 21663
[-- Attachment #1: Type: text/plain, Size: 969 bytes --]
Thank you Juri for your help on this.
I have tested the attached patch (isearch-5.patch)
with `multi-isearch-buffers'/`multi-isearch-files': it seems
OK now.
< To avoid the need to add multi-isearch-end to isearch-mode-end-hook,
< you could try to restore saved variables before calling isearch-mode.
< Then multi-isearch-setup called from isearch-mode should take care of
< adding multi-isearch-end to isearch-mode-end-hook when necessary
< variables are already restored, i.e. when you save the variable
< multi-isearch-next-buffer-function instead of
< multi-isearch-next-buffer-current-function.
I got the point. Actually I bind multi-isearch-next-buffer-function
to multi-isearch-next-buffer-current-function, because the former was nil
and multi-isearch-setup makes a non-nil test for this variable at the
beginning
< multi-isearch-current-buffer still needs to be restored after
< isearch-mode in the same place where you already added it in your patch.
OK.
[-- Attachment #2: Type: text/plain, Size: 1373 bytes --]
diff --git a/lisp/isearch.el b/lisp/isearch.el
index 4fc9b38..4c7187b 100644
--- a/lisp/isearch.el
+++ b/lisp/isearch.el
@@ -1242,6 +1242,11 @@ with-isearch-suspended
(isearch-adjusted isearch-adjusted)
(isearch-yank-flag isearch-yank-flag)
(isearch-error isearch-error)
+
+ (multi-isearch-file-list-new multi-isearch-file-list)
+ (multi-isearch-buffer-list-new multi-isearch-buffer-list)
+ (multi-isearch-next-buffer-function multi-isearch-next-buffer-current-function)
+ (multi-isearch-current-buffer-new multi-isearch-current-buffer)
;;; Don't bind this. We want isearch-search, below, to set it.
;;; And the old value won't matter after that.
;;; (isearch-other-end isearch-other-end)
@@ -1303,7 +1308,10 @@ with-isearch-suspended
isearch-message isearch-new-message
isearch-forward isearch-new-forward
isearch-word isearch-new-word
- isearch-case-fold-search isearch-new-case-fold))
+ isearch-case-fold-search isearch-new-case-fold
+ multi-isearch-current-buffer multi-isearch-current-buffer-new
+ multi-isearch-file-list multi-isearch-file-list-new
+ multi-isearch-buffer-list multi-isearch-buffer-list-new))
;; Empty isearch-string means use default.
(when (= 0 (length isearch-string))
^ permalink raw reply related [flat|nested] 27+ messages in thread
* bug#21684: 25.0.50; undo in query-replace w/o exit
@ 2015-10-14 13:26 Tino Calancha
2015-10-14 16:23 ` Juri Linkov
[not found] ` <handler.21684.B.144482901430164.ack@debbugs.gnu.org>
0 siblings, 2 replies; 27+ messages in thread
From: Tino Calancha @ 2015-10-14 13:26 UTC (permalink / raw)
To: 21684
[-- Attachment #1: Type: text/plain, Size: 677 bytes --]
In GNU Emacs 25.0.50.1 (x86_64-unknown-linux-gnu, GTK+ Version 2.24.23)
of 2015-10-14
Repository revision: 38f99a02b83e9e408970cb7abdb685725b2004f9
Quite often, performing query-replace, i just hit the [space] quicky
with no much attention. If i replace one string by mistake, i can
comeback to it with "^", but if i edit the string with "E" to reset it
to its original value, the interactive query-replace session ends.
I found useful if we can undo such replacements without exiting the
query-replace.
The attached patch implement such behaviour for `query-replace'.
Having this also working for `query-replace-regexp' would be very nice,
but harder to implement.
[-- Attachment #2: Type: text/plain, Size: 2767 bytes --]
diff --git a/lisp/replace.el b/lisp/replace.el
index 3a908ac..e3c906b 100644
--- a/lisp/replace.el
+++ b/lisp/replace.el
@@ -1802,6 +1802,7 @@ query-replace-help
C-l to clear the screen, redisplay, and offer same replacement again,
! to replace all remaining matches in this buffer with no more questions,
^ to move point back to previous match,
+U to undo previous replacement (queries w/ regexp not supported),
E to edit the replacement string.
In multi-buffer replacements type `Y' to replace all remaining
matches in all remaining buffers with no more questions,
@@ -1831,6 +1832,8 @@ query-replace-map
(define-key map "\C-l" 'recenter)
(define-key map "!" 'automatic)
(define-key map "^" 'backup)
+ (define-key map "u" 'undo)
+ (define-key map "U" 'undo)
(define-key map "\C-h" 'help)
(define-key map [f1] 'help)
(define-key map [help] 'help)
@@ -1856,7 +1859,7 @@ query-replace-map
`act-and-exit', `exit', `exit-prefix', `recenter', `scroll-up',
`scroll-down', `scroll-other-window', `scroll-other-window-down',
`edit', `edit-replacement', `delete-and-edit', `automatic',
-`backup', `quit', and `help'.
+`backup', `undo', `quit', and `help'.
This keymap is used by `y-or-n-p' as well as `query-replace'.")
@@ -2332,6 +2335,32 @@ perform-replace
(message "No previous match")
(ding 'no-terminate)
(sit-for 1)))
+ ((eq def 'undo)
+ (cond (regexp-flag
+ (message "Undo not supported in queries with regexp")
+ (ding 'no-terminate)
+ (sit-for 1))
+ (t
+ ;; bind locally swapped values (search-string/replacement)
+ (let* ((search-string-1 next-replacement)
+ (next-replacement search-string)
+ (search-string search-string-1)
+ (elt (if stack (pop stack) (match-data))))
+ (goto-char (nth 0 elt))
+ (setq replaced (nth 1 elt))
+ (and replaced (goto-char (- (point) (length next-replacement))))
+
+ (replace-match-maybe-edit
+ next-replacement nocasify literal
+ noedit real-match-data backward)
+
+ (setq noedit nil
+ replace-count (1- replace-count)
+ replaced nil
+ real-match-data
+ (replace-match-data
+ t real-match-data
+ (nth 2 elt)))))))
((eq def 'act)
(or replaced
(setq noedit
^ permalink raw reply related [flat|nested] 27+ messages in thread
* bug#21663: 25.0.50; isearch-edit-string dont resume multi isearches
2015-10-14 6:48 ` Tino Calancha
@ 2015-10-14 16:17 ` Juri Linkov
0 siblings, 0 replies; 27+ messages in thread
From: Juri Linkov @ 2015-10-14 16:17 UTC (permalink / raw)
To: Tino Calancha; +Cc: 21663
Thank you Tino, I have tested your patch and it works OK,
so please commit it.
^ permalink raw reply [flat|nested] 27+ messages in thread
* bug#21684: 25.0.50; undo in query-replace w/o exit
2015-10-14 13:26 bug#21684: 25.0.50; undo in query-replace w/o exit Tino Calancha
@ 2015-10-14 16:23 ` Juri Linkov
2015-10-17 13:04 ` Tino Calancha
[not found] ` <handler.21684.B.144482901430164.ack@debbugs.gnu.org>
1 sibling, 1 reply; 27+ messages in thread
From: Juri Linkov @ 2015-10-14 16:23 UTC (permalink / raw)
To: Tino Calancha; +Cc: 21684
> Quite often, performing query-replace, i just hit the [space] quicky
> with no much attention. If i replace one string by mistake, i can
> comeback to it with "^", but if i edit the string with "E" to reset it to
> its original value, the interactive query-replace session ends.
>
> I found useful if we can undo such replacements without exiting the
> query-replace.
>
> The attached patch implement such behaviour for `query-replace'.
> Having this also working for `query-replace-regexp' would be very nice,
> but harder to implement.
This would be a useful feature. But I wonder why it's harder to
implement for regexps? If you need, you could add all previous
replacements strings to the same stack at the end of data elements in
the stack like we did when necessary by adding new data at the end of the
similar isearch stack elements in isearch-cmds. This would simplify
restoring the previous replaced strings from the stack.
PS: an alternative solution would be to call ordinary (undo) since
perform-replace places undo boundaries with (undo-boundary), but
it seems this would be a less reliable approach?
^ permalink raw reply [flat|nested] 27+ messages in thread
* bug#21684: 25.0.50; undo in query-replace w/o exit
2015-10-14 16:23 ` Juri Linkov
@ 2015-10-17 13:04 ` Tino Calancha
2015-10-17 21:49 ` Juri Linkov
0 siblings, 1 reply; 27+ messages in thread
From: Tino Calancha @ 2015-10-17 13:04 UTC (permalink / raw)
To: 21684
[-- Attachment #1: Type: text/plain, Size: 577 bytes --]
> I wonder why it's harder to implement for regexps?
Basically for my lack of expertise in this code: i was trying
to extend my patch to support regexp without success.
> you could add all previous replacements strings
> to the same stack at the end of data elements
> like we did when necessary by adding new data at
> the end of the similar isearch stack elements in isearch-cmds.
Thank you, it sounds a good idea!!
See new patch (replace-2.patch): AFAICS is working as i wanted.
Please try it and feel free to give me any comments if you
find some issues to fix/improve.
[-- Attachment #2: Type: text/plain, Size: 6384 bytes --]
diff --git a/lisp/replace.el b/lisp/replace.el
index 3a908ac..7ada519 100644
--- a/lisp/replace.el
+++ b/lisp/replace.el
@@ -1802,6 +1802,7 @@ query-replace-help
C-l to clear the screen, redisplay, and offer same replacement again,
! to replace all remaining matches in this buffer with no more questions,
^ to move point back to previous match,
+U to undo previous replacement,
E to edit the replacement string.
In multi-buffer replacements type `Y' to replace all remaining
matches in all remaining buffers with no more questions,
@@ -1831,6 +1832,8 @@ query-replace-map
(define-key map "\C-l" 'recenter)
(define-key map "!" 'automatic)
(define-key map "^" 'backup)
+ (define-key map "u" 'undo)
+ (define-key map "U" 'undo)
(define-key map "\C-h" 'help)
(define-key map [f1] 'help)
(define-key map [help] 'help)
@@ -1856,7 +1859,7 @@ query-replace-map
`act-and-exit', `exit', `exit-prefix', `recenter', `scroll-up',
`scroll-down', `scroll-other-window', `scroll-other-window-down',
`edit', `edit-replacement', `delete-and-edit', `automatic',
-`backup', `quit', and `help'.
+`backup', `undo', `quit', and `help'.
This keymap is used by `y-or-n-p' as well as `query-replace'.")
@@ -2105,6 +2108,9 @@ perform-replace
(noedit nil)
(keep-going t)
(stack nil)
+ (search-string-solved-regexp nil) ; last string matching `from-string'
+ (next-replacement-solved-regexp nil) ; replacement string (substituted regexp)
+ (last-was-undo)
(replace-count 0)
(skip-read-only-count 0)
(skip-filtered-count 0)
@@ -2279,6 +2285,22 @@ perform-replace
(match-beginning 0) (match-end 0)
start end search-string
regexp-flag delimited-flag case-fold-search backward)
+ ;; Obtain the matched groups: needed only when regexp-flag non nil
+ (when (and last-was-undo regexp-flag)
+ (setq last-was-undo nil
+ real-match-data
+ (save-excursion
+ (goto-char (match-beginning 0))
+ (looking-at search-string)
+ (match-data t real-match-data))))
+ ;; Matched string and next-replacement (subtituted matched groups) stored in stack.
+ (setq search-string-solved-regexp (buffer-substring-no-properties (match-beginning 0)
+ (match-end 0))
+ next-replacement-solved-regexp
+ (query-replace-descr
+ (save-match-data
+ (set-match-data real-match-data)
+ (match-substitute-replacement next-replacement nocasify literal))))
;; Bind message-log-max so we don't fill up the message log
;; with a bunch of identical messages.
(let ((message-log-max nil)
@@ -2332,6 +2354,45 @@ perform-replace
(message "No previous match")
(ding 'no-terminate)
(sit-for 1)))
+ ((eq def 'undo)
+ (if (null stack)
+ (progn
+ (message "No previous match")
+ (ding 'no-terminate)
+ (sit-for 1))
+ (let* (search-string next-replacement (elt (pop stack)))
+ (goto-char (nth 0 elt))
+ (setq replaced (nth 1 elt)
+ ;; Bind locally swapped values (search-string <---> replacement).
+ search-string (nth (if replaced 1 0) (nth 3 elt))
+ next-replacement (nth (if replaced 0 1) (nth 3 elt))
+ search-string-solved-regexp search-string
+ next-replacement-solved-regexp next-replacement)
+
+ (cond ((null replaced) ; nothing to undo
+ (setq real-match-data
+ (replace-match-data
+ t real-match-data
+ (nth 2 elt))))
+ (t ; undo replacement
+ (set-match-data (nth 2 elt))
+ (setq real-match-data
+ (save-excursion
+ (goto-char (match-beginning 0))
+ (looking-at search-string)
+ (match-data t (nth 2 elt)))
+ noedit
+ (replace-match-maybe-edit
+ next-replacement nocasify literal
+ noedit real-match-data backward)
+ replace-count (1- replace-count)
+ real-match-data
+ (save-excursion
+ (goto-char (match-beginning 0))
+ (looking-at next-replacement)
+ (match-data t (nth 2 elt))))))
+ (setq replaced nil
+ last-was-undo t))))
((eq def 'act)
(or replaced
(setq noedit
@@ -2454,8 +2515,12 @@ perform-replace
(match-beginning 0)
(match-end 0)
(current-buffer))
- (match-data t)))
- stack))))))
+ (match-data t))
+ (list search-string-solved-regexp
+ next-replacement-solved-regexp))
+ stack)
+ (setq next-replacement-solved-regexp nil
+ search-string-solved-regexp nil))))))
(replace-dehighlight))
(or unread-command-events
^ permalink raw reply related [flat|nested] 27+ messages in thread
* bug#21684: 25.0.50; undo in query-replace w/o exit
2015-10-17 13:04 ` Tino Calancha
@ 2015-10-17 21:49 ` Juri Linkov
2015-10-18 9:45 ` Tino Calancha
0 siblings, 1 reply; 27+ messages in thread
From: Juri Linkov @ 2015-10-17 21:49 UTC (permalink / raw)
To: Tino Calancha; +Cc: 21684
> See new patch (replace-2.patch): AFAICS is working as i wanted.
> Please try it and feel free to give me any comments if you
> find some issues to fix/improve.
Thank you, your patch is working well. One issue to improve I noticed that
when a previous replacement is skipped with "n" then undo "U" acts exactly
as backup "^" by going to the previous place, and doing no undo actually.
Maybe better would be for undo "U" to only undo and skip non-replacement
entries in the stack? (Implementation-wise this means looping until
finding a previous non-replacement entry in the stack).
A minor comment is that to save cons cells you could just put both new
elements shallow as elements 3 and 4 in the stack instead of adding
a list of them.
Another minor suggestions is for better names you could rename
the prefix -solved-regexp to -replaced, i.e. replace
search-string-solved-regexp, next-replacement-solved-regexp with
search-string-replaced, next-replacement-replaced.
Also we need this feature to be documented in etc/NEWS.
Have you already signed FSF copyright assignment papers?
Your patch for bug#21663 is short enough to be installed without the
copyright paperwork, but your changes for bug#21684 require it.
^ permalink raw reply [flat|nested] 27+ messages in thread
* bug#21684: 25.0.50; undo in query-replace w/o exit
2015-10-17 21:49 ` Juri Linkov
@ 2015-10-18 9:45 ` Tino Calancha
2015-10-18 15:58 ` Richard Stallman
0 siblings, 1 reply; 27+ messages in thread
From: Tino Calancha @ 2015-10-18 9:45 UTC (permalink / raw)
To: 21684
[-- Attachment #1: Type: text/plain, Size: 815 bytes --]
>Maybe better would be for undo "U" to only undo and skip non-replacement
>entries in the stack? (Implementation-wise this means looping until
>finding a previous non-replacement entry in the stack).
I agree, its better undo 'just' undo. Fixed in the new patch
(replace-3.patch).
>A minor comment is that to save cons cells you could just put both new
>elements shallow as elements 3 and 4 in the stack instead of adding
>a list of them.
Sure, thank you for remind me this. Applied.
>Another minor suggestions is for better names you could rename
>the prefix -solved-regexp to -replaced
Done. Thank you.
>Also we need this feature to be documented in etc/NEWS.
>Have you already signed FSF copyright assignment papers?
I didn't. I would like to sign. Maybe someone could guide me how to
complete such process.
[-- Attachment #2: Type: text/plain, Size: 6556 bytes --]
diff --git a/lisp/replace.el b/lisp/replace.el
index 3a908ac..43a5a78 100644
--- a/lisp/replace.el
+++ b/lisp/replace.el
@@ -1802,6 +1802,7 @@ query-replace-help
C-l to clear the screen, redisplay, and offer same replacement again,
! to replace all remaining matches in this buffer with no more questions,
^ to move point back to previous match,
+U to undo previous replacement,
E to edit the replacement string.
In multi-buffer replacements type `Y' to replace all remaining
matches in all remaining buffers with no more questions,
@@ -1831,6 +1832,8 @@ query-replace-map
(define-key map "\C-l" 'recenter)
(define-key map "!" 'automatic)
(define-key map "^" 'backup)
+ (define-key map "u" 'undo)
+ (define-key map "U" 'undo)
(define-key map "\C-h" 'help)
(define-key map [f1] 'help)
(define-key map [help] 'help)
@@ -1856,7 +1859,7 @@ query-replace-map
`act-and-exit', `exit', `exit-prefix', `recenter', `scroll-up',
`scroll-down', `scroll-other-window', `scroll-other-window-down',
`edit', `edit-replacement', `delete-and-edit', `automatic',
-`backup', `quit', and `help'.
+`backup', `undo', `quit', and `help'.
This keymap is used by `y-or-n-p' as well as `query-replace'.")
@@ -2105,6 +2108,9 @@ perform-replace
(noedit nil)
(keep-going t)
(stack nil)
+ (search-string-replaced nil) ; last string matching `from-string'
+ (next-replacement-replaced nil) ; replacement string (substituted regexp)
+ (last-was-undo)
(replace-count 0)
(skip-read-only-count 0)
(skip-filtered-count 0)
@@ -2279,6 +2285,22 @@ perform-replace
(match-beginning 0) (match-end 0)
start end search-string
regexp-flag delimited-flag case-fold-search backward)
+ ;; Obtain the matched groups: needed only when regexp-flag non nil
+ (when (and last-was-undo regexp-flag)
+ (setq last-was-undo nil
+ real-match-data
+ (save-excursion
+ (goto-char (match-beginning 0))
+ (looking-at search-string)
+ (match-data t real-match-data))))
+ ;; Matched string and next-replacement (subtituted matched groups) stored in stack.
+ (setq search-string-replaced (buffer-substring-no-properties (match-beginning 0)
+ (match-end 0))
+ next-replacement-replaced
+ (query-replace-descr
+ (save-match-data
+ (set-match-data real-match-data)
+ (match-substitute-replacement next-replacement nocasify literal))))
;; Bind message-log-max so we don't fill up the message log
;; with a bunch of identical messages.
(let ((message-log-max nil)
@@ -2332,6 +2354,50 @@ perform-replace
(message "No previous match")
(ding 'no-terminate)
(sit-for 1)))
+ ((eq def 'undo)
+ (if (null stack)
+ (progn
+ (message "Nothing to undo")
+ (ding 'no-terminate)
+ (sit-for 1))
+ (let ((stack-idx 0)
+ (stack-len (length stack)))
+ (while (and (< stack-idx stack-len) stack (null replaced))
+ (let* (search-string next-replacement (elt (nth stack-idx stack)))
+ (setq stack-idx (1+ stack-idx)
+ replaced (nth 1 elt)
+ ;; Bind locally swapped values (search-string <---> replacement).
+ search-string (if replaced (nth 4 elt) (nth 3 elt))
+ next-replacement (if replaced (nth 3 elt) (nth 4 elt))
+ search-string-replaced search-string
+ next-replacement-replaced next-replacement)
+
+ (when (and (null replaced) (= stack-idx stack-len))
+ (message "Nothing to undo")
+ (ding 'no-terminate)
+ (sit-for 1))
+
+ (when replaced
+ (setq stack (nthcdr stack-idx stack))
+ (goto-char (nth 0 elt))
+ (set-match-data (nth 2 elt))
+ (setq real-match-data
+ (save-excursion
+ (goto-char (match-beginning 0))
+ (looking-at search-string)
+ (match-data t (nth 2 elt)))
+ noedit
+ (replace-match-maybe-edit
+ next-replacement nocasify literal
+ noedit real-match-data backward)
+ replace-count (1- replace-count)
+ real-match-data
+ (save-excursion
+ (goto-char (match-beginning 0))
+ (looking-at next-replacement)
+ (match-data t (nth 2 elt))))))))
+ (setq replaced nil
+ last-was-undo t)))
((eq def 'act)
(or replaced
(setq noedit
@@ -2454,9 +2520,12 @@ perform-replace
(match-beginning 0)
(match-end 0)
(current-buffer))
- (match-data t)))
- stack))))))
-
+ (match-data t))
+ search-string-replaced
+ next-replacement-replaced)
+ stack)
+ (setq next-replacement-replaced nil
+ search-string-replaced nil))))))
(replace-dehighlight))
(or unread-command-events
(message "Replaced %d occurrence%s%s"
^ permalink raw reply related [flat|nested] 27+ messages in thread
* bug#21684: 25.0.50; undo in query-replace w/o exit
2015-10-18 9:45 ` Tino Calancha
@ 2015-10-18 15:58 ` Richard Stallman
2015-10-19 1:20 ` Tino Calancha
0 siblings, 1 reply; 27+ messages in thread
From: Richard Stallman @ 2015-10-18 15:58 UTC (permalink / raw)
To: Tino Calancha; +Cc: 21684
[[[ To any NSA and FBI agents reading my email: please consider ]]]
[[[ whether defending the US Constitution against all enemies, ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]
> >Maybe better would be for undo "U" to only undo and skip non-replacement
> >entries in the stack? (Implementation-wise this means looping until
> >finding a previous non-replacement entry in the stack).
> I agree, its better undo 'just' undo. Fixed in the new patch
> (replace-3.patch).
What change in functionality is being considered here?
--
Dr Richard Stallman
President, Free Software Foundation (gnu.org, fsf.org)
Internet Hall-of-Famer (internethalloffame.org)
Skype: No way! See stallman.org/skype.html.
^ permalink raw reply [flat|nested] 27+ messages in thread
* bug#21684: 25.0.50; undo in query-replace w/o exit
2015-10-18 15:58 ` Richard Stallman
@ 2015-10-19 1:20 ` Tino Calancha
2015-10-19 22:04 ` Juri Linkov
2015-10-26 4:09 ` bug#21684: 25.0.50; undo in query-replace w/o exit Richard Stallman
0 siblings, 2 replies; 27+ messages in thread
From: Tino Calancha @ 2015-10-19 1:20 UTC (permalink / raw)
To: Richard Stallman; +Cc: Tino Calancha, 21684
> What change in functionality is being considered here?
Hi Richard,
the purpose is provide 'undo' into `query-replace'/`query-replace-regexp'.
Original code do not support such functionality in a convenient way.
For instance, in the scratch buffer:
M-x query-replace RET f RET @ RET [space] RET [space] RET C-/
(C-/ undo last replacement but end session: [space] would insert one space)
Indeed, you may correct last replacement with existing code without exit current
search replace, as follows:
I)
M-x query-replace RET f RET @ RET [space] RET [space] "^" C-r
(now you can edit last replacement; comeback to query-replace session with C-M-c)
C-M-c [space] [space] ...
This seems too complicated/slow to just undo last 1-2 replacements.
In my experience as an user 99% of the times, the situation is that i hit [space]
many times and fast, and then i realize i just want to undo last 1-2
replacements and keep going. It would be useful if that can be done just
with one key.
The patch replace-3.patch in this thread implements such interactive undo and binds
the new funtionality to keys "u" and "U".
Every time you hit "u" the latest replacement is undo: now you can hit "n" to skip
it (tipically) or [space] to replace it again, or maybe "u" to undo
another previous replacement (if any). The query-replace session is not
exit.
Tino
^ permalink raw reply [flat|nested] 27+ messages in thread
* bug#21684: 25.0.50; undo in query-replace w/o exit
2015-10-19 1:20 ` Tino Calancha
@ 2015-10-19 22:04 ` Juri Linkov
2015-10-20 12:02 ` Tino Calancha
2015-10-26 4:09 ` bug#21684: 25.0.50; undo in query-replace w/o exit Richard Stallman
1 sibling, 1 reply; 27+ messages in thread
From: Juri Linkov @ 2015-10-19 22:04 UTC (permalink / raw)
To: Tino Calancha; +Cc: 21684, Richard Stallman
> The patch replace-3.patch in this thread implements such interactive undo
> and binds the new funtionality to keys "u" and "U".
Please note that usually the upper-case "U" applies to all
elements in the set such as e.g. in Dired the lower-case "u"
is bound to a single-mark dired-unmark whereas the upper-case "U"
is bound to dired-unmark-all-marks, etc.
For query-replace this means that better would be to bind the
upper-case "U" to a new operation undo-all that could be easy to
implement in the same branch with (or (eq def 'undo) (eq def 'undo-all))
and looping until the top of the stack when (eq def 'undo-all).
^ permalink raw reply [flat|nested] 27+ messages in thread
* bug#21684: 25.0.50; undo in query-replace w/o exit
2015-10-19 22:04 ` Juri Linkov
@ 2015-10-20 12:02 ` Tino Calancha
2016-02-23 8:40 ` Lars Ingebrigtsen
0 siblings, 1 reply; 27+ messages in thread
From: Tino Calancha @ 2015-10-20 12:02 UTC (permalink / raw)
To: 21684
[-- Attachment #1: Type: text/plain, Size: 269 bytes --]
> Please note that usually the upper-case "U" applies to all
> elements in the set.
> For query-replace this means that better would be to bind the
> upper-case "U" to a new operation undo-all
Good point. Thank you very much.
Included in new patch (replace-4.patch).
[-- Attachment #2: Type: text/plain, Size: 7554 bytes --]
diff --git a/lisp/replace.el b/lisp/replace.el
index 3a908ac..ef8c5e4 100644
--- a/lisp/replace.el
+++ b/lisp/replace.el
@@ -1802,6 +1802,8 @@ query-replace-help
C-l to clear the screen, redisplay, and offer same replacement again,
! to replace all remaining matches in this buffer with no more questions,
^ to move point back to previous match,
+u to undo previous replacement,
+U to undo all replacements,
E to edit the replacement string.
In multi-buffer replacements type `Y' to replace all remaining
matches in all remaining buffers with no more questions,
@@ -1831,6 +1833,8 @@ query-replace-map
(define-key map "\C-l" 'recenter)
(define-key map "!" 'automatic)
(define-key map "^" 'backup)
+ (define-key map "u" 'undo)
+ (define-key map "U" 'undo-all)
(define-key map "\C-h" 'help)
(define-key map [f1] 'help)
(define-key map [help] 'help)
@@ -1856,7 +1860,7 @@ query-replace-map
`act-and-exit', `exit', `exit-prefix', `recenter', `scroll-up',
`scroll-down', `scroll-other-window', `scroll-other-window-down',
`edit', `edit-replacement', `delete-and-edit', `automatic',
-`backup', `quit', and `help'.
+`backup', `undo', `undo-all', `quit', and `help'.
This keymap is used by `y-or-n-p' as well as `query-replace'.")
@@ -2105,6 +2109,9 @@ perform-replace
(noedit nil)
(keep-going t)
(stack nil)
+ (search-string-replaced nil) ; last string matching `from-string'
+ (next-replacement-replaced nil) ; replacement string (substituted regexp)
+ (last-was-undo)
(replace-count 0)
(skip-read-only-count 0)
(skip-filtered-count 0)
@@ -2279,6 +2286,23 @@ perform-replace
(match-beginning 0) (match-end 0)
start end search-string
regexp-flag delimited-flag case-fold-search backward)
+ ;; Obtain the matched groups: needed only when regexp-flag non nil.
+ (when (and last-was-undo regexp-flag)
+ (setq last-was-undo nil
+ real-match-data
+ (save-excursion
+ (goto-char (match-beginning 0))
+ (looking-at search-string)
+ (match-data t real-match-data))))
+ ;; Matched string and next-replacement-replaced stored in stack.
+ (setq search-string-replaced (buffer-substring-no-properties
+ (match-beginning 0)
+ (match-end 0))
+ next-replacement-replaced
+ (query-replace-descr
+ (save-match-data
+ (set-match-data real-match-data)
+ (match-substitute-replacement next-replacement nocasify literal))))
;; Bind message-log-max so we don't fill up the message log
;; with a bunch of identical messages.
(let ((message-log-max nil)
@@ -2332,6 +2356,64 @@ perform-replace
(message "No previous match")
(ding 'no-terminate)
(sit-for 1)))
+ ((or (eq def 'undo) (eq def 'undo-all))
+ (if (null stack)
+ (progn
+ (message "Nothing to undo")
+ (ding 'no-terminate)
+ (sit-for 1))
+ (let ((stack-idx 0)
+ (stack-len (length stack))
+ (num-replacements 0)
+ search-string
+ next-replacement)
+ (while (and (< stack-idx stack-len) stack (null replaced))
+ (let* ((elt (nth stack-idx stack)))
+ (setq stack-idx (1+ stack-idx)
+ replaced (nth 1 elt)
+ ;; Bind swapped values (search-string <--> replacement)
+ search-string (nth (if replaced 4 3) elt)
+ next-replacement (nth (if replaced 3 4) elt)
+ search-string-replaced search-string
+ next-replacement-replaced next-replacement)
+
+ (when (and (null replaced) (= stack-idx stack-len))
+ (message "Nothing to undo")
+ (ding 'no-terminate)
+ (sit-for 1))
+
+ (when replaced
+ (setq stack (nthcdr stack-idx stack))
+ (goto-char (nth 0 elt))
+ (set-match-data (nth 2 elt))
+ (setq real-match-data
+ (save-excursion
+ (goto-char (match-beginning 0))
+ (looking-at search-string)
+ (match-data t (nth 2 elt)))
+ noedit
+ (replace-match-maybe-edit
+ next-replacement nocasify literal
+ noedit real-match-data backward)
+ replace-count (1- replace-count)
+ real-match-data
+ (save-excursion
+ (goto-char (match-beginning 0))
+ (looking-at next-replacement)
+ (match-data t (nth 2 elt))))
+ (when (eq def 'undo-all) ; Set replaced nil to keep in loop
+ (setq replaced nil
+ stack-len (- stack-len stack-idx)
+ stack-idx 0
+ num-replacements (1+ num-replacements))
+ (unless stack
+ (message "Undid %d %s" num-replacements
+ (if (= num-replacements 1)
+ "replacement"
+ "replacements"))
+ (ding 'no-terminate)
+ (sit-for 1)))))))
+ (setq replaced nil last-was-undo t)))
((eq def 'act)
(or replaced
(setq noedit
@@ -2454,9 +2536,12 @@ perform-replace
(match-beginning 0)
(match-end 0)
(current-buffer))
- (match-data t)))
- stack))))))
-
+ (match-data t))
+ search-string-replaced
+ next-replacement-replaced)
+ stack)
+ (setq next-replacement-replaced nil
+ search-string-replaced nil))))))
(replace-dehighlight))
(or unread-command-events
(message "Replaced %d occurrence%s%s"
^ permalink raw reply related [flat|nested] 27+ messages in thread
* bug#21684: Acknowledgement (25.0.50; undo in query-replace w/o exit)
[not found] ` <handler.21684.B.144482901430164.ack@debbugs.gnu.org>
@ 2015-10-20 13:01 ` Tino Calancha
0 siblings, 0 replies; 27+ messages in thread
From: Tino Calancha @ 2015-10-20 13:01 UTC (permalink / raw)
To: 21684
[-- Attachment #1: Type: text/plain, Size: 218 bytes --]
In previous patch 'undo-all just show the total number of undid
replacements if the first element was replaced.
New patch (replace-5.patch) fix that: undo-all always show the accumulated
number of undone performed.
[-- Attachment #2: Type: text/plain, Size: 7907 bytes --]
diff --git a/lisp/replace.el b/lisp/replace.el
index 3a908ac..16a9942 100644
--- a/lisp/replace.el
+++ b/lisp/replace.el
@@ -1802,6 +1802,8 @@ query-replace-help
C-l to clear the screen, redisplay, and offer same replacement again,
! to replace all remaining matches in this buffer with no more questions,
^ to move point back to previous match,
+u to undo previous replacement,
+U to undo all replacements,
E to edit the replacement string.
In multi-buffer replacements type `Y' to replace all remaining
matches in all remaining buffers with no more questions,
@@ -1831,6 +1833,8 @@ query-replace-map
(define-key map "\C-l" 'recenter)
(define-key map "!" 'automatic)
(define-key map "^" 'backup)
+ (define-key map "u" 'undo)
+ (define-key map "U" 'undo-all)
(define-key map "\C-h" 'help)
(define-key map [f1] 'help)
(define-key map [help] 'help)
@@ -1856,7 +1860,7 @@ query-replace-map
`act-and-exit', `exit', `exit-prefix', `recenter', `scroll-up',
`scroll-down', `scroll-other-window', `scroll-other-window-down',
`edit', `edit-replacement', `delete-and-edit', `automatic',
-`backup', `quit', and `help'.
+`backup', `undo', `undo-all', `quit', and `help'.
This keymap is used by `y-or-n-p' as well as `query-replace'.")
@@ -2105,6 +2109,9 @@ perform-replace
(noedit nil)
(keep-going t)
(stack nil)
+ (search-string-replaced nil) ; last string matching `from-string'
+ (next-replacement-replaced nil) ; replacement string (substituted regexp)
+ (last-was-undo)
(replace-count 0)
(skip-read-only-count 0)
(skip-filtered-count 0)
@@ -2279,6 +2286,23 @@ perform-replace
(match-beginning 0) (match-end 0)
start end search-string
regexp-flag delimited-flag case-fold-search backward)
+ ;; Obtain the matched groups: needed only when regexp-flag non nil.
+ (when (and last-was-undo regexp-flag)
+ (setq last-was-undo nil
+ real-match-data
+ (save-excursion
+ (goto-char (match-beginning 0))
+ (looking-at search-string)
+ (match-data t real-match-data))))
+ ;; Matched string and next-replacement-replaced stored in stack.
+ (setq search-string-replaced (buffer-substring-no-properties
+ (match-beginning 0)
+ (match-end 0))
+ next-replacement-replaced
+ (query-replace-descr
+ (save-match-data
+ (set-match-data real-match-data)
+ (match-substitute-replacement next-replacement nocasify literal))))
;; Bind message-log-max so we don't fill up the message log
;; with a bunch of identical messages.
(let ((message-log-max nil)
@@ -2332,6 +2356,67 @@ perform-replace
(message "No previous match")
(ding 'no-terminate)
(sit-for 1)))
+ ((or (eq def 'undo) (eq def 'undo-all))
+ (if (null stack)
+ (progn
+ (message "Nothing to undo")
+ (ding 'no-terminate)
+ (sit-for 1))
+ (let ((stack-idx 0)
+ (stack-len (length stack))
+ (num-replacements 0)
+ search-string
+ next-replacement)
+ (while (and (< stack-idx stack-len) stack (null replaced))
+ (let* ((elt (nth stack-idx stack)))
+ (setq stack-idx (1+ stack-idx)
+ replaced (nth 1 elt)
+ ;; Bind swapped values (search-string <--> replacement)
+ search-string (nth (if replaced 4 3) elt)
+ next-replacement (nth (if replaced 3 4) elt)
+ search-string-replaced search-string
+ next-replacement-replaced next-replacement)
+
+ (when (= stack-idx stack-len)
+ (cond ((and (null replaced) (zerop num-replacements))
+ (message "Nothing to undo")
+ (ding 'no-terminate)
+ (sit-for 1))
+ ((or replaced (null (zerop num-replacements)))
+ (let ((num-replacements (if replaced (1+ num-replacements)
+ num-replacements)))
+ (message "Undid %d %s" num-replacements
+ (if (= num-replacements 1)
+ "replacement"
+ "replacements"))
+ (ding 'no-terminate)
+ (sit-for 1)))))
+
+ (when replaced
+ (setq stack (nthcdr stack-idx stack))
+ (goto-char (nth 0 elt))
+ (set-match-data (nth 2 elt))
+ (setq real-match-data
+ (save-excursion
+ (goto-char (match-beginning 0))
+ (looking-at search-string)
+ (match-data t (nth 2 elt)))
+ noedit
+ (replace-match-maybe-edit
+ next-replacement nocasify literal
+ noedit real-match-data backward)
+ replace-count (1- replace-count)
+ real-match-data
+ (save-excursion
+ (goto-char (match-beginning 0))
+ (looking-at next-replacement)
+ (match-data t (nth 2 elt))))
+ (when (eq def 'undo-all) ; Set replaced nil to keep in loop
+ (setq replaced nil
+ stack-len (- stack-len stack-idx)
+ stack-idx 0
+ num-replacements (1+ num-replacements)))))))
+ (setq replaced nil last-was-undo t)))
((eq def 'act)
(or replaced
(setq noedit
@@ -2454,9 +2539,12 @@ perform-replace
(match-beginning 0)
(match-end 0)
(current-buffer))
- (match-data t)))
- stack))))))
-
+ (match-data t))
+ search-string-replaced
+ next-replacement-replaced)
+ stack)
+ (setq next-replacement-replaced nil
+ search-string-replaced nil))))))
(replace-dehighlight))
(or unread-command-events
(message "Replaced %d occurrence%s%s"
^ permalink raw reply related [flat|nested] 27+ messages in thread
* bug#21684: 25.0.50; undo in query-replace w/o exit
2015-10-19 1:20 ` Tino Calancha
2015-10-19 22:04 ` Juri Linkov
@ 2015-10-26 4:09 ` Richard Stallman
1 sibling, 0 replies; 27+ messages in thread
From: Richard Stallman @ 2015-10-26 4:09 UTC (permalink / raw)
To: Tino Calancha; +Cc: f92capac, 21684
[[[ To any NSA and FBI agents reading my email: please consider ]]]
[[[ whether defending the US Constitution against all enemies, ]]]
[[[ foreign or domestic, requires you to follow Snowden's example. ]]]
Thanks. It seems useful.
(Please forgive my delay.)
--
Dr Richard Stallman
President, Free Software Foundation (gnu.org, fsf.org)
Internet Hall-of-Famer (internethalloffame.org)
Skype: No way! See stallman.org/skype.html.
^ permalink raw reply [flat|nested] 27+ messages in thread
* bug#21684: 25.0.50; undo in query-replace w/o exit
2015-10-20 12:02 ` Tino Calancha
@ 2016-02-23 8:40 ` Lars Ingebrigtsen
2016-02-23 16:46 ` Tino Calancha
0 siblings, 1 reply; 27+ messages in thread
From: Lars Ingebrigtsen @ 2016-02-23 8:40 UTC (permalink / raw)
To: Tino Calancha; +Cc: 21684
Tino Calancha <f92capac@gmail.com> writes:
> Good point. Thank you very much.
> Included in new patch (replace-4.patch).
Looks good. Could you also add documentation for this (to the manual)
and a NEWS entry?
--
(domestic pets only, the antidote for overdose, milk.)
bloggy blog: http://lars.ingebrigtsen.no
^ permalink raw reply [flat|nested] 27+ messages in thread
* bug#21684: 25.0.50; undo in query-replace w/o exit
2016-02-23 8:40 ` Lars Ingebrigtsen
@ 2016-02-23 16:46 ` Tino Calancha
2016-02-23 17:54 ` Eli Zaretskii
2016-02-24 1:36 ` Lars Ingebrigtsen
0 siblings, 2 replies; 27+ messages in thread
From: Tino Calancha @ 2016-02-23 16:46 UTC (permalink / raw)
To: Lars Ingebrigtsen; +Cc: Tino Calancha, 21684
[-- Attachment #1: Type: text/plain, Size: 142 bytes --]
> Looks good. Could you also add documentation for this (to the manual)
> and a NEWS entry?
Sure. Added NEWS entry and updated emacs manual.
[-- Attachment #2: Type: text/plain, Size: 8265 bytes --]
From 8c9f54de418166036df0da0c81d3c2b42da39430 Mon Sep 17 00:00:00 2001
From: Tino Calancha <f92capac@gmail.com>
Date: Wed, 24 Feb 2016 01:30:52 +0900
Subject: [PATCH 1/2] Undo in query-replace without exit
* lisp/replace.el (perform-replace): 'undo', undo last replacement
and move back to that place; 'undo-all', undo all replacements
and move back to the place where the first replacement was performed.
(Bug#21684)
---
lisp/replace.el | 95 ++++++++++++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 91 insertions(+), 4 deletions(-)
diff --git a/lisp/replace.el b/lisp/replace.el
index 488eff7..ab839ce 100644
--- a/lisp/replace.el
+++ b/lisp/replace.el
@@ -1824,6 +1824,8 @@ query-replace-help
C-l to clear the screen, redisplay, and offer same replacement again,
! to replace all remaining matches in this buffer with no more questions,
^ to move point back to previous match,
+u to undo previous replacement,
+U to undo all replacements,
E to edit the replacement string.
In multi-buffer replacements type `Y' to replace all remaining
matches in all remaining buffers with no more questions,
@@ -1853,6 +1855,8 @@ query-replace-map
(define-key map "\C-l" 'recenter)
(define-key map "!" 'automatic)
(define-key map "^" 'backup)
+ (define-key map "u" 'undo)
+ (define-key map "U" 'undo-all)
(define-key map "\C-h" 'help)
(define-key map [f1] 'help)
(define-key map [help] 'help)
@@ -1878,7 +1882,7 @@ query-replace-map
`act-and-exit', `exit', `exit-prefix', `recenter', `scroll-up',
`scroll-down', `scroll-other-window', `scroll-other-window-down',
`edit', `edit-replacement', `delete-and-edit', `automatic',
-`backup', `quit', and `help'.
+`backup', `undo', `undo-all', `quit', and `help'.
This keymap is used by `y-or-n-p' as well as `query-replace'.")
@@ -2132,6 +2136,9 @@ perform-replace
(noedit nil)
(keep-going t)
(stack nil)
+ (search-string-replaced nil) ; last string matching `from-string'
+ (next-replacement-replaced nil) ; replacement string (substituted regexp)
+ (last-was-undo)
(replace-count 0)
(skip-read-only-count 0)
(skip-filtered-count 0)
@@ -2328,6 +2335,23 @@ perform-replace
(match-beginning 0) (match-end 0)
start end search-string
regexp-flag delimited-flag case-fold-search backward)
+ ;; Obtain the matched groups: needed only when regexp-flag non nil.
+ (when (and last-was-undo regexp-flag)
+ (setq last-was-undo nil
+ real-match-data
+ (save-excursion
+ (goto-char (match-beginning 0))
+ (looking-at search-string)
+ (match-data t real-match-data))))
+ ;; Matched string and next-replacement-replaced stored in stack.
+ (setq search-string-replaced (buffer-substring-no-properties
+ (match-beginning 0)
+ (match-end 0))
+ next-replacement-replaced
+ (query-replace-descr
+ (save-match-data
+ (set-match-data real-match-data)
+ (match-substitute-replacement next-replacement nocasify literal))))
;; Bind message-log-max so we don't fill up the message log
;; with a bunch of identical messages.
(let ((message-log-max nil)
@@ -2381,6 +2405,66 @@ perform-replace
(message "No previous match")
(ding 'no-terminate)
(sit-for 1)))
+ ((or (eq def 'undo) (eq def 'undo-all))
+ (if (null stack)
+ (progn
+ (message "Nothing to undo")
+ (ding 'no-terminate)
+ (sit-for 1))
+ (let ((stack-idx 0)
+ (stack-len (length stack))
+ (num-replacements 0)
+ search-string
+ next-replacement)
+ (while (and (< stack-idx stack-len) stack (null replaced))
+ (let* ((elt (nth stack-idx stack)))
+ (setq stack-idx (1+ stack-idx)
+ replaced (nth 1 elt)
+ ;; Bind swapped values (search-string <--> replacement)
+ search-string (nth (if replaced 4 3) elt)
+ next-replacement (nth (if replaced 3 4) elt)
+ search-string-replaced search-string
+ next-replacement-replaced next-replacement)
+
+ (when (and (= stack-idx stack-len)
+ (null replaced)
+ (zerop num-replacements))
+ (message "Nothing to undo")
+ (ding 'no-terminate)
+ (sit-for 1))
+
+ (when replaced
+ (setq stack (nthcdr stack-idx stack))
+ (goto-char (nth 0 elt))
+ (set-match-data (nth 2 elt))
+ (setq real-match-data
+ (save-excursion
+ (goto-char (match-beginning 0))
+ (looking-at search-string)
+ (match-data t (nth 2 elt)))
+ noedit
+ (replace-match-maybe-edit
+ next-replacement nocasify literal
+ noedit real-match-data backward)
+ replace-count (1- replace-count)
+ real-match-data
+ (save-excursion
+ (goto-char (match-beginning 0))
+ (looking-at next-replacement)
+ (match-data t (nth 2 elt))))
+ (when (eq def 'undo-all) ; Set replaced nil to keep in loop
+ (setq replaced nil
+ stack-len (- stack-len stack-idx)
+ stack-idx 0
+ num-replacements (1+ num-replacements))))))
+ (when (and (eq def 'undo-all) (null (zerop num-replacements)))
+ (message "Undid %d %s" num-replacements
+ (if (= num-replacements 1)
+ "replacement"
+ "replacements"))
+ (ding 'no-terminate)
+ (sit-for 1)))
+ (setq replaced nil last-was-undo t)))
((eq def 'act)
(or replaced
(setq noedit
@@ -2503,9 +2587,12 @@ perform-replace
(match-beginning 0)
(match-end 0)
(current-buffer))
- (match-data t)))
- stack))))))
-
+ (match-data t))
+ search-string-replaced
+ next-replacement-replaced)
+ stack)
+ (setq next-replacement-replaced nil
+ search-string-replaced nil))))))
(replace-dehighlight))
(or unread-command-events
(message "Replaced %d occurrence%s%s"
--
2.7.0
[-- Attachment #3: Type: text/plain, Size: 2044 bytes --]
From a0bdcedd9aa6eb9e05dde2eae01389ae67f911c3 Mon Sep 17 00:00:00 2001
From: Tino Calancha <f92capac@gmail.com>
Date: Wed, 24 Feb 2016 01:38:50 +0900
Subject: [PATCH 2/2] ; Add NEWS and documentation for last commit
---
ChangeLog.2 | 7 +++++++
doc/lispref/searching.texi | 8 ++++++++
etc/NEWS | 5 +++++
3 files changed, 20 insertions(+)
diff --git a/ChangeLog.2 b/ChangeLog.2
index 6edc654..0d76762 100644
--- a/ChangeLog.2
+++ b/ChangeLog.2
@@ -1,3 +1,10 @@
+2016-02-23 Tino Calancha <f92capac@gmail.com>
+
+ * lisp/replace.el (perform-replace): `undo', undo last replacement
+ and move back to that place; `undo-all', undo all replacements
+ and move back to the place where the first replacement was performed.
+ (Bug#21684)
+
2016-02-15 Glenn Morris <rgm@gnu.org>
* lisp/dired-aux.el: Require cl-lib. (Bug#22613)
diff --git a/doc/lispref/searching.texi b/doc/lispref/searching.texi
index 1243d72..644716a 100644
--- a/doc/lispref/searching.texi
+++ b/doc/lispref/searching.texi
@@ -1805,6 +1805,14 @@ Search and Replace
@item backup
Move back to the previous place that a question was asked about.
+@item undo
+Undo last replacement and move back to the place where that
+replacement was performed.
+
+@item undo-all
+Undo all replacements and move back to the place where the first
+replacement was performed.
+
@item edit
Enter a recursive edit to deal with this question---instead of any
other action that would normally be taken.
diff --git a/etc/NEWS b/etc/NEWS
index 255afde..8c14e6d 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -435,6 +435,11 @@ is intended for adding to 'kill-emacs-query-functions'.
in favor of the global `M-s h' bindings introduced in Emacs-23.1.
They'll disappear soon.
++++
+** New bindings for 'query-replace-map'.
+`undo', undo the last replacement; bind to `u'.
+`undo-all', undo all replacements; Bind to `U'.
+
\f
* Changes in Specialized Modes and Packages in Emacs 25.1
--
2.7.0
^ permalink raw reply related [flat|nested] 27+ messages in thread
* bug#21684: 25.0.50; undo in query-replace w/o exit
2016-02-23 16:46 ` Tino Calancha
@ 2016-02-23 17:54 ` Eli Zaretskii
2016-02-24 1:36 ` Lars Ingebrigtsen
1 sibling, 0 replies; 27+ messages in thread
From: Eli Zaretskii @ 2016-02-23 17:54 UTC (permalink / raw)
To: Tino Calancha; +Cc: 21684, larsi
> Date: Wed, 24 Feb 2016 01:46:14 +0900 (JST)
> From: Tino Calancha <f92capac@gmail.com>
> Cc: Tino Calancha <f92capac@gmail.com>, 21684@debbugs.gnu.org
>
> > Looks good. Could you also add documentation for this (to the manual)
> > and a NEWS entry?
> Sure. Added NEWS entry and updated emacs manual.
Thanks. A minor nit below:
> --- a/etc/NEWS
> +++ b/etc/NEWS
> @@ -435,6 +435,11 @@ is intended for adding to 'kill-emacs-query-functions'.
> in favor of the global `M-s h' bindings introduced in Emacs-23.1.
> They'll disappear soon.
>
> ++++
> +** New bindings for 'query-replace-map'.
> +`undo', undo the last replacement; bind to `u'.
> +`undo-all', undo all replacements; Bind to `U'.
"Bound", not "bind"; and the capitalization needs to be fixed.
^ permalink raw reply [flat|nested] 27+ messages in thread
* bug#21684: 25.0.50; undo in query-replace w/o exit
2016-02-23 16:46 ` Tino Calancha
2016-02-23 17:54 ` Eli Zaretskii
@ 2016-02-24 1:36 ` Lars Ingebrigtsen
2016-02-24 13:13 ` Tino Calancha
2016-05-31 22:32 ` Glenn Morris
1 sibling, 2 replies; 27+ messages in thread
From: Lars Ingebrigtsen @ 2016-02-24 1:36 UTC (permalink / raw)
To: Tino Calancha; +Cc: 21684
Tino Calancha <f92capac@gmail.com> writes:
>> Looks good. Could you also add documentation for this (to the manual)
>> and a NEWS entry?
> Sure. Added NEWS entry and updated emacs manual.
Thanks; I've now applied this to the trunk. Seems to be working great,
and it's a feature I've missed for years.
--
(domestic pets only, the antidote for overdose, milk.)
bloggy blog: http://lars.ingebrigtsen.no
^ permalink raw reply [flat|nested] 27+ messages in thread
* bug#21684: 25.0.50; undo in query-replace w/o exit
2016-02-24 1:36 ` Lars Ingebrigtsen
@ 2016-02-24 13:13 ` Tino Calancha
2016-05-31 22:32 ` Glenn Morris
1 sibling, 0 replies; 27+ messages in thread
From: Tino Calancha @ 2016-02-24 13:13 UTC (permalink / raw)
To: 21684; +Cc: Tino Calancha
> Thanks; I've now applied this to the trunk. Seems to be working great,
> and it's a feature I've missed for years.
Great! It has being my pleasure.
^ permalink raw reply [flat|nested] 27+ messages in thread
* bug#21684: 25.0.50; undo in query-replace w/o exit
2016-02-24 1:36 ` Lars Ingebrigtsen
2016-02-24 13:13 ` Tino Calancha
@ 2016-05-31 22:32 ` Glenn Morris
2016-06-01 2:44 ` Tino Calancha
2016-06-04 22:06 ` bug#21663: 25.0.50; isearch-edit-string dont resume multi isearches Juri Linkov
1 sibling, 2 replies; 27+ messages in thread
From: Glenn Morris @ 2016-05-31 22:32 UTC (permalink / raw)
To: Lars Ingebrigtsen; +Cc: Tino Calancha, 21684
Lars Ingebrigtsen wrote:
> Thanks; I've now applied this to the trunk. Seems to be working great,
> and it's a feature I've missed for years.
Was a copyright assignment ever completed?
I don't see one on file.
http://debbugs.gnu.org/21684#14
Juri Linkov wrote:
> Have you already signed FSF copyright assignment papers?
>
> Your patch for bug#21663 is short enough to be installed without the
> copyright paperwork, but your changes for bug#21684 require it.
^ permalink raw reply [flat|nested] 27+ messages in thread
* bug#21684: 25.0.50; undo in query-replace w/o exit
2016-05-31 22:32 ` Glenn Morris
@ 2016-06-01 2:44 ` Tino Calancha
2016-06-01 17:45 ` Glenn Morris
2016-06-04 22:06 ` bug#21663: 25.0.50; isearch-edit-string dont resume multi isearches Juri Linkov
1 sibling, 1 reply; 27+ messages in thread
From: Tino Calancha @ 2016-06-01 2:44 UTC (permalink / raw)
To: Glenn Morris; +Cc: Tino Calancha, 21684, Lars Ingebrigtsen
On Tue, 31 May 2016, Glenn Morris wrote:
> Was a copyright assignment ever completed?
> I don't see one on file.
>
> http://debbugs.gnu.org/21684#14
Yes it was, around November 2015: copyright assignment #1056152
Tino
^ permalink raw reply [flat|nested] 27+ messages in thread
* bug#21684: 25.0.50; undo in query-replace w/o exit
2016-06-01 2:44 ` Tino Calancha
@ 2016-06-01 17:45 ` Glenn Morris
2016-06-01 17:53 ` Lars Ingebrigtsen
0 siblings, 1 reply; 27+ messages in thread
From: Glenn Morris @ 2016-06-01 17:45 UTC (permalink / raw)
To: Tino Calancha; +Cc: 21684, Lars Ingebrigtsen
Tino Calancha wrote:
>> Was a copyright assignment ever completed?
>> I don't see one on file.
>>
>> http://debbugs.gnu.org/21684#14
>
> Yes it was, around November 2015: copyright assignment #1056152
Thanks. The semi-public file that records these things must not be
up-to-date (not for the first time). Not your problem. I'll ask the
relevant people.
^ permalink raw reply [flat|nested] 27+ messages in thread
* bug#21684: 25.0.50; undo in query-replace w/o exit
2016-06-01 17:45 ` Glenn Morris
@ 2016-06-01 17:53 ` Lars Ingebrigtsen
2016-06-01 17:56 ` Glenn Morris
0 siblings, 1 reply; 27+ messages in thread
From: Lars Ingebrigtsen @ 2016-06-01 17:53 UTC (permalink / raw)
To: Glenn Morris; +Cc: Tino Calancha, 21684
Glenn Morris <rgm@gnu.org> writes:
> Tino Calancha wrote:
>
>>> Was a copyright assignment ever completed?
>>> I don't see one on file.
>>>
>>> http://debbugs.gnu.org/21684#14
>>
>> Yes it was, around November 2015: copyright assignment #1056152
>
> Thanks. The semi-public file that records these things must not be
> up-to-date (not for the first time). Not your problem. I'll ask the
> relevant people.
It was the last time I fetched it, but the name is in a slightly
different format. :-)
Search for "Calancha". (I'm not sure I'm allowed to post the full name
from the assignment here.)
--
(domestic pets only, the antidote for overdose, milk.)
bloggy blog: http://lars.ingebrigtsen.no
^ permalink raw reply [flat|nested] 27+ messages in thread
* bug#21684: 25.0.50; undo in query-replace w/o exit
2016-06-01 17:53 ` Lars Ingebrigtsen
@ 2016-06-01 17:56 ` Glenn Morris
2016-06-02 16:44 ` Glenn Morris
0 siblings, 1 reply; 27+ messages in thread
From: Glenn Morris @ 2016-06-01 17:56 UTC (permalink / raw)
To: Lars Ingebrigtsen; +Cc: Tino Calancha, 21684
Lars Ingebrigtsen wrote:
> It was the last time I fetched it, but the name is in a slightly
> different format. :-)
>
> Search for "Calancha". (I'm not sure I'm allowed to post the full name
> from the assignment here.)
I don't think my grep-fu is to blame here. I generally try a broad search.
I've asked assign@gnu. There seem to be several missing entries AFAICS.
^ permalink raw reply [flat|nested] 27+ messages in thread
* bug#21684: 25.0.50; undo in query-replace w/o exit
2016-06-01 17:56 ` Glenn Morris
@ 2016-06-02 16:44 ` Glenn Morris
0 siblings, 0 replies; 27+ messages in thread
From: Glenn Morris @ 2016-06-02 16:44 UTC (permalink / raw)
To: Lars Ingebrigtsen; +Cc: Tino Calancha, 21684
Glenn Morris wrote:
> I've asked assign@gnu. There seem to be several missing entries AFAICS.
The file that records the info was indeed out-of-date (malfunctioning
cron job) and has now been fixed.
^ permalink raw reply [flat|nested] 27+ messages in thread
* bug#21663: 25.0.50; isearch-edit-string dont resume multi isearches
2016-05-31 22:32 ` Glenn Morris
2016-06-01 2:44 ` Tino Calancha
@ 2016-06-04 22:06 ` Juri Linkov
1 sibling, 0 replies; 27+ messages in thread
From: Juri Linkov @ 2016-06-04 22:06 UTC (permalink / raw)
To: 21663-done
> Lars Ingebrigtsen wrote:
>
>> Thanks; I've now applied this to the trunk. Seems to be working great,
>> and it's a feature I've missed for years.
>
> Was a copyright assignment ever completed?
> I don't see one on file.
>
> http://debbugs.gnu.org/21684#14
>
> Juri Linkov wrote:
>
>> Have you already signed FSF copyright assignment papers?
>>
>> Your patch for bug#21663 is short enough to be installed without the
>> copyright paperwork, but your changes for bug#21684 require it.
Thanks for the reminder. This is now installed (required merging
with other changes in the same function).
^ permalink raw reply [flat|nested] 27+ messages in thread
end of thread, other threads:[~2016-06-04 22:06 UTC | newest]
Thread overview: 27+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-10-14 13:26 bug#21684: 25.0.50; undo in query-replace w/o exit Tino Calancha
2015-10-14 16:23 ` Juri Linkov
2015-10-17 13:04 ` Tino Calancha
2015-10-17 21:49 ` Juri Linkov
2015-10-18 9:45 ` Tino Calancha
2015-10-18 15:58 ` Richard Stallman
2015-10-19 1:20 ` Tino Calancha
2015-10-19 22:04 ` Juri Linkov
2015-10-20 12:02 ` Tino Calancha
2016-02-23 8:40 ` Lars Ingebrigtsen
2016-02-23 16:46 ` Tino Calancha
2016-02-23 17:54 ` Eli Zaretskii
2016-02-24 1:36 ` Lars Ingebrigtsen
2016-02-24 13:13 ` Tino Calancha
2016-05-31 22:32 ` Glenn Morris
2016-06-01 2:44 ` Tino Calancha
2016-06-01 17:45 ` Glenn Morris
2016-06-01 17:53 ` Lars Ingebrigtsen
2016-06-01 17:56 ` Glenn Morris
2016-06-02 16:44 ` Glenn Morris
2016-06-04 22:06 ` bug#21663: 25.0.50; isearch-edit-string dont resume multi isearches Juri Linkov
2015-10-26 4:09 ` bug#21684: 25.0.50; undo in query-replace w/o exit Richard Stallman
[not found] ` <handler.21684.B.144482901430164.ack@debbugs.gnu.org>
2015-10-20 13:01 ` bug#21684: Acknowledgement (25.0.50; undo in query-replace w/o exit) Tino Calancha
-- strict thread matches above, loose matches on Subject: below --
2015-10-11 4:57 bug#21663: Subject: 25.0.50; isearch-edit-string dont resume multi isearches Tino Calancha
[not found] ` <handler.21663.B.144453929427612.ack@debbugs.gnu.org>
2015-10-13 5:18 ` bug#21663: " Tino Calancha
2015-10-13 22:04 ` Juri Linkov
2015-10-14 6:48 ` Tino Calancha
2015-10-14 16:17 ` 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).