-
-
Notifications
You must be signed in to change notification settings - Fork 68
Description
Summary:
the advice function transient--recursive-edit incorrectly handles unwinds from using e.g. (throw 'exit t) from within a recursive edit.
This appeared for me when using a function similar to read-string-from-buffer.
Reproduced in emacs -q with only (require 'transient)
Steps:
first, define a modified read-string-from-buffer. the key difference is the (throw 'exit "Aborted edit"), which causes the recursive edit to signal an error when the user presses C-c C-k.
(defun my/read-string-from-buffer (prompt string)
(string-edit
prompt
string
(lambda (edited)
(setq string edited)
(exit-recursive-edit))
:abort-callback (lambda ()
(throw 'exit "Aborted edit")))
(recursive-edit)
string)
next, define a transient that relies on this behaviour, handling the error with some specific behaviour:
(transient-define-prefix foo-prefix ()
["args"
("-m" "message" "--message="
:reader (lambda (p s h)
(condition-case er
(my/read-string-from-buffer p (or s ""))
(error (prog1 "cancel"
(princ er))))))
("-o" "other" "--other-infix")
("-a" "another" "--another-infix=")])
finally, invoke the foo-prefix, invoke the -m infix, and cancel the input buffer with C-c C-k.
Expected:
The transient returns to the foo-prefix with --message=cancel.
Actual:
The transient buffer is left in a broken state and does not accept further interaction. typing simply types into the active buffer rather than affecting the transient.
Remarks:
- I have not bothered with a backtrace as the relevant error never reaches the toplevel.
- I have a patch incoming to resolve this, but it is fairly simple. The issue seems to be the lack of an
unwind-protectin the tail end oftransient--recursive-edit.