Ihor Radchenko <[email protected]> writes: > Simon Cossar <[email protected]> writes: > >>> You can just move this extra logic arranging :results to >>> org-babel-execute:clojure. >> >> To fix the issue for myself, I extracted the logic that wraps the body >> in a print expression into its own function. Here is the code I'm >> using. I can create a patch if that would help. Any suggestions for >> improving the code would be appreciated. > > Thanks! > If it is easy for you to create a patch, providing a patch would be > appreciated. If not, I can try to port your code snippets directly.
I'll try creating a patch. I'm unsure about adding tests for the changes. In the tests I have included, the first test does not rely on having a Clojure executable, the second test does. I've only run the tests from within Emacs. They don't seem to get picked up when I run `make test` from the command line. I'll look into that some more later on today. -- Simon Cossar
>From 4435e42271cdfef75a725a6d6aae2bc21ccc1394 Mon Sep 17 00:00:00 2001 From: Simon Cossar <[email protected]> Date: Wed, 20 May 2026 07:05:50 -0700 Subject: [PATCH 1/2] lisp/ob-clojure.el: Stop tangling code that is used for evaluation * org-clojure.el (org-babel-expand-body:clojure, ob-clojure--prepare-for-evaluation): Extract code that is used for evaluation of source blocks into its own function. (org-babel-execute:clojure): Call ob-clojure--prepare-for-evaluation on expanded source block body. --- lisp/ob-clojure.el | 108 ++++++++++++++++++++++----------------------- 1 file changed, 53 insertions(+), 55 deletions(-) diff --git a/lisp/ob-clojure.el b/lisp/ob-clojure.el index 8f07d3d3f..7f18ef1ad 100644 --- a/lisp/ob-clojure.el +++ b/lisp/ob-clojure.el @@ -133,9 +133,8 @@ :group 'org-babel :package-version '(Org . "9.7")) -(defun org-babel-expand-body:clojure (body params &optional cljs-p) - "Expand BODY according to PARAMS, return the expanded body. -When CLJS-P is non-nil, expand in a cljs context instead of clj." +(defun org-babel-expand-body:clojure (body params &optional _cljs-p) + "Expand BODY according to PARAMS, return the expanded body." (let* ((vars (org-babel--get-vars params)) (backend-override (cdr (assq :backend params))) (org-babel-clojure-backend @@ -144,51 +143,30 @@ When CLJS-P is non-nil, expand in a cljs context instead of clj." (org-babel-clojure-backend org-babel-clojure-backend) (t (user-error "You need to customize `org-babel-clojure-backend' or set the `:backend' header argument")))) - (ns (or (cdr (assq :ns params)) - (if (eq org-babel-clojure-backend 'cider) - (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))) - (result-params (cdr (assq :result-params params))) - (print-level nil) - (print-length nil) - (body (org-trim - (concat - ;; Source block specified namespace :ns. - (and (cdr (assq :ns params)) (format "(ns %s)\n" ns)) - ;; Variables binding. - (if (null vars) (org-trim body) - ;; Remove comments, they break (let [...] ...) bindings - (let ((body (replace-regexp-in-string "^[ ]*;+.*$" "" body))) - (format "(let [%s]\n%s)" - (mapconcat - (lambda (var) - (format "%S '%S" (car var) (cdr var))) - vars - "\n ") - body))))))) - ;; If the result param is set to "output" we don't have to do - ;; anything special and just let the backend handle everything - (if (member "output" result-params) - body - - ;; If the result is not "output" (i.e. it's "value"), disable - ;; stdout output and print the last returned value. Use pprint - ;; instead of prn when results param is "pp" or "code". - (concat - (if (or (member "code" result-params) - (member "pp" result-params)) - (concat (if cljs-p - "(require '[cljs.pprint :refer [pprint]])" - "(require '[clojure.pprint :refer [pprint]])") - " (pprint ") - "(prn ") - (if cljs-p - "(binding [cljs.core/*print-fn* (constantly nil)]" - "(binding [*out* (java.io.StringWriter.)]") - body "))")))) + (ns (or (cdr (assq :ns params)) + (if (eq org-babel-clojure-backend 'cider) + (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))) + (print-level nil) + (print-length nil)) + (org-trim + (concat + ;; Source block specified namespace :ns. + (and (cdr (assq :ns params)) (format "(ns %s)\n" ns)) + ;; Variables binding. + (if (null vars) (org-trim body) + ;; Remove comments, they break (let [...] ...) bindings + (let ((body (replace-regexp-in-string "^[ ]*;+.*$" "" body))) + (format "(let [%s]\n%s)" + (mapconcat + (lambda (var) + (format "%S '%S" (car var) (cdr var))) + vars + "\n ") + body))))))) (defvar ob-clojure-inf-clojure-filter-out) (defvar ob-clojure-inf-clojure-tmp-output) @@ -300,6 +278,25 @@ The PARAMS from Babel are not used in this function." (format "%s %s" cmd (org-babel-process-file-name script-file)) ""))) +(defun ob-clojure--prepare-for-evaluation (expanded-body params cljs-p) + "Wrap EXPANDED-BODY in a print expression, depending on PARAMS and CLJS-P." + (let* ((result-params (cdr (assq :result-params params))) + (output (if (member "output" result-params) + expanded-body + (concat + (if (or (member "code" result-params) + (member "pp" result-params)) + (concat (if cljs-p + "(require '[cljs.pprint :refer [pprint]])" + "(require '[clojure.pprint :refer [pprint]])") + " (pprint") + "(prn ") + (if cljs-p + "(binding [cljs.core/*print-fn* (constantly nil)])" + "(binding [*out* (java.io.StringWriter.)]") + expanded-body "))")))) + output)) + (defun org-babel-execute:clojure (body params &optional cljs-p) "Execute the BODY block of Clojure code with PARAMS using Babel. When CLJS-P is non-nil, execute with a ClojureScript backend @@ -321,23 +318,24 @@ or set the `:backend' header argument" ;; ClojureScript syntax when we either evaluate a ;; ClojureScript source block or use the nbb backend. (cljs-p (or cljs-p (eq org-babel-clojure-backend 'nbb)))) - (let* ((expanded (org-babel-expand-body:clojure body params cljs-p)) + (let* ((expanded (org-babel-expand-body:clojure body params)) + (prepared (ob-clojure--prepare-for-evaluation expanded params cljs-p)) (result-params (cdr (assq :result-params params))) result) (setq result (cond ((eq org-babel-clojure-backend 'inf-clojure) - (ob-clojure-eval-with-inf-clojure expanded params)) + (ob-clojure-eval-with-inf-clojure prepared params)) ((eq org-babel-clojure-backend 'clojure-cli) - (ob-clojure-eval-with-cmd ob-clojure-cli-command expanded)) + (ob-clojure-eval-with-cmd ob-clojure-cli-command prepared)) ((eq org-babel-clojure-backend 'babashka) - (ob-clojure-eval-with-cmd ob-clojure-babashka-command expanded)) + (ob-clojure-eval-with-cmd ob-clojure-babashka-command prepared)) ((eq org-babel-clojure-backend 'nbb) - (ob-clojure-eval-with-cmd ob-clojure-nbb-command expanded)) + (ob-clojure-eval-with-cmd ob-clojure-nbb-command prepared)) ((eq org-babel-clojure-backend 'cider) - (ob-clojure-eval-with-cider expanded params cljs-p)) + (ob-clojure-eval-with-cider prepared params cljs-p)) ((eq org-babel-clojure-backend 'slime) - (ob-clojure-eval-with-slime expanded params)) + (ob-clojure-eval-with-slime prepared params)) (t (user-error "Invalid backend")))) (org-babel-result-cond result-params result -- 2.54.0
>From d6309ed8875c7bce49ea66a43796e013d57cd1cd Mon Sep 17 00:00:00 2001 From: Simon Cossar <[email protected]> Date: Wed, 20 May 2026 07:57:09 -0700 Subject: [PATCH 2/2] testing/lisp/test-ob-clojure.el: Add tests * test-ob-clojure.el (ob-clojure/org-babel-tangle): Test that when a source block's :results parameter is set to "value", the tangled code does not include `prn' statements. (ob-clojure/org-babel-execute): Test that :result-params "value" and "output" values are correctly handled. --- testing/lisp/test-ob-clojure.el | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/testing/lisp/test-ob-clojure.el b/testing/lisp/test-ob-clojure.el index 6ec33fb11..e66ea4bfc 100644 --- a/testing/lisp/test-ob-clojure.el +++ b/testing/lisp/test-ob-clojure.el @@ -23,11 +23,39 @@ ;; Org tests for ob-clojure.el live here ;;; Code: +(require 'org-test "../testing/org-test") (unless (featurep 'ob-clojure) (signal 'missing-test-dependency '("Support for Clojure code blocks"))) -;; FIXME: The old tests where totally off. We need to write new tests. +;; tangle +(ert-deftest ob-clojure/org-babel-tangle () + "org-babel-tangle returns the exact body of the source block." + (org-test-with-temp-text-in-file + "#+begin_src clojure :tangle \"tangle.clj\" :results value\n +(+ 1 2)\n#+end_src" + (unwind-protect + (progn (org-babel-tangle) + (with-temp-buffer + (insert-file-contents "tangle.clj") + (let ((tangled (buffer-string))) + (should + (string-match-p "^(\\+ 1 2)\\\n$" tangled))))) + (delete-file "tangle.clj")))) + +;; execute +(ert-deftest ob-clojure/org-babel-execute () + "org-babel-execute:clojure correctly handles :result-params" + (skip-unless (executable-find "clojure")) + (let ((org-babel-clojure-backend 'clojure-cli)) + (should (equal 3 + (org-babel-execute:clojure + "(+ 1 2)" + '((:result-params "value"))))) + (should (equal "" + (org-babel-execute:clojure + "(+ 1 2)" + '((:result-params "output"))))))) (provide 'test-ob-clojure) -- 2.54.0
