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"))