summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonas Bernoulli <jonas@bernoul.li>2026-03-05 22:44:47 +0100
committerJonas Bernoulli <jonas@bernoul.li>2026-03-05 22:44:47 +0100
commitecb2005d2e6c0584c864429879f641034fbc7be5 (patch)
tree7e37972b6c9efec2dcb873dce53585b5852ef40d
parentcde0756fb1e30fa1629a2b69f1dfe0f12510adcf (diff)
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.
-rw-r--r--lisp/transient.el24
1 files changed, 17 insertions, 7 deletions
diff --git a/lisp/transient.el b/lisp/transient.el
index 379c888..b3b6646 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"))