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

Reply via email to