From mboxrd@z Thu Jan 1 00:00:00 1970 From: stardiviner Subject: [PATCH] ob-clojure.el and ob-clojure-literate.el support new header argument :ns Date: Fri, 13 Apr 2018 20:55:25 +0800 Message-ID: <87zi272rlu.fsf@gmail.com> Reply-To: numbchild@gmail.com Mime-Version: 1.0 Content-Type: multipart/signed; boundary="==-=-="; micalg=pgp-sha256; protocol="application/pgp-signature" Return-path: Received: from eggs.gnu.org ([2001:4830:134:3::10]:53869) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f6ypa-0005wb-N4 for emacs-orgmode@gnu.org; Fri, 13 Apr 2018 09:33:37 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1f6ypX-0007gw-FG for emacs-orgmode@gnu.org; Fri, 13 Apr 2018 09:33:34 -0400 Received: from [183.249.134.91] (port=3796 helo=dark.localdomain) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f6ypW-0007e0-04 for emacs-orgmode@gnu.org; Fri, 13 Apr 2018 09:33:31 -0400 List-Id: "General discussions about Org-mode." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org Sender: "Emacs-orgmode" To: org-mode-email --==-=-= Content-Type: multipart/mixed; boundary="=-=-=" --=-=-= Content-Type: text/plain After about 5 times test, And about 4 times review. I decide to PR. About new header argument :ns, I don't know how to write the test for it with loading CIDER in ERT. So have not write test. But I load my patch code, and run test on the following examples works fine. #+begin_src clojure :results pp ;; (def greeting "hi there!") *ns* #+end_src #+RESULTS[<2018-04-13 20:37:16> f6f68aecdefcfd1be88fb144d47f5881f47b95db]: : #namespace[user] #+begin_src clojure :results pp (ns kk.test) (def he "hi") #+end_src #+RESULTS[<2018-04-13 20:37:24> 0b564a90ba588ba72b622a217834057600ac6d07]: : #'kk.test/he Deeper testing: #+begin_src emacs-lisp :results pp (nrepl-sync-request:eval "(clojure.pprint/pprint (do (ns user)\n (ns kk.test)\n (def he 2)))" (cider-current-connection) "user" ) #+end_src #+RESULTS[<2018-04-13 20:37:39> a05d9349d3b991a7fd47fb4ed268bf7e40f53e7a]: : (dict "status" : ("done" "state") : "id" "20" "out" "#'user/he\n" "session" "72ab6c95-08d4-4873-b83b-31c66aa26d62" "ns" "kk.test" "value" "nil" "changed-namespaces" : (dict) : "repl-type" "clj") #+begin_src clojure :results value :ns kk2 (def he "hi") *ns* #+end_src #+RESULTS[<2018-04-13 20:38:09> 89b32544ad50101e9f6f529a9e87a7bb86235cd9]: : nil#'kk2/he#namespace[kk2] What about another src block without ~:ns~ specified after previous specified src block? #+begin_src clojure :results value (def he "hi") *ns* #+end_src #+RESULTS[<2018-04-13 20:38:14> 85a2890ea59d198e2d1c771e2b80b1ae6335c416]: : nil#'user/he#namespace[user] More complex example: #+begin_src clojure :results output :var he="hi" :ns kk ;; (def he "hi") (prn he) (prn *ns*) #+end_src #+RESULTS[<2018-04-13 20:38:19> 9f6d74be8c54e2bc1b5047b569ddc6514c789cf0]: : "hi" : #namespace[kk] --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0001-ob-clojure-literate.el-CIDER-jack-in-outside-of-proj.patch Content-Transfer-Encoding: quoted-printable From=201a0d80c000384b929b84a3755669e0d44c662558 Mon Sep 17 00:00:00 2001 From: stardiviner Date: Thu, 22 Mar 2018 01:21:22 +0800 Subject: [PATCH 1/6] * ob-clojure-literate.el: CIDER jack-in outside of project by default. =2D-- contrib/lisp/ob-clojure-literate.el | 50 +++++++++++++++++------------ 1 file changed, 30 insertions(+), 20 deletions(-) diff --git a/contrib/lisp/ob-clojure-literate.el b/contrib/lisp/ob-clojure-= literate.el index a7ab1894d..8d419b0b4 100644 =2D-- a/contrib/lisp/ob-clojure-literate.el +++ b/contrib/lisp/ob-clojure-literate.el @@ -35,8 +35,10 @@ Don't auto jack in by default for not rude." :type 'boolean :group 'ob-clojure-literate) =20 =2D(defcustom ob-clojure-literate-project-location (concat user-emacs-direc= tory "Org-mode/") =2D "The location for `ob-clojure-literate' scaffold project." +(defcustom ob-clojure-literate-project-location nil + "The location for `ob-clojure-literate' scaffold project. +If it is nil, then `cider-jack-in' will jack-in outside of Clojure project. +If it is a directory, `ob-clojure-literate' will try to create Clojure pro= ject automatically." :type 'string :group 'ob-clojure-literate) =20 @@ -45,7 +47,7 @@ Don't auto jack in by default for not rude." (defvar ob-clojure-literate-session-ns nil) (defvar ob-clojure-literate-cider-connections nil) =20 =2D(defcustom ob-clojure-literate-default-session "*cider-repl ob-clojure*" +(defcustom ob-clojure-literate-default-session "*cider-repl localhost*" "The default session name for `ob-clojure-literate'." :type 'string :group 'ob-clojure-literate) @@ -104,23 +106,31 @@ Don't auto jack in by default for not rude." (defun ob-clojure-literate-auto-jackin () "Auto setup ob-clojure-literate scaffold and jack-in Clojure project." (interactive) =2D (unless (file-directory-p (expand-file-name ob-clojure-literate-projec= t-location)) =2D (make-directory ob-clojure-literate-project-location t) =2D (let ((default-directory ob-clojure-literate-project-location)) =2D (shell-command "lein new ob-clojure"))) =2D (unless (or =2D (and (cider-connected-p) =2D (if (not (null ob-clojure-literate-session)) =2D (seq-contains cider-connections (get-buffer ob-cloju= re-literate-session)))) =2D cider-connections =2D (not (null ob-clojure-literate-session))) =2D ;; return back to original file. =2D (if (not (and (=3D (length (ob-clojure-literate-get-session-list)) 1) =2D (-contains-p (ob-clojure-literate-get-session-list) ob= -clojure-literate-default-session))) =2D (save-window-excursion =2D (find-file (expand-file-name (concat ob-clojure-literate-proje= ct-location "ob-clojure/src/ob_clojure/core.clj"))) =2D (with-current-buffer "core.clj" =2D (cider-jack-in)))))) + (cond + ;; jack-in outside of Clojure project. + ((null ob-clojure-literate-project-location) + (if (member (get-buffer "*cider-repl localhost*") cider-connections) + (message "CIDER default session already launched.") + (cider-jack-in nil))) + ((not (null ob-clojure-literate-project-location)) + (unless (file-directory-p (expand-file-name ob-clojure-literate-projec= t-location)) + (make-directory ob-clojure-literate-project-location t) + (let ((default-directory ob-clojure-literate-project-location)) + (shell-command "lein new ob-clojure"))) + (unless (or + (and (cider-connected-p) + (if (not (null ob-clojure-literate-session)) + (seq-contains cider-connections (get-buffer ob-clojure-literate-se= ssion)))) + cider-connections + (not (null ob-clojure-literate-session))) + ;; return back to original file. + (if (not (and (=3D (length (ob-clojure-literate-get-session-list)) 1) + (-contains-p (ob-clojure-literate-get-session-list) ob= -clojure-literate-default-session))) + (save-window-excursion + (find-file (expand-file-name (concat ob-clojure-literate-proje= ct-location "ob-clojure/src/ob_clojure/core.clj"))) + (with-current-buffer "core.clj" + (cider-jack-in)))))) + )) =20 (defun ob-clojure-literate-set-local-cider-connections (toggle?) "Set buffer local `cider-connections' for `ob-clojure-literate-mode' `TO= GGLE?'." =2D-=20 2.17.0 --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0002-ob-clojure-literate.el-support-use-ns-header-argumen.patch Content-Transfer-Encoding: quoted-printable From=205f14edb8ff3e8b1aaa14338753103c5bd961c014 Mon Sep 17 00:00:00 2001 From: stardiviner Date: Thu, 22 Mar 2018 01:43:18 +0800 Subject: [PATCH 2/6] * ob-clojure-literate.el: support use :ns header argument. =2D rename ob-clojure-literate-cider-do-not-find-ns to ob-clojure-literate-= set-ns =2D-- contrib/lisp/ob-clojure-literate.el | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/contrib/lisp/ob-clojure-literate.el b/contrib/lisp/ob-clojure-= literate.el index 8d419b0b4..71ea909ba 100644 =2D-- a/contrib/lisp/ob-clojure-literate.el +++ b/contrib/lisp/ob-clojure-literate.el @@ -151,14 +151,15 @@ If it is a directory, `ob-clojure-literate' will try = to create Clojure project a ;; (setq-local cider-connections '()) )) =20 =2D(defun ob-clojure-literate-cider-do-not-find-ns (body params) +(defun ob-clojure-literate-set-ns (body params) "Fix the issue that `cider-current-ns' try to invoke `clojure-find-ns' t= o extract ns from buffer." ;; TODO: Is it possible to find ns in `body'? (when (ob-clojure-literate-any-connection-p) (setq ob-clojure-literate-original-ns (cider-current-ns)) (with-current-buffer ob-clojure-literate-session (setq ob-clojure-literate-session-ns cider-buffer-ns)) =2D (setq-local cider-buffer-ns ob-clojure-literate-session-ns)) + (setq-local cider-buffer-ns (or (cdr (assq :ns params)) + ob-clojure-literate-session-ns))) (message (format "ob-clojure-literate: current CIDER ns is [%s]." cider-= buffer-ns))) =20 (defun ob-clojure-literate-set-local-session (toggle?) @@ -302,7 +303,7 @@ reset `RESULT' to `nil'." (equal major-mode 'org-mode)) ; `ob-clojure-literate-mode' on= ly works in `org-mode'. (ob-clojure-literate-set-local-cider-connections ob-clojure-literate-m= ode) (ob-clojure-literate-set-local-session ob-clojure-literate-mode) =2D (advice-add 'org-babel-execute:clojure :before #'ob-clojure-literate= -cider-do-not-find-ns) + (advice-add 'org-babel-execute:clojure :before #'ob-clojure-literate-s= et-ns) (advice-add 'org-babel-expand-body:clojure :filter-args #'ob-clojure-l= iterate-inject-code) (advice-add 'org-babel-execute:clojure :filter-return #'ob-clojure-lit= erate-support-graphics-result) (message "ob-clojure-literate minor mode enabled."))) @@ -310,7 +311,7 @@ reset `RESULT' to `nil'." ;;;###autoload (defun ob-clojure-literate-disable () "Disable Org-mode buffer locally for `ob-clojure-literate'." =2D (advice-remove 'org-babel-execute:clojure #'ob-clojure-literate-cider-= do-not-find-ns) + (advice-remove 'org-babel-execute:clojure #'ob-clojure-literate-set-ns) (advice-remove 'org-babel-expand-body:clojure #'ob-clojure-literate-inje= ct-code) (advice-remove 'org-babel-execute:clojure #'ob-clojure-literate-support-= graphics-result) (setq-local cider-buffer-ns ob-clojure-literate-original-ns) =2D-=20 2.17.0 --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0003-ob-clojure-literate.el-support-vars-initialization-w.patch Content-Transfer-Encoding: quoted-printable From=202676754c4f616d023efae75d7de7e0621a681616 Mon Sep 17 00:00:00 2001 From: stardiviner Date: Mon, 26 Mar 2018 09:47:54 +0800 Subject: [PATCH 3/6] * ob-clojure-literate.el: support vars initialization when prepare session. =2D org-babel-clojure-var-to-clojure =2D-- contrib/lisp/ob-clojure-literate.el | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/contrib/lisp/ob-clojure-literate.el b/contrib/lisp/ob-clojure-= literate.el index 71ea909ba..2d1d30db8 100644 =2D-- a/contrib/lisp/ob-clojure-literate.el +++ b/contrib/lisp/ob-clojure-literate.el @@ -221,7 +221,14 @@ If it is a directory, `ob-clojure-literate' will try t= o create Clojure project a =20 (defun org-babel-clojure-var-to-clojure (var) "Convert src block's `VAR' to Clojure variable." =2D ;; TODO: reference `org-babel-python-var-to-python' + (if (listp var) + (replace-regexp-in-string "(" "'(" var) + (cond + ((stringp var) + ;; wrap org-babel passed in header argument value with quote in Cloj= ure. + (format "\"%s\"" var)) + (t + (format "%s" var)))) ) =20 (defun org-babel-variable-assignments:clojure (params) @@ -230,8 +237,7 @@ If it is a directory, `ob-clojure-literate' will try to= create Clojure project a (lambda (pair) (format "(def %s %s)" (car pair) =2D ;; (org-babel-clojure-var-to-clojure (cdr pair)) =2D (cdr pair))) + (org-babel-clojure-var-to-clojure (cdr pair)))) (org-babel--get-vars params))) =20 ;;; Support header arguments :results graphics :file "image.png" by injec= t Clojure code. =2D-=20 2.17.0 --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0004-ob-clojure.el-org-babel-execute-clojure-support-ns-h.patch Content-Transfer-Encoding: quoted-printable From=20d59a789dd86359f3907163125389decf51d8da5d Mon Sep 17 00:00:00 2001 From: stardiviner Date: Mon, 26 Mar 2018 11:35:21 +0800 Subject: [PATCH 4/6] * ob-clojure.el (org-babel-execute:clojure) support :ns header argument. Remove optional parameter (cider-current-ns) to better handling namespace. =2D-- lisp/ob-clojure.el | 54 ++++++++++++++++++++++++++++++++++------------ 1 file changed, 40 insertions(+), 14 deletions(-) diff --git a/lisp/ob-clojure.el b/lisp/ob-clojure.el index 890f60ada..35b4c3fe5 100644 =2D-- a/lisp/ob-clojure.el +++ b/lisp/ob-clojure.el @@ -41,6 +41,7 @@ ;;; Code: (require 'cl-lib) (require 'ob) +(require 'subr-x) =20 (declare-function cider-current-connection "ext:cider-client" (&optional t= ype)) (declare-function cider-current-ns "ext:cider-client" ()) @@ -55,6 +56,7 @@ (declare-function slime-eval "ext:slime" (sexp &optional package)) =20 (defvar nrepl-sync-request-timeout) +(defvar cider-buffer-ns) =20 (defvar org-babel-tangle-lang-exts) (add-to-list 'org-babel-tangle-lang-exts '("clojure" . "clj")) @@ -80,19 +82,43 @@ If the value is nil, timeout is disabled." (const :tag "cider" cider) (const :tag "SLIME" slime))) =20 +(defcustom org-babel-clojure-default-ns "user" + "Default Clojure namespace for src block when all find ns ways 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 + (when-let* ((repl-buf (cider-current-connection))) + (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 (cdr (assq :ns params))) + (ns-fallback (org-babel-clojure-cider-current-ns)) (result-params (cdr (assq :result-params params))) (print-level nil) (print-length nil) + (bind-vars (lambda (body) + (if (null vars) (org-trim body) + (concat + "(let [" + (mapconcat + (lambda (var) + (format "%S (quote %S)" (car var) (cdr var))) + vars "\n ") + "]\n" body ")")))) + (specify-namespace (lambda (body) + (concat + "(ns " (if (null ns) ns-fallback ns) ")\n" body))) (body (org-trim =2D (if (null vars) (org-trim body) =2D (concat "(let [" =2D (mapconcat =2D (lambda (var) =2D (format "%S (quote %S)" (car var) (cdr var))) =2D vars "\n ") =2D "]\n" body ")"))))) + (thread-last body + ;; variables binding + (funcall bind-vars) + ;; src block specified namespace :ns + (funcall specify-namespace))))) (if (or (member "code" result-params) (member "pp" result-params)) (format "(clojure.pprint/pprint (do %s))" body) @@ -102,9 +128,11 @@ 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." =2D (let ((expanded (org-babel-expand-body:clojure body params)) =2D (response (list 'dict)) =2D result) + (let* ((expanded (org-babel-expand-body:clojure body params)) + (ns (cdr (assq :ns params))) + (ns-fallback (org-babel-clojure-cider-current-ns)) + (response (list 'dict)) + result) (cl-case org-babel-clojure-backend (cider (require 'cider) @@ -117,8 +145,7 @@ using the :show-process parameter." (let ((nrepl-sync-request-timeout org-babel-clojure-sync-nrepl-timeout)) (nrepl-sync-request:eval expanded =2D (cider-current-connection) =2D (cider-current-ns)))) + (cider-current-connection)))) (setq result (concat (nrepl-dict-get response @@ -152,8 +179,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"))) =2D (cider-current-connection) =2D (cider-current-ns)) + (cider-current-connection)) =20 ;; Wait until the nREPL code finished to be processed. (while (not (member "done" status)) =2D-=20 2.17.0 --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0005-ob-clojure-literate.el-ob-clojure-literate-get-sessi.patch Content-Transfer-Encoding: quoted-printable From=2078948e652621f0e46ce52761aa6f372c5a919ece Mon Sep 17 00:00:00 2001 From: stardiviner Date: Mon, 2 Apr 2018 11:58:28 +0800 Subject: [PATCH 5/6] * ob-clojure-literate.el (ob-clojure-literate-get-session-list) get session from global connections list. =2D-- contrib/lisp/ob-clojure-literate.el | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/contrib/lisp/ob-clojure-literate.el b/contrib/lisp/ob-clojure-= literate.el index 2d1d30db8..0c928572b 100644 =2D-- a/contrib/lisp/ob-clojure-literate.el +++ b/contrib/lisp/ob-clojure-literate.el @@ -63,7 +63,11 @@ If it is a directory, `ob-clojure-literate' will try to = create Clojure project a =20 (defun ob-clojure-literate-get-session-list () "Return a list of available started CIDER REPL sessions list." =2D (-map 'buffer-name cider-connections)) + (-map 'buffer-name + ;; for multiple connections case. + ;; get global value instead of buffer local. + (default-value 'cider-connections) + )) =20 (defun ob-clojure-literate-set-session () "Set session name for buffer local." @@ -82,7 +86,7 @@ If it is a directory, `ob-clojure-literate' will try to c= reate Clojure project a )) =20 ;;;###autoload =2D(defun ob-clojure-literate-specify-session-header-argument () +(defun ob-clojure-literate-specify-session () "Specify ob-clojure header argument :session with value selected from a = list of available sessions." (interactive) (let ((lang (nth 0 (org-babel-get-src-block-info)))) @@ -297,7 +301,7 @@ reset `RESULT' to `nil'." map) "Keymap for `ob-clojure-literate-mode'.") =20 =2D(define-key org-babel-map (kbd "M-s") 'ob-clojure-literate-specify-sessi= on-header-argument) +(define-key org-babel-map (kbd "M-s") 'ob-clojure-literate-specify-session) (define-key org-babel-map (kbd "M-j") 'ob-clojure-literate-auto-jackin) ;; (define-key org-babel-map (kbd "M-e") 'cider-eval-last-sexp) ;; (define-key org-babel-map (kbd "M-d") 'cider-doc) =2D-=20 2.17.0 --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0006-ob-clojure-literate.el-ob-clojure-literate-inject-co.patch Content-Transfer-Encoding: quoted-printable From=207eeecfe2e0009c99f197c2e4eedb68d92bb58e89 Mon Sep 17 00:00:00 2001 From: stardiviner Date: Mon, 2 Apr 2018 13:47:28 +0800 Subject: [PATCH 6/6] * ob-clojure-literate.el (ob-clojure-literate-inject-code) Handle no :file specified file is nil case. =2D-- contrib/lisp/ob-clojure-literate.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/lisp/ob-clojure-literate.el b/contrib/lisp/ob-clojure-= literate.el index 0c928572b..5dec2ad9b 100644 =2D-- a/contrib/lisp/ob-clojure-literate.el +++ b/contrib/lisp/ob-clojure-literate.el @@ -265,7 +265,7 @@ Then you need to assign image variable to this :file va= lue like: (directory (and dir (file-name-as-directory (expand-file-name dir= )))) (result-type (cdr (assq :results params))) (file (cdr (assq :file params))) =2D (file-name (file-name-base file)) + (file-name (and file (file-name-base file))) ;; TODO: future support `:graphics-file' to avoid collision. (graphics-result (member "graphics" (cdr (assq :result-params params)))) ;; (graphics-file (cdr (assq :graphics-file params))) =2D-=20 2.17.0 --=-=-= Content-Type: text/plain -- [ stardiviner ] don't need to convince with trends. Blog: https://stardiviner.github.io/ IRC(freenode): stardiviner GPG: F09F650D7D674819892591401B5DF1C95AE89AC3 --=-=-=-- --==-=-= Content-Type: application/pgp-signature; name="signature.asc" -----BEGIN PGP SIGNATURE----- iQEzBAEBCAAdFiEE8J9lDX1nSBmJJZFAG13xyVromsMFAlrQqL4ACgkQG13xyVro msMEhwgAsfcRo8dFZWUYqtOxXFB1qzRkZQADfi86xjfx2NqaGkBCVkPd0VAGOrE/ st/NNXHc7fdqS8wzBCLmZmBvEKHqIJlwz0Drw6V5ZbAC2VmnS4CZOlhieT//RP3M 7YrsG7S9SD3VUwu9ZgzHdbTtOYt/X0vxhGRmRWjRwTDqk8GzlHCvBBcxejWYxWl/ R6ulf9bK2Uq4pjIpYJV1nAGfBWK39WOeNzwn6pg5B39Nfqeh5TZIsN5Kuz3D8UmK BFqiAtMz3acLhxED3EuljEWKNYldvQfs8qEbFz9eg0FeOP1EK596lOoh3J9NVcQb wdHhQpS73WOUqnvLlL61XyS5wySrqg== =ocVA -----END PGP SIGNATURE----- --==-=-=--