[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[nongnu] elpa/evil 8a3ac25680: Fix evil-with-undo/evil-undo-pop with und
From: |
ELPA Syncer |
Subject: |
[nongnu] elpa/evil 8a3ac25680: Fix evil-with-undo/evil-undo-pop with undo-tree |
Date: |
Sat, 7 Jan 2023 15:58:58 -0500 (EST) |
branch: elpa/evil
commit 8a3ac256804a4786bd8adbf6a3f6925162e2722f
Author: Toby S. Cubitt <tsc25@cantab.net>
Commit: Axel Forsman <axelsfor@gmail.com>
Fix evil-with-undo/evil-undo-pop with undo-tree
Addresses #1074
- evil-with-undo:
nconc'ing onto front of buffer-undo-list here can corrupt buffer-undo-list
when in undo-tree-mode in rare circumstances (see issue #1074). Leave
standard undo machinery to work as usual when undo is enabled. Deal with
disabled undo by temporarily enabling then disabling undo, and
transferring
any undo changes to evil-temporary-undo.
- evil-undo-pop:
This function called `undo' directly from Elisp, which is wrong when in
undo-tree-mode. Fix this by calling undo-tree-undo instead when in
undo-tree-mode.
Co-authored-by: Axel Forsman <axelsfor@gmail.com>
---
evil-common.el | 69 ++++++++++++++++++++++++++++++++++------------------------
1 file changed, 40 insertions(+), 29 deletions(-)
diff --git a/evil-common.el b/evil-common.el
index ae03ae8b90..a9d511f257 100644
--- a/evil-common.el
+++ b/evil-common.el
@@ -3629,6 +3629,14 @@ If no description is available, return the empty string."
;;; Undo
+(defvar buffer-undo-tree)
+(declare-function undo-tree-current "ext:undo-tree")
+(declare-function undo-tree-node-next "ext:undo-tree")
+(declare-function undo-tree-node-branch "ext:undo-tree")
+(declare-function undo-tree-node-branch "ext:undo-tree")
+(declare-function undo-tree-undo "ext:undo-tree")
+(declare-function undo-tree-snip-node "ext:undo-tree")
+
(defun evil-start-undo-step (&optional continue)
"Start a undo step.
All following buffer modifications are grouped together as a
@@ -3667,46 +3675,49 @@ make the entries undoable as a single action. See
"Execute BODY with enabled undo.
If undo is disabled in the current buffer, the undo information
is stored in `evil-temporary-undo' instead of `buffer-undo-list'."
- (declare (indent defun)
- (debug t))
- `(unwind-protect
- (let (buffer-undo-list)
- (unwind-protect
- (progn ,@body)
- (setq evil-temporary-undo buffer-undo-list)
- ;; ensure evil-temporary-undo starts with exactly one undo
- ;; boundary marker, i.e. nil
- (unless (null (car-safe evil-temporary-undo))
- (push nil evil-temporary-undo))))
- (unless (eq buffer-undo-list t)
- ;; undo is enabled, so update the global buffer undo list
- (setq buffer-undo-list
- ;; prepend new undos (if there are any)
- (if (cdr evil-temporary-undo)
- (nconc evil-temporary-undo buffer-undo-list)
- buffer-undo-list)
- evil-temporary-undo nil))))
+ (declare (debug t))
+ (let ((undo-list (make-symbol "undo-list")))
+ `(let ((,undo-list buffer-undo-list)
+ (evil-undo-system evil-undo-system))
+ (when (eq ,undo-list t) (setq buffer-undo-list nil
+ evil-undo-system nil))
+ (unwind-protect
+ (progn ,@body)
+ ;; ensure any new undo changes we've accumulated start with
+ ;; exactly one undo boundary marker, i.e. nil
+ (when (car-safe buffer-undo-list) (push nil buffer-undo-list))
+ (if (eq ,undo-list t)
+ ;; undo is disabled, so store undo information in
+ ;; evil-temporary-undo
+ (setq evil-temporary-undo buffer-undo-list
+ buffer-undo-list t)
+ (setq evil-temporary-undo nil))))))
(defmacro evil-with-single-undo (&rest body)
"Execute BODY as a single undo step."
- (declare (indent defun)
- (debug t))
+ (declare (debug t))
`(let (evil-undo-list-pointer)
(evil-with-undo
+ (evil-start-undo-step)
(unwind-protect
- (progn
- (evil-start-undo-step)
- (let ((evil-in-single-undo t))
- ,@body))
+ (let ((evil-in-single-undo t)) ,@body)
(evil-end-undo-step)))))
(defun evil-undo-pop ()
- "Undo the last buffer change.
-Removes the last undo information from `buffer-undo-list'.
+ "Undo and forget the last buffer change.
If undo is disabled in the current buffer, use the information
in `evil-temporary-undo' instead."
- (let ((paste-undo (list nil)))
- (let ((undo-list (if (eq buffer-undo-list t)
+ (if (and (eq evil-undo-system 'undo-tree)
+ (not (eq buffer-undo-list t)))
+ (let (current)
+ (undo-tree-undo)
+ (setq current (undo-tree-current buffer-undo-tree)
+ current (nth (undo-tree-node-branch current)
+ (undo-tree-node-next current)))
+ ;; Remove only if leaf to not have to adjust child buffer positions
+ (unless (undo-tree-node-next current) (undo-tree-snip-node current)))
+ (let ((paste-undo (list nil))
+ (undo-list (if (eq buffer-undo-list t)
evil-temporary-undo
buffer-undo-list)))
(when (or (not undo-list) (car undo-list))
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [nongnu] elpa/evil 8a3ac25680: Fix evil-with-undo/evil-undo-pop with undo-tree,
ELPA Syncer <=