diff --git a/cider-interaction.el b/cider-interaction.el index d4db5da0f..3575f2ce5 100644 --- a/cider-interaction.el +++ b/cider-interaction.el @@ -811,13 +811,20 @@ into a new error buffer." (cond (class (cons response causes)) (status (cider--render-stacktrace-causes causes))))) -(defun cider-default-err-op-handler () - "Display the last exception, with middleware support." +(defun cider-default-err-op-handler (&optional storage-key) + "Display an exception, with middleware support. +If optional argument STORAGE-KEY is not given, will return the most recent +exception bound to *e; this binding typically happens during a non-sync +`eval` op. Optional argument STORAGE-KEY will look up a stored exception +instead of trying to use the *e bound exception; this is useful when the +error occurred due to a sync request op which typically do not bind *e." ;; Causes are returned as a series of messages, which we aggregate in `causes' (let (causes) (cider-nrepl-send-request (append (list "op" "stacktrace" "session" (cider-current-session)) + (when storage-key + (list "storage-key" storage-key)) (when (cider--pprint-fn) (list "pprint-fn" (cider--pprint-fn))) (when cider-stacktrace-print-length @@ -830,11 +837,15 @@ into a new error buffer." ;; after it has been handled, so it's fine to set it unconditionally here (setq causes (cider--handle-stacktrace-response response causes)))))) -(defun cider-default-err-handler () +(defun cider-default-err-handler (&optional storage-key) "This function determines how the error buffer is shown. -It delegates the actual error content to the eval or op handler." +It delegates the actual error content to the eval or op handler. +Optional argument STORAGE-KEY will be passed to the op handler to help +retrieve a stored exception instead of trying to use the *e bound +exception; this is useful when the error occurred due to a sync request op +which typically do not bind *e." (if (cider-nrepl-op-supported-p "stacktrace") - (cider-default-err-op-handler) + (cider-default-err-op-handler storage-key) (cider-default-err-eval-handler))) (defvar cider-compilation-regexp diff --git a/nrepl-client.el b/nrepl-client.el index bdab522a8..c00c9c4b6 100644 --- a/nrepl-client.el +++ b/nrepl-client.el @@ -965,16 +965,11 @@ sign of user input, so as not to hang the interface." (when (member "done" status) (when-let ((ex (nrepl-dict-get response "ex")) (err (nrepl-dict-get response "err"))) - ;; non-eval requests currently don't set the *e var - ;; which is required by the stacktrace middleware - ;; so we have to handle them differently until this is resolved - (if (member "eval-error" status) - (funcall nrepl-err-handler) - ;; dump the stacktrace in the REPL - ;; TODO: This has to be replaced with rendering of the - ;; standard stacktrace buffer - (cider-repl-emit-interactive-stderr err) - (switch-to-buffer-other-window connection))) + ;; Non-eval requests currently don't set the *e var + ;; but instead get stored in util/storage, the storage-key + ;; lets us retrieve these errors. If there's no storage-key, + ;; then this will end up returning *e. + (funcall nrepl-err-handler (nrepl-dict-get response "storage-key"))) (when-let ((id (nrepl-dict-get response "id"))) (with-current-buffer connection (nrepl--mark-id-completed id)))