branch: elpa/cider
commit c374b18fe726204bb61cacac0370409e2f04bc1b
Author: vemv <[email protected]>
Commit: GitHub <[email protected]>
`cider-pprint-eval-last-sexp`: use error overlays to indicate failure
(#3558)
* `cider-pprint-eval-last-sexp`, `cider-eval-last-sexp-to-repl`,
`cider-pprint-eval-last-sexp-to-repl`: use error overlays to indicate failure
This also avoids showing an empty `*cider-result*` buffer.
Fixes https://github.com/clojure-emacs/cider/issues/3553
---
CHANGELOG.md | 2 +
cider-eval.el | 152 ++++++++++++++++++++++++++++++++++++++++------------------
2 files changed, 107 insertions(+), 47 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9ebe833385..cfa114d42e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,8 @@
- Improves performance for completions- and info-related functionality.
- Updates
[Orchard](https://github.com/clojure-emacs/orchard/blob/v0.18.0/CHANGELOG.md#0180-2023-10-30)
- Improves various Inspector presentational aspects.
+- [#3553](https://github.com/clojure-emacs/cider/issues/3553):
`cider-pprint-eval-last-sexp`, `cider-eval-last-sexp-to-repl`,
`cider-pprint-eval-last-sexp-to-repl`: use error overlays to indicate failure.
+ - this also avoids showing an empty `*cider-result*` buffer.
- [#3554](https://github.com/clojure-emacs/cider/issues/3554): CIDER
macroexpand: handle errors more gracefully.
### Bugs fixed
diff --git a/cider-eval.el b/cider-eval.el
index 73d914c55d..790dfb9cbd 100644
--- a/cider-eval.el
+++ b/cider-eval.el
@@ -746,24 +746,46 @@ evaluation command. Honor `cider-auto-jump-to-error'."
;;; Interactive evaluation handlers
-(defun cider-insert-eval-handler (&optional buffer)
- "Make an nREPL evaluation handler for the BUFFER.
+(defun cider-insert-eval-handler (&optional buffer bounds source-buffer
on-success-callback)
+ "Make an nREPL evaluation handler for the BUFFER,
+BOUNDS representing the buffer bounds of the evaled input,
+SOURCE-BUFFER the original buffer,
+and ON-SUCCESS-CALLBACK an optional callback.
+
The handler simply inserts the result value in BUFFER."
(let ((eval-buffer (current-buffer))
- (res ""))
+ (res "")
+ (failed nil))
(nrepl-make-response-handler (or buffer eval-buffer)
+ ;; value handler:
(lambda (_buffer value)
(with-current-buffer buffer
(insert value))
(when cider-eval-register
(setq res (concat res value))))
+ ;; stdout handler:
(lambda (_buffer out)
(cider-repl-emit-interactive-stdout out))
+ ;; stderr handler:
(lambda (_buffer err)
+ (setq failed t)
+ (when (and source-buffer
+ (listp bounds)) ;; if it's a
list, it represents bounds, otherwise it's a string (code) and we can't display
the overlay
+ (with-current-buffer source-buffer
+ (let* ((phase
(cider--error-phase-of-last-exception buffer))
+ (end (or (car-safe (cdr-safe
bounds)) bounds))
+ (end (when end
+ (copy-marker end))))
+
(cider--maybe-display-error-as-overlay phase err end))))
+
(cider-handle-compilation-errors err
eval-buffer))
+ ;; done handler:
(lambda (_buffer)
(when cider-eval-register
- (set-register cider-eval-register
res))))))
+ (set-register cider-eval-register res))
+ (when (and (not failed)
+ on-success-callback)
+ (funcall on-success-callback))))))
(defun cider--emit-interactive-eval-output (output repl-emit-function)
"Emit output resulting from interactive code evaluation.
@@ -841,6 +863,24 @@ and the suffix matched by `cider-module-info-regexp'."
"")
(string-trim)))
+(defun cider--maybe-display-error-as-overlay (phase err end)
+ "Possibly display ERR as an overlay honoring END,
+depending on the PHASE."
+ (when (or
+ ;; if we won't show *cider-error*, because of configuration, the
overlay is adequate because it compensates for the lack of info in a compact
manner:
+ (not cider-show-error-buffer)
+ (not (cider-connection-has-capability-p 'jvm-compilation-errors))
+ ;; if we won't show *cider-error*, because of an ignored phase, the
overlay is adequate:
+ (and cider-show-error-buffer
+ (member phase cider-clojure-compilation-error-phases)))
+ ;; Display errors as temporary overlays
+ (let ((cider-result-use-clojure-font-lock nil)
+ (trimmed-err (funcall cider-inline-error-message-function err)))
+ (cider--display-interactive-eval-result trimmed-err
+ 'error
+ end
+ 'cider-error-overlay-face))))
+
(declare-function cider-inspect-last-result "cider-inspector")
(defun cider-interactive-eval-handler (&optional buffer place)
"Make an interactive eval handler for BUFFER.
@@ -867,21 +907,8 @@ when `cider-auto-inspect-after-eval' is non-nil."
(cider-emit-interactive-eval-err-output err)
(let ((phase
(cider--error-phase-of-last-exception buffer)))
- (when (or
- ;; if we won't show *cider-error*,
because of configuration, the overlay is adequate because it compensates for
the lack of info in a compact manner:
- (not cider-show-error-buffer)
- (not
(cider-connection-has-capability-p 'jvm-compilation-errors))
- ;; if we won't show *cider-error*,
because of an ignored phase, the overlay is adequate:
- (and cider-show-error-buffer
- (member phase
cider-clojure-compilation-error-phases)))
- ;; Display errors as temporary overlays
- (let
((cider-result-use-clojure-font-lock nil)
- (trimmed-err (funcall
cider-inline-error-message-function err)))
-
(cider--display-interactive-eval-result
- trimmed-err
- 'error
- end
- 'cider-error-overlay-face)))
+
+ (cider--maybe-display-error-as-overlay
phase err end)
(cider-handle-compilation-errors err
eval-buffer
@@ -1018,24 +1045,51 @@ COMMENT-POSTFIX is the text to output after the last
line."
(lambda (_buffer warning)
(setq res (concat res warning))))))
-(defun cider-popup-eval-handler (&optional buffer)
- "Make a handler for printing evaluation results in popup BUFFER.
+(defun cider-popup-eval-handler (&optional buffer bounds source-buffer)
+ "Make a handler for printing evaluation results in popup BUFFER,
+BOUNDS representing the buffer bounds of the evaled input,
+and SOURCE-BUFFER the original buffer
+
This is used by pretty-printing commands."
;; NOTE: cider-eval-register behavior is not implemented here for
performance reasons.
;; See https://github.com/clojure-emacs/cider/pull/3162
- (nrepl-make-response-handler
- (or buffer (current-buffer))
- (lambda (buffer value)
- (cider-emit-into-popup-buffer buffer (ansi-color-apply value) nil t))
- (lambda (_buffer out)
- (cider-emit-interactive-eval-output out))
- (lambda (_buffer err)
- (cider-emit-interactive-eval-err-output err))
- nil
- nil
- nil
- (lambda (buffer warning)
- (cider-emit-into-popup-buffer buffer warning 'font-lock-warning-face t))))
+ (let ((chosen-buffer (or buffer (current-buffer))))
+ (nrepl-make-response-handler
+ chosen-buffer
+ ;; value handler:
+ (lambda (buffer value)
+ (cider-emit-into-popup-buffer buffer (ansi-color-apply value) nil t))
+ ;; stdout handler:
+ (lambda (_buffer out)
+ (cider-emit-interactive-eval-output out))
+ ;; stderr handler:
+ (lambda (buffer err)
+ (cider-emit-interactive-eval-err-output err)
+ (when (and source-buffer
+ (listp bounds)) ;; if it's a list, it represents bounds,
otherwise it's a string (code) and we can't display the overlay
+ (with-current-buffer source-buffer
+ (let* ((phase (cider--error-phase-of-last-exception buffer))
+ (end (or (car-safe (cdr-safe bounds)) bounds))
+ (end (when end
+ (copy-marker end))))
+ (cider--maybe-display-error-as-overlay phase err end)))))
+ ;; done handler:
+ nil
+ ;; eval-error handler:
+ (lambda ()
+ (when (and (buffer-live-p chosen-buffer)
+ (member (buffer-name chosen-buffer)
+ cider-ancillary-buffers))
+ (with-selected-window (get-buffer-window chosen-buffer)
+ (cider-popup-buffer-quit-function t)))
+ ;; also call the default nrepl-err-handler, so that our custom behavior
doesn't void the base behavior:
+ (when nrepl-err-handler
+ (funcall nrepl-err-handler)))
+ ;; content type handler:
+ nil
+ ;; truncated handler:
+ (lambda (buffer warning)
+ (cider-emit-into-popup-buffer buffer warning 'font-lock-warning-face
t)))))
;;; Interactive valuation commands
@@ -1325,27 +1379,31 @@ If INSERT-BEFORE is non-nil, insert before the form,
otherwise afterwards."
(declare-function cider-switch-to-repl-buffer "cider-mode")
+(defun cider--eval-last-sexp-to-repl (switch-to-repl request-map)
+ "Evaluate the expression preceding point and insert its result in the REPL,
+honoring SWITCH-TO-REPL, REQUEST-MAP."
+ (let ((bounds (cider-last-sexp 'bounds)))
+ (cider-interactive-eval nil
+ (cider-insert-eval-handler (cider-current-repl)
+ bounds
+ (current-buffer)
+ (lambda ()
+ (when switch-to-repl
+
(cider-switch-to-repl-buffer))))
+ bounds
+ request-map)))
+
(defun cider-eval-last-sexp-to-repl (&optional prefix)
"Evaluate the expression preceding point and insert its result in the REPL.
If invoked with a PREFIX argument, switch to the REPL buffer."
(interactive "P")
- (cider-interactive-eval nil
- (cider-insert-eval-handler (cider-current-repl))
- (cider-last-sexp 'bounds)
- (cider--nrepl-pr-request-map))
- (when prefix
- (cider-switch-to-repl-buffer)))
+ (cider--eval-last-sexp-to-repl prefix (cider--nrepl-pr-request-map)))
(defun cider-pprint-eval-last-sexp-to-repl (&optional prefix)
"Evaluate expr before point and insert its pretty-printed result in the REPL.
If invoked with a PREFIX argument, switch to the REPL buffer."
(interactive "P")
- (cider-interactive-eval nil
- (cider-insert-eval-handler (cider-current-repl))
- (cider-last-sexp 'bounds)
- (cider--nrepl-print-request-map fill-column))
- (when prefix
- (cider-switch-to-repl-buffer)))
+ (cider--eval-last-sexp-to-repl prefix (cider--nrepl-print-request-map
fill-column)))
(defun cider-eval-print-last-sexp (&optional pretty-print)
"Evaluate the expression preceding point.
@@ -1363,7 +1421,7 @@ With an optional PRETTY-PRINT prefix it pretty-prints the
result."
"Pretty print FORM in popup buffer."
(let* ((buffer (current-buffer))
(result-buffer (cider-popup-buffer cider-result-buffer nil
'clojure-mode 'ancillary))
- (handler (cider-popup-eval-handler result-buffer)))
+ (handler (cider-popup-eval-handler result-buffer form buffer)))
(with-current-buffer buffer
(cider-interactive-eval (when (stringp form) form)
handler