From df8284b45c35e0c1dcbccf40ba7b76fd18270b90 Mon Sep 17 00:00:00 2001 From: Frederick Giasson Date: Mon, 7 Nov 2016 13:48:50 -0500 Subject: [PATCH 1/2] Better error handling with nREPL. Displaying any possible errors or exceptions in the result block. Adding a new :show-process header option such that the underlying process of a Clojure block code get output in a new buffer and a new window such that the developer can see what is going on. --- lisp/ob-clojure.el | 106 +++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 82 insertions(+), 24 deletions(-) diff --git a/lisp/ob-clojure.el b/lisp/ob-clojure.el index 72ea77d..4800c9a 100644 --- a/lisp/ob-clojure.el +++ b/lisp/ob-clojure.el @@ -2,7 +2,7 @@ ;; Copyright (C) 2009-2016 Free Software Foundation, Inc. -;; Author: Joel Boehland, Eric Schulte, Oleh Krehel +;; Author: Joel Boehland, Eric Schulte, Oleh Krehel, Frederick Giasson ;; ;; Keywords: literate programming, reproducible research ;; Homepage: http://orgmode.org @@ -84,34 +84,92 @@ body))) (defun org-babel-execute:clojure (body params) - "Execute a block of Clojure code with Babel." + "Execute a block of Clojure code with Babel. The underlying process performed by the + code block can be output using the :show-process parameter" (let ((expanded (org-babel-expand-body:clojure body params)) - result) + (sbuffer "*Clojure Show Process Sub Buffer*") + (show (if (assoc :show-process params) t nil)) + (response (cons 'dict nil)) + status + result) (cl-case org-babel-clojure-backend (cider (require 'cider) (let ((result-params (cdr (assq :result-params params)))) - (setq result - (nrepl-dict-get - (nrepl-sync-request:eval - expanded (cider-current-connection) (cider-current-session)) - (if (or (member "output" result-params) - (member "pp" result-params)) - "out" - "value"))))) - (slime - (require 'slime) - (with-temp-buffer - (insert expanded) - (setq result - (slime-eval - `(swank:eval-and-grab-output - ,(buffer-substring-no-properties (point-min) (point-max))) - (cdr (assq :package params))))))) - (org-babel-result-cond (cdr (assq :result-params params)) - result - (condition-case nil (org-babel-script-escape result) - (error result))))) + ; Check if the user want show the process in an output buffer/window + (when show + ; Create a new window with the show output buffer + (switch-to-buffer-other-window sbuffer) + + ; Run the Clojure code in nREPL + (nrepl-request:eval + expanded + (lambda (resp) + (when (member "out" resp) + ; Print the output of the nREPL in the output buffer + (princ (nrepl-dict-get resp "out") (get-buffer sbuffer))) + (when (member "ex" resp) + ; In case there is an exception, then add it to the output buffer as well + (princ (nrepl-dict-get resp "ex") (get-buffer sbuffer)) + (princ (nrepl-dict-get resp "root-ex") (get-buffer sbuffer))) + (when (member "err" resp) + ; In case there is an error, then add it to the output buffer as well + (princ (nrepl-dict-get resp "err") (get-buffer sbuffer))) + (nrepl--merge response resp) + ; Update the status of the nREPL output session + (setq status (nrepl-dict-get response "status"))) + (cider-current-connection) + (cider-current-session)) + + ; Wait until the nREPL code finished to be processed + (while (not (member "done" status)) + (nrepl-dict-put response "status" (remove "need-input" status)) + (accept-process-output nil 0.01) + (redisplay)) + + ; Delete the show buffer & window when the processing is finalized + (let ((wins (get-buffer-window-list sbuffer nil t))) + (dolist (win wins) + (delete-window win)) + (kill-buffer sbuffer)) + + ; Put the output or the value in the result section of the code block + (setq result (concat (nrepl-dict-get response + (if (or (member "output" result-params) + (member "pp" result-params)) + "out" + "value")) + (nrepl-dict-get response "ex") + (nrepl-dict-get response "root-ex") + (nrepl-dict-get response "err")))) + ; Check if user want to run code without showing the process + (when (not show) + (setq response (let ((nrepl-sync-request-timeout + org-babel-clojure-sync-nrepl-timeout)) + (nrepl-sync-request:eval + expanded (cider-current-connection) (cider-current-session)))) + (setq result + (concat + (nrepl-dict-get response (if (or (member "output" result-params) + (member "pp" result-params)) + "out" + "value")) + (nrepl-dict-get response "ex") + (nrepl-dict-get response "root-ex") + (nrepl-dict-get response "err")))))) + (slime + (require 'slime) + (with-temp-buffer + (insert expanded) + (setq result + (slime-eval + `(swank:eval-and-grab-output + ,(buffer-substring-no-properties (point-min) (point-max))) + (cdr (assq :package params))))))) + (org-babel-result-cond (cdr (assq :result-params params)) + result + (condition-case nil (org-babel-script-escape result) + (error result))))) (provide 'ob-clojure) -- 1.9.5.msysgit.0