emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[nongnu] elpa/undo-fu 8b00b16fa8 46/82: Non-destructive commands no long


From: ELPA Syncer
Subject: [nongnu] elpa/undo-fu 8b00b16fa8 46/82: Non-destructive commands no longer break the undo-chain
Date: Thu, 7 Jul 2022 12:04:53 -0400 (EDT)

branch: elpa/undo-fu
commit 8b00b16fa87499dc63b25010ec5738a4f94c9bf8
Author: Campbell Barton <ideasman42@gmail.com>
Commit: Campbell Barton <ideasman42@gmail.com>

    Non-destructive commands no longer break the undo-chain
    
    Remove 'last-command' use for detecting edits.
---
 changelog.rst |  2 ++
 undo-fu.el    | 63 +++++++++++++++++++++++++++++++++++------------------------
 2 files changed, 40 insertions(+), 25 deletions(-)

diff --git a/changelog.rst b/changelog.rst
index 51579514e7..371c64ec53 100644
--- a/changelog.rst
+++ b/changelog.rst
@@ -5,6 +5,8 @@ Change Log
 
 - In development.
 
+  - Support non-destructive commands between undo/redo actions without 
breaking the chain.
+    Internally ``last-command`` is no longer used to detect changes.
   - Add ``undo-fu-ignore-keyboard-quit`` option for explicit non-linear 
behavior.
   - Support using ``undo-fu-only-redo`` after regular ``undo`` / ``undo-only``.
 
diff --git a/undo-fu.el b/undo-fu.el
index 037f451aa0..52ab6f91ba 100644
--- a/undo-fu.el
+++ b/undo-fu.el
@@ -73,6 +73,9 @@ Instead, explicitly call `undo-fu-disable-checkpoint'."
 ;; Initiated an undo-in region (don't use `undo-only').
 ;; Only use when `undo-fu-allow-undo-in-region' is true.
 (defvar-local undo-fu--in-region nil)
+;; Track the last undo/redo direction.
+;; Use in conjunction with `undo-fu--was-undo-or-redo'.
+(defvar-local undo-fu--was-redo nil)
 
 ;; ---------------------------------------------------------------------------
 ;; Internal Functions/Macros
@@ -147,13 +150,12 @@ Returns the number of steps to reach this list or 
COUNT-LIMIT."
       pending-undo-list)
     list-to-find count-limit))
 
-(defun undo-fu--was-undo ()
-  "Return t when the last command was undo."
-  (not (null (member last-command '(undo undo-fu-only-undo)))))
-
-(defun undo-fu--was-redo ()
-  "Return t when the last command was redo."
-  (not (null (member last-command '(undo-fu-only-redo)))))
+(defun undo-fu--was-undo-or-redo ()
+  "Return t when the last destructive action was undo or redo."
+  (let ((undo-list buffer-undo-list))
+    (while (and (consp undo-list) (eq (car undo-list) nil))
+      (setq undo-list (cdr undo-list)))
+    (not (null (gethash undo-list undo-equiv-table)))))
 
 ;; ---------------------------------------------------------------------------
 ;; Public Functions
@@ -166,19 +168,15 @@ This command is needed when 
`undo-fu-ignore-keyboard-quit' is t,
 since in this case `keyboard-quit' cannot be used
 to perform unconstrained undo/redo actions."
   (interactive)
-  (let ((was-undo-or-redo (or (undo-fu--was-undo) (undo-fu--was-redo))))
-    ;; Display an appropriate message.
-    (if was-undo-or-redo
-      (if (and undo-fu--respect undo-fu--checkpoint)
-        (message "Undo checkpoint cleared!")
-        (message "Undo checkpoint already cleared!"))
-      (message "Undo checkpoint disabled for next undo action!"))
+  ;; Display an appropriate message.
+  (if (undo-fu--was-undo-or-redo)
+    (if (and undo-fu--respect undo-fu--checkpoint)
+      (message "Undo checkpoint cleared!")
+      (message "Undo checkpoint already cleared!"))
+    (message "Undo checkpoint disabled for next undo action!"))
 
-    (undo-fu--checkpoint-disable)
+  (undo-fu--checkpoint-disable))
 
-    (when was-undo-or-redo
-      (setq this-command last-command)
-      (setq real-this-command real-last-command))))
 
 ;;;###autoload
 (defun undo-fu-only-redo-all ()
@@ -202,9 +200,9 @@ Optional argument ARG The number of steps to redo."
 
   (let*
     ( ;; Assign for convenience.
-      (was-undo (undo-fu--was-undo))
-      (was-redo (undo-fu--was-redo))
-      (was-undo-or-redo (or was-undo was-redo))
+      (was-undo-or-redo (undo-fu--was-undo-or-redo))
+      (was-redo (and was-undo-or-redo undo-fu--was-redo))
+      (was-undo (and was-undo-or-redo (null was-redo)))
       (undo-fu-quit-command
         (if undo-fu-ignore-keyboard-quit
           'undo-fu-disable-checkpoint
@@ -263,13 +261,19 @@ Optional argument ARG The number of steps to redo."
               (eq (last list undo-fu--checkpoint-length) undo-fu--checkpoint))
             (setq pending-undo-list list)))))
 
+    (when undo-fu--respect
+      (when (or (null was-undo-or-redo) (null undo-fu--checkpoint))
+        (user-error
+          "Redo without undo step (%s to ignore)"
+          (substitute-command-keys (format "\\[%s]" (symbol-name 
undo-fu-quit-command))))))
+
     (let*
       (
         ;; It's important to clamp the number of steps before assigning
         ;; 'last-command' since it's used when checking the available steps.
         (steps
           (if (numberp arg)
-            (if (and undo-fu--respect undo-fu--checkpoint)
+            (if undo-fu--respect
               (let ((steps-test (undo-fu--count-redo-available 
undo-fu--checkpoint arg was-undo)))
 
                 ;; Ensure the next steps is a redo action.
@@ -290,6 +294,11 @@ Optional argument ARG The number of steps to redo."
             (was-redo
               ;; Checked by the undo function.
               'undo)
+            ((string-equal last-command 'keyboard-quit)
+              ;; This case needs to be explicitly detected.
+              ;; If we undo until there is no undo information left,
+              ;; then press `keyboard-quit' and redo, it fails without this 
case.
+              'ignore)
             (t
               ;; No change.
               last-command)))
@@ -307,6 +316,9 @@ Optional argument ARG The number of steps to redo."
                 (message "%s" (error-message-string err))
                 nil)))))
 
+      (when success
+        (setq undo-fu--was-redo t))
+
       (setq this-command 'undo-fu-only-redo)
       success)))
 
@@ -321,9 +333,7 @@ Optional argument ARG the number of steps to undo."
 
   (let*
     ( ;; Assign for convenience.
-      (was-undo (undo-fu--was-undo))
-      (was-redo (undo-fu--was-redo))
-      (was-undo-or-redo (or was-undo was-redo))
+      (was-undo-or-redo (undo-fu--was-undo-or-redo))
       (undo-fu-quit-command
         (if undo-fu-ignore-keyboard-quit
           'undo-fu-disable-checkpoint
@@ -386,6 +396,9 @@ Optional argument ARG the number of steps to undo."
                 (message "%s" (error-message-string err))
                 nil)))))
 
+      (when success
+        (setq undo-fu--was-redo nil))
+
       (setq this-command 'undo-fu-only-undo)
       success)))
 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]