summaryrefslogtreecommitdiff
path: root/cider-interaction.el
diff options
context:
space:
mode:
authorBozhidar Batsov <bozhidar.batsov@gmail.com>2015-03-30 21:24:03 +0300
committerBozhidar Batsov <bozhidar.batsov@gmail.com>2015-03-30 21:24:03 +0300
commit26ac3123c0915b8a2cbe8a3de4c50db02f6612ca (patch)
tree0c2759394b06b4e77a58e59461d1f3946b986b05 /cider-interaction.el
parent8814c4152473d1b1ae640633347fea6a19760d5e (diff)
parentc5661d78015a41db7deadaf933df00c3de74af7c (diff)
Merge pull request #1046 from cichli/delay-error-buffer-creation
Delay creation of error buffer until the error can be rendered
Diffstat (limited to 'cider-interaction.el')
-rw-r--r--cider-interaction.el102
1 files changed, 68 insertions, 34 deletions
diff --git a/cider-interaction.el b/cider-interaction.el
index b284684d..f56ba606 100644
--- a/cider-interaction.el
+++ b/cider-interaction.el
@@ -1124,21 +1124,68 @@ They exist for compatibility with `next-error'."
(goto-next-note-boundary))
(goto-next-note-boundary)))
-(defun cider-default-err-eval-handler (buffer session)
- "Display in BUFFER the last SESSION exception, without middleware support."
- (nrepl-request:eval
- "(clojure.stacktrace/print-cause-trace *e)"
- (lambda (response)
- (nrepl-dbind-response response (out)
- (when out
- (with-current-buffer buffer
- (cider-emit-into-color-buffer buffer out)
- (compilation-minor-mode +1)))))
- nil
- session))
+(defun cider--show-error-buffer-p ()
+ "Return non-nil if the error buffer must be shown on error.
-(defun cider-default-err-op-handler (buffer session)
- "Display in BUFFER the last SESSION exception, with middleware support."
+Takes into account both the value of `cider-show-error-buffer' and the
+currently selected buffer."
+ (let* ((selected-buffer (window-buffer (selected-window)))
+ (replp (with-current-buffer selected-buffer (derived-mode-p 'cider-repl-mode))))
+ (memq cider-show-error-buffer
+ (if replp
+ '(t always only-in-repl)
+ '(t always except-in-repl)))))
+
+(defun cider-new-error-buffer ()
+ "Return an empty error buffer, possibly displaying and/or selecting it.
+
+When deciding whether to display the buffer, takes into account both the
+value of `cider-show-error-buffer' and the currently selected buffer.
+
+When deciding whether to select the buffer, takes into account the value of
+`cider-auto-select-error-buffer'."
+ (if (cider--show-error-buffer-p)
+ (cider-popup-buffer cider-error-buffer cider-auto-select-error-buffer)
+ (cider-make-popup-buffer cider-error-buffer)))
+
+(defun cider--handle-err-eval-response (response)
+ "Render eval RESPONSE into a new error buffer.
+
+Uses the value of the `out' slot in RESPONSE."
+ (nrepl-dbind-response response (out)
+ (when out
+ (let ((error-buffer (cider-new-error-buffer)))
+ (cider-emit-into-color-buffer error-buffer out)
+ (with-current-buffer error-buffer
+ (compilation-minor-mode +1))))))
+
+(defun cider-default-err-eval-handler (session)
+ "Display the last exception for SESSION, without middleware support."
+ (cider--handle-err-eval-response
+ (nrepl-sync-request:eval
+ "(clojure.stacktrace/print-cause-trace *e)"
+ nil
+ session)))
+
+(defun cider--render-stacktrace-causes (causes)
+ "If CAUSES is non-nil, render its contents into a new error buffer."
+ (when causes
+ (let ((error-buffer (cider-new-error-buffer)))
+ (cider-stacktrace-render error-buffer (reverse causes)))))
+
+(defun cider--handle-stacktrace-response (response causes)
+ "Handle stacktrace op RESPONSE, aggregating the result into CAUSES.
+
+If RESPONSE contains a cause, cons it onto CAUSES and return that. If
+RESPONSE is the final message (i.e. it contains a status), render CAUSES
+into a new error buffer."
+ (nrepl-dbind-response response (class status)
+ (cond (class (cons response causes))
+ (status (cider--render-stacktrace-causes causes)))))
+
+(defun cider-default-err-op-handler (session)
+ "Display the last exception for SESSION, with middleware support."
+ ;; Causes are returned as a series of messages, which we aggregate in `causes'
(let (causes)
(nrepl-send-request
(append
@@ -1148,31 +1195,18 @@ They exist for compatibility with `next-error'."
(when cider-stacktrace-print-level
(list "print-level" cider-stacktrace-print-level)))
(lambda (response)
- (nrepl-dbind-response response (class status)
- (cond (class (setq causes (cons response causes)))
- (status (when causes
- (cider-stacktrace-render buffer (reverse causes))))))))))
-
-(defun cider--show-error-buffer-p (buffer)
- "Return non-nil if stacktrace buffer must be shown on error.
-Takes into account the current BUFFER and the value of `cider-show-error-buffer'."
- (let ((replp (with-current-buffer buffer (derived-mode-p 'cider-repl-mode))))
- (memq cider-show-error-buffer
- (if replp
- '(t always only-in-repl)
- '(t always except-in-repl)))))
+ ;; While the return value of `cider--handle-stacktrace-response' is not
+ ;; meaningful for the last message, we do not need the value of `causes'
+ ;; 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 (buffer ex root-ex session)
"Make an error handler for BUFFER, EX, ROOT-EX and SESSION.
This function determines how the error buffer is shown, and then delegates
the actual error content to the eval or op handler."
- (let* ((error-buffer (if (cider--show-error-buffer-p buffer)
- (cider-popup-buffer cider-error-buffer
- cider-auto-select-error-buffer)
- (cider-make-popup-buffer cider-error-buffer))))
- (if (nrepl-op-supported-p "stacktrace")
- (cider-default-err-op-handler error-buffer session)
- (cider-default-err-eval-handler error-buffer session))))
+ (if (nrepl-op-supported-p "stacktrace")
+ (cider-default-err-op-handler session)
+ (cider-default-err-eval-handler session)))
(defvar cider-compilation-regexp
'("\\(?:.*\\(warning, \\)\\|.*?\\(, compiling\\):(\\)\\([^:]*\\):\\([[:digit:]]+\\)\\(?::\\([[:digit:]]+\\)\\)?\\(\\(?: - \\(.*\\)\\)\\|)\\)" 3 4 5 (1))