From: phillip.lord@russet.org.uk (Phillip Lord)
To: Stefan Monnier <monnier@IRO.UMontreal.CA>
Cc: Chong Yidong <cyd@gnu.org>, 23632@debbugs.gnu.org
Subject: bug#23632: 25.1.50; Gratuitous undo boundary in latex-insert-block
Date: Fri, 03 Jun 2016 17:13:19 +0100 [thread overview]
Message-ID: <87shwutfmo.fsf@russet.org.uk> (raw)
In-Reply-To: <jwvoa7ibf7m.fsf-monnier+emacsbugs@gnu.org> (Stefan Monnier's message of "Fri, 03 Jun 2016 09:00:47 -0400")
[-- Attachment #1: Type: text/plain, Size: 923 bytes --]
Stefan Monnier <monnier@IRO.UMontreal.CA> writes:
>> 1) undo-auto--undoably-changed-buffers becomes an alist
>
>> ((0 . (buffers*))
>> (1 . (buffers*))
>> (2 . (buffers*)))
>
>> where the key is the return of (recursion-depth)
>
>> 2) undo-auto--boundaries operates only on buffers at the
>> current-recursion-depth. Or, probably, at the current of greater
>> recursion depth, to ensure that undo-buffers happens when a recursive
>> edit exits.
>
> Hmm... sounds pretty good, and I think you can do it more simply:
> just let-bind undo-auto--undoably-changed-buffers to nil when entering
> a recursive edit.
Tried it before I got your mail. Seems to function.
Simple let binding would not give quite the same functionality, because
of the last part -- I also add a boundary to buffers with a greater
recursive depth; with a let binding, I think these would be unbound for
commands that lower the recursion depth.
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Add-undo-boundaries-based-on-recursion-depth.patch --]
[-- Type: text/x-diff, Size: 8031 bytes --]
From 018429dafe1395e0927934fd95d65b74c69b2d07 Mon Sep 17 00:00:00 2001
From: Phillip Lord <phillip.lord@russet.org.uk>
Date: Mon, 30 May 2016 22:50:36 +0100
Subject: [PATCH] Add undo-boundaries based on recursion depth
* lisp/simple.el (undo-auto--undoably-changed-buffers): Now an alist
which stores recursion depth as well as
changes.
(undo-auto--boundaries): Add boundaries only to buffers at
current or higher recursion depth.
(undo-auto--undoable-change): Adjust for other changes.
(undo-auto--extract-buffers, undo-auto--undoable-change-1): New
functions.
Addresses #23632
---
lisp/simple.el | 66 +++++++++++++++++++++++++-----
test/automated/simple-test.el | 94 ++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 149 insertions(+), 11 deletions(-)
diff --git a/lisp/simple.el b/lisp/simple.el
index c5aa292..d55d9b0 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -2867,7 +2867,7 @@ undo-auto--last-boundary-amalgamating-number
that calls `undo-auto-amalgamate'."
(car-safe undo-auto--last-boundary-cause))
-(defun undo-auto--ensure-boundary (cause)
+(defun undo-auto--ensure-boundary (changed-buffers cause)
"Add an `undo-boundary' to the current buffer if needed.
REASON describes the reason that the boundary is being added; see
`undo-auto--last-boundary' for more information."
@@ -2880,19 +2880,44 @@ undo-auto--ensure-boundary
(if (eq 'amalgamate cause)
(cons
(if last-amalgamating (1+ last-amalgamating) 0)
- undo-auto--undoably-changed-buffers)
+ changed-buffers)
cause)))))
+(defun undo-auto--extract-buffers (depth buffer-list &optional no-change)
+ "Extract buffers from BUFFER-LIST at DEPTH or deeper.
+
+This expects BUFFER-LIST to be of the form of
+`undo-auto--undoably-changed-buffers'. The relevant buffers are
+returned, and removed from BUFFER-LIST by side effect.
+
+If NO-CHANGE is non-nil, do not alter BUFFER-LIST."
+ (let ((rtn))
+ (dolist (level-and-buffer buffer-list)
+ (when (<= depth
+ (car level-and-buffer))
+ (dolist (b (cdr level-and-buffer))
+ (setq rtn (cons b rtn)))
+ (unless no-change
+ (setcdr level-and-buffer nil))))
+ rtn))
+
(defun undo-auto--boundaries (cause)
"Check recently changed buffers and add a boundary if necessary.
REASON describes the reason that the boundary is being added; see
`undo-last-boundary' for more information."
- (dolist (b undo-auto--undoably-changed-buffers)
- (when (buffer-live-p b)
- (with-current-buffer b
- (unless undo-auto-disable-boundaries
- (undo-auto--ensure-boundary cause)))))
- (setq undo-auto--undoably-changed-buffers nil))
+ ;; We must account for recusion depth in general, and also
+ ;; specifically, to cope with changes in the minibuffer (see bug
+ ;; #23632).
+ (let ((changed-buffers
+ (undo-auto--extract-buffers
+ (recursion-depth)
+ ;; This is updated by side effect.
+ undo-auto--undoably-changed-buffers)))
+ (dolist (b changed-buffers)
+ (when (buffer-live-p b)
+ (with-current-buffer b
+ (unless undo-auto-disable-boundaries
+ (undo-auto--ensure-boundary changed-buffers cause)))))))
(defun undo-auto--boundary-timer ()
"Timer which will run `undo--auto-boundary-timer'."
@@ -2912,6 +2937,10 @@ undo-auto--undoably-changed-buffers
`undo-auto--boundaries' and can be affected by changes to their
default values.
+It is an list of conses whose car is the last returned value of
+`recursion-depth', and whose cdr is the list of changed buffers at that
+depth.
+
See also `undo-auto--buffer-undoably-changed'.")
(defun undo-auto--add-boundary ()
@@ -2955,9 +2984,26 @@ undo-auto-amalgamate
(cdr buffer-undo-list))))))
(setq undo-auto--last-boundary-cause 0)))))
-(defun undo-auto--undoable-change ()
+(defun undo-auto--undoable-change-1 (depth buffer changed-buffers)
"Called after every undoable buffer change."
- (add-to-list 'undo-auto--undoably-changed-buffers (current-buffer))
+ (let ((buffers-for-depth (assoc depth changed-buffers)))
+ (if buffers-for-depth
+ (progn
+ (setcdr buffers-for-depth
+ (cons buffer (cdr buffers-for-depth)))
+ changed-buffers)
+ (cons
+ (list
+ depth
+ buffer)
+ changed-buffers))))
+
+(defun undo-auto--undoable-change ()
+ (setq undo-auto--undoably-changed-buffers
+ (undo-auto--undoable-change-1
+ (recursion-depth)
+ (current-buffer)
+ undo-auto--undoably-changed-buffers))
(undo-auto--boundary-ensure-timer))
;; End auto-boundary section
diff --git a/test/automated/simple-test.el b/test/automated/simple-test.el
index 12ebc75..57dbbf0 100644
--- a/test/automated/simple-test.el
+++ b/test/automated/simple-test.el
@@ -237,7 +237,9 @@ simple-test--transpositions
(with-temp-buffer
(setq buffer-undo-list nil)
(insert "hello")
- (member (current-buffer) undo-auto--undoably-changed-buffers)))
+ (member (current-buffer)
+ (assoc 0
+ undo-auto--undoably-changed-buffers))))
;; The head of buffer-undo-list should be the insertion event, and
;; therefore not nil
(should
@@ -310,6 +312,96 @@ undo-test-point-after-forward-kill
(= 6
(undo-test-point-after-forward-kill))))
+(ert-deftest simple-test-undo--auto-undoable-change-1 ()
+ (should
+ (equal
+ '((0 a))
+ (undo-auto--undoable-change-1 0 'a nil)))
+ (should
+ (equal
+ '((0 b a))
+ (undo-auto--undoable-change-1
+ 0 'b
+ '((0 a)))))
+ (should
+ (equal
+ '((1 c)
+ (0 a))
+ (undo-auto--undoable-change-1
+ 1 'c '((0 a))))))
+
+(ert-deftest simple-test-undo-auto--extract-buffers ()
+ (should
+ (equal
+ (list
+ '((1)
+ (0 a))
+ '(c))
+ (let
+ ((buffer-list
+ '((1 c)
+ (0 a))))
+ (list
+ buffer-list
+ (undo-auto--extract-buffers
+ 1 buffer-list))))))
+
+;; These macros are lifted from assess-robot.el, and should be removed
+;; when that comes into core.
+(defmacro simple-test-with-switched-buffer (buffer &rest body)
+ (declare (indent 1) (debug t))
+ (let ((before-buffer (make-symbol "before-buffer")))
+ `(let ((,before-buffer (current-buffer)))
+ (unwind-protect
+ (progn
+ (switch-to-buffer ,buffer)
+ ,@body)
+ (switch-to-buffer ,before-buffer)))))
+
+(defmacro simple-test-with-temp-switched-buffer (&rest body)
+ (declare (indent 0) (debug t))
+ (let ((temp-buffer (make-symbol "temp-buffer")))
+ `(let ((,temp-buffer (generate-new-buffer " *temp*")))
+ (simple-test-with-switched-buffer ,temp-buffer
+ (unwind-protect
+ (progn
+ (setq buffer-undo-list nil)
+ ,@body)
+ (and (buffer-name ,temp-buffer)
+ ;(kill-buffer ,temp-buffer)
+ ))))))
+
+(ert-deftest simple-test-undo-amalgamation ()
+ ;; We should undo 0123456789 but not hello
+ (should
+ (string=
+ "hello
+"
+ (simple-test-with-temp-switched-buffer
+ (execute-kbd-macro
+ (read-kbd-macro
+ "
+hello ;; self-insert-command
+RET ;; newline
+0123456789 ;; self-insert-command
+C-/ ;; undo
+"
+ ))
+ (buffer-substring-no-properties (point-min)
+ (point-max)))))
+ ;; we should leave 20 characters in the buffer
+ (should
+ (string=
+ "012345678901234567890"
+ (simple-test-with-temp-switched-buffer
+ (execute-kbd-macro
+ (read-kbd-macro
+ "
+012345678901234567890123456789 ;; self-insert-command
+C-/ ;; undo"))
+ (buffer-substring-no-properties
+ (point-min)
+ (point-max))))))
(provide 'simple-test)
;;; simple-test.el ends here
--
2.8.3
next prev parent reply other threads:[~2016-06-03 16:13 UTC|newest]
Thread overview: 24+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-05-27 15:11 bug#23632: 25.1.50; Gratuitous undo boundary in latex-insert-block Chong Yidong
2016-05-28 8:22 ` Chong Yidong
2016-05-29 21:51 ` Phillip Lord
2016-05-31 21:42 ` Phillip Lord
2016-06-01 13:15 ` Stefan Monnier
2016-06-02 20:08 ` Phillip Lord
2016-06-03 13:00 ` Stefan Monnier
2016-06-03 16:13 ` Phillip Lord [this message]
2016-06-03 17:00 ` Stefan Monnier
2016-06-03 22:18 ` Phillip Lord
2016-06-04 3:05 ` Stefan Monnier
2016-06-04 8:51 ` Phillip Lord
2016-06-04 16:49 ` Stefan Monnier
2016-06-04 17:17 ` Phillip Lord
2016-06-04 18:41 ` Stefan Monnier
2016-06-06 14:33 ` Phillip Lord
2016-06-06 15:02 ` Stefan Monnier
2016-06-06 15:36 ` Phillip Lord
2016-06-06 15:26 ` Eli Zaretskii
2016-06-06 15:38 ` Phillip Lord
2016-06-06 16:22 ` Eli Zaretskii
2016-06-07 11:20 ` Phillip Lord
2016-06-07 15:09 ` Eli Zaretskii
2016-06-03 2:58 ` Chong Yidong
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87shwutfmo.fsf@russet.org.uk \
--to=phillip.lord@russet.org.uk \
--cc=23632@debbugs.gnu.org \
--cc=cyd@gnu.org \
--cc=monnier@IRO.UMontreal.CA \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this external index
https://git.savannah.gnu.org/cgit/emacs.git
https://git.savannah.gnu.org/cgit/emacs/org-mode.git
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.