summaryrefslogtreecommitdiff
path: root/lisp/org/ob-clojure.el
diff options
context:
space:
mode:
authorBastien <bzg@gnu.org>2019-12-03 23:27:04 +0100
committerBastien <bzg@gnu.org>2019-12-03 23:27:04 +0100
commit165f7383822086d465519ebe6e4283723923f097 (patch)
tree820be9480e3d571d766483f564c963037192f6ec /lisp/org/ob-clojure.el
parent821de968434d2096bdea67dd24301bf6b517aef1 (diff)
downloademacs-165f7383822086d465519ebe6e4283723923f097.tar.gz
Update Org to 9.3
Diffstat (limited to 'lisp/org/ob-clojure.el')
-rw-r--r--lisp/org/ob-clojure.el127
1 files changed, 106 insertions, 21 deletions
diff --git a/lisp/org/ob-clojure.el b/lisp/org/ob-clojure.el
index 14c014a9f9a..0e5642adbbf 100644
--- a/lisp/org/ob-clojure.el
+++ b/lisp/org/ob-clojure.el
@@ -41,26 +41,30 @@
;;; Code:
(require 'cl-lib)
(require 'ob)
+(require 'org-macs)
+(declare-function cider-jack-in "ext:cider" (&optional prompt-project cljs-too))
(declare-function cider-current-connection "ext:cider-client" (&optional type))
(declare-function cider-current-ns "ext:cider-client" ())
+(declare-function cider-repls "ext:cider-connection" (&optional type ensure))
(declare-function nrepl--merge "ext:nrepl-client" (dict1 dict2))
(declare-function nrepl-dict-get "ext:nrepl-client" (dict key))
(declare-function nrepl-dict-put "ext:nrepl-client" (dict key value))
-(declare-function nrepl-request:eval "ext:nrepl-client"
- (input callback connection &optional session ns line column additional-params))
-(declare-function nrepl-sync-request:eval "ext:nrepl-client"
- (input connection session &optional ns))
-(declare-function org-trim "org" (s &optional keep-lead))
+(declare-function nrepl-request:eval "ext:nrepl-client" (input callback connection &optional ns line column additional-params tooling))
+(declare-function nrepl-sync-request:eval "ext:nrepl-client" (input connection &optional ns tooling))
(declare-function slime-eval "ext:slime" (sexp &optional package))
(defvar nrepl-sync-request-timeout)
+(defvar cider-buffer-ns)
+(defvar sesman-system)
+(defvar cider-version)
(defvar org-babel-tangle-lang-exts)
(add-to-list 'org-babel-tangle-lang-exts '("clojure" . "clj"))
(defvar org-babel-default-header-args:clojure '())
-(defvar org-babel-header-args:clojure '((package . :any)))
+(defvar org-babel-header-args:clojure '((ns . :any)
+ (package . :any)))
(defcustom org-babel-clojure-sync-nrepl-timeout 10
"Timeout value, in seconds, of a Clojure sync call.
@@ -80,19 +84,39 @@ If the value is nil, timeout is disabled."
(const :tag "cider" cider)
(const :tag "SLIME" slime)))
+(defcustom org-babel-clojure-default-ns "user"
+ "Default Clojure namespace for source block when finding ns failed."
+ :type 'string
+ :group 'org-babel)
+
+(defun org-babel-clojure-cider-current-ns ()
+ "Like `cider-current-ns' except `cider-find-ns'."
+ (or cider-buffer-ns
+ (let ((repl-buf (cider-current-connection)))
+ (and repl-buf (buffer-local-value 'cider-buffer-ns repl-buf)))
+ org-babel-clojure-default-ns))
+
(defun org-babel-expand-body:clojure (body params)
"Expand BODY according to PARAMS, return the expanded body."
(let* ((vars (org-babel--get-vars params))
+ (ns (or (cdr (assq :ns params))
+ (org-babel-clojure-cider-current-ns)))
(result-params (cdr (assq :result-params params)))
- (print-level nil) (print-length nil)
+ (print-level nil)
+ (print-length nil)
(body (org-trim
- (if (null vars) (org-trim body)
- (concat "(let ["
- (mapconcat
- (lambda (var)
- (format "%S (quote %S)" (car var) (cdr var)))
- vars "\n ")
- "]\n" body ")")))))
+ (concat
+ ;; Source block specified namespace :ns.
+ (and (cdr (assq :ns params)) (format "(ns %s)\n" ns))
+ ;; Variables binding.
+ (if (null vars) (org-trim body)
+ (format "(let [%s]\n%s)"
+ (mapconcat
+ (lambda (var)
+ (format "%S (quote %S)" (car var) (cdr var)))
+ vars
+ "\n ")
+ body))))))
(if (or (member "code" result-params)
(member "pp" result-params))
(format "(clojure.pprint/pprint (do %s))" body)
@@ -102,9 +126,9 @@ If the value is nil, timeout is disabled."
"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))
- (response (list 'dict))
- result)
+ (let* ((expanded (org-babel-expand-body:clojure body params))
+ (response (list 'dict))
+ result)
(cl-case org-babel-clojure-backend
(cider
(require 'cider)
@@ -117,8 +141,7 @@ using the :show-process parameter."
(let ((nrepl-sync-request-timeout
org-babel-clojure-sync-nrepl-timeout))
(nrepl-sync-request:eval expanded
- (cider-current-connection)
- (cider-current-ns))))
+ (cider-current-connection))))
(setq result
(concat
(nrepl-dict-get response
@@ -152,8 +175,7 @@ using the :show-process parameter."
(nrepl--merge response resp)
;; Update the status of the nREPL output session.
(setq status (nrepl-dict-get response "status")))
- (cider-current-connection)
- (cider-current-ns))
+ (cider-current-connection))
;; Wait until the nREPL code finished to be processed.
(while (not (member "done" status))
@@ -193,6 +215,69 @@ using the :show-process parameter."
(condition-case nil (org-babel-script-escape result)
(error result)))))
+(defun org-babel-clojure-initiate-session (&optional session _params)
+ "Initiate a session named SESSION according to PARAMS."
+ (when (and session (not (string= session "none")))
+ (save-window-excursion
+ (cond
+ ((org-babel-comint-buffer-livep session) nil)
+ ;; CIDER jack-in to the Clojure project directory.
+ ((eq org-babel-clojure-backend 'cider)
+ (require 'cider)
+ (let ((session-buffer
+ (save-window-excursion
+ (if (version< cider-version "0.18.0")
+ ;; Older CIDER (without sesman) still need to use
+ ;; old way.
+ (cider-jack-in nil) ;jack-in without project
+ ;; New CIDER (with sesman to manage sessions).
+ (unless (cider-repls)
+ (let ((sesman-system 'CIDER))
+ (call-interactively 'sesman-link-with-directory))))
+ (current-buffer))))
+ (when (org-babel-comint-buffer-livep session-buffer)
+ (sit-for .25)
+ session-buffer)))
+ ((eq org-babel-clojure-backend 'slime)
+ (error "Session evaluation with SLIME is not supported"))
+ (t
+ (error "Session initiate failed")))
+ (get-buffer session))))
+
+(defun org-babel-prep-session:clojure (session params)
+ "Prepare SESSION according to the header arguments specified in PARAMS."
+ (let ((session (org-babel-clojure-initiate-session session))
+ (var-lines (org-babel-variable-assignments:clojure params)))
+ (when session
+ (org-babel-comint-in-buffer session
+ (dolist (var var-lines)
+ (insert var)
+ (comint-send-input nil t)
+ (org-babel-comint-wait-for-output session)
+ (sit-for .1)
+ (goto-char (point-max)))))
+ session))
+
+(defun org-babel-clojure-var-to-clojure (var)
+ "Convert src block's VAR to Clojure variable."
+ (cond
+ ((listp var)
+ (replace-regexp-in-string "(" "'(" var))
+ ((stringp var)
+ ;; Wrap Babel passed-in header argument value with quotes in Clojure.
+ (format "\"%s\"" var))
+ (t
+ (format "%S" var))))
+
+(defun org-babel-variable-assignments:clojure (params)
+ "Return a list of Clojure statements assigning the block's variables in PARAMS."
+ (mapcar
+ (lambda (pair)
+ (format "(def %s %s)"
+ (car pair)
+ (org-babel-clojure-var-to-clojure (cdr pair))))
+ (org-babel--get-vars params)))
+
(provide 'ob-clojure)
;;; ob-clojure.el ends here