branch: externals/transient
commit ecb2005d2e6c0584c864429879f641034fbc7be5
Author: Jonas Bernoulli <[email protected]>
Commit: Jonas Bernoulli <[email protected]>

    transient--recursive-edit: Actually handle aborts as intended
    
    For context, read the docstring of `recursive-edit'.  In our case it
    is most suitable if the recursive edit is exited using the "any other
    value" variant, but that isn't guaranteed, so we have to handle the
    other exit variants as well.
    
    Wrap the call to `recursive-edit' with `unwind-protect' to ensure we
    regain control, when `recursive-edit' returns to the command loop one
    level up (i.e., our level).  We use this to either completely exit or
    completely restore the menu.
    
    If (throw 'exit t) is used to abort the recursive edit, then we also
    exit the menu.  (This is a design decision.)  We can only detect this
    if it was done by invoking `abort-recursive-edit' as a command.
    
    If this form was evaluated through other means, we end up restoring the
    menu.  However this also causes "C-g" to be immediately unread, which
    results in `transient-quit-one' being invoked, so the menu is exited
    anyway.  Needlessly restoring the menu first is unfortunate, but not a
    big deal (users won't notice).
    
    Additionally wrap the `unwind-protect' with `condition-case'.  This is
    needed to deal with the (throw 'exit "'error' message") variant.  This
    variant is commonly used to print an abort message, which isn't really
    an error as far as we are concerned.  We want to demote "abort errors"
    to messages.
    
    Unfortunately "abort errors" do not use a dedicated error type (see
    `recursive_edit_1'), and `condition-case' can only match against error
    types (symbols), meaning that it cannot distinguish an abort from a
    genuine error.  As a consequence we are stuck demoting both abort
    messages and genuine error messages.
    
    Closes #425.
    Closes #426.
---
 lisp/transient.el | 24 +++++++++++++++++-------
 1 file changed, 17 insertions(+), 7 deletions(-)

diff --git a/lisp/transient.el b/lisp/transient.el
index 379c88894c..b3b66464d9 100644
--- a/lisp/transient.el
+++ b/lisp/transient.el
@@ -2960,13 +2960,23 @@ value.  Otherwise return CHILDREN as is.")
   (if (not transient--prefix)
       (funcall fn)
     (transient--suspend-override (bound-and-true-p edebug-active))
-    (funcall fn) ; Already unwind protected.
-    (cond ((memq this-command '(top-level abort-recursive-edit))
-           (setq transient--exitp t)
-           (transient--post-exit this-command)
-           (transient--delete-window))
-          (transient--prefix
-           (transient--resume-override)))))
+    (condition-case err
+        (unwind-protect
+            (funcall fn)
+          (cond
+            ((memq this-command '(top-level abort-recursive-edit))
+             (setq transient--exitp t)
+             (transient--post-exit this-command)
+             (transient--delete-window)
+             (transient--debug "     abort recursive-edit and menu "))
+            (transient--prefix
+             (transient--resume-override)
+             (transient--debug "     exit recursive-edit and resumed menu"))))
+      (error (if (and (eq (car err) 'error)
+                      (stringp (cadr err))
+                      (string-prefix-p "Abort" (cadr err)))
+                 (message "%s" (cadr err))
+               (message "transient--recursive-edit: %S" err))))))
 
 (defmacro transient--with-suspended-override (&rest body)
   (let ((depth (make-symbol "depth"))

Reply via email to