clojure and clojurescript in org-babel

Table of Contents

1 Clojure and Clojurescript in Org-Babel

TLDR: your org-directory needs to have a project.clj for lein and Clojure, and a deps.edn and dev.cljs.edn for Clojurescript.

Note: this is specifically for doom emacs, but should work on other emacs’ as well. This is partially based off the official docs, but has been extended to work with the clj tool as well as lein. I use lein for clojure and clj for clojurescript. Clojurescript through cider should also pop open a browser, which you should be able to interact with from your org file, using figwheel.

I had attempted using clojupyter and other jupyter solutions, but they were all so complicated to install that I stuck with this current version. I had also attempted ob-clojurescript, but this simply directly evaluated src blocks as opposed to sending them to the repl, which is my desired behaviour. My hope is to do exploratory programming and learn while using the repl, while also taking notes and documenting the process. So here’s how to get it set up:

1.1 Installation

We assume we have set org-directory like so. This is the root directory of where you will be writing your org files that will have executable clojure in them.

; config.el
(setq org-directory "~/f/notes")

Also inside of your emacs config.el, you need to have:

; config.el
(require 'ob-clojure)
(setq org-babel-clojure-backend 'cider)
(require 'cider)

1.1.1 Clojurescript

Then, I add my clojurescript files. First, add the dependencies. Here you can add any dependencies you might want available to the clojurescript repl in your org files.

; org-directory/deps.edn
{:deps {org.clojure/clojure {:mvn/version "1.9.0"}
        org.clojure/clojurescript {:mvn/version "1.10.773"}
        org.clojure/test.check {:mvn/version "0.9.0"} ; this enables spec
        com.bhauman/figwheel-main {:mvn/version "0.2.12"}
        reagent {:mvn/version "1.0.0"}
        ;; optional but recommended
        com.bhauman/rebel-readline-cljs {:mvn/version "0.1.4"}}

 :aliases {:fig {:main-opts ["-m" "figwheel.main"
                             "-b" "dev" ;references file dev.cljs.edn
                             "-r"]}} ; repl i guess

 :paths ["src"]}

Then, for figwheel, I will add the following file. I will be honest, I am not entirely sure why or how all of this is needed, but it works for me.

; org-directory/dev.cljs.edn
{:main clojurescriptexamples.core}

additionally I add the file src/clojurescriptexamples/core.cljs in the org directory to have the main file.

1.1.2 Clojure

I add the file for leiningen like so:

1.2 Running

Now, we should be able to add a code block, like so

#+BEGIN_SRC clojure :eval no-exports :exports both
  [1 2 3]
 [1 2 3]
Please reevaluate when nREPL is connected

now, when you C-c C-c in that block, you should be confronted with a menu. where you can choose between:


With this, I make the decision to start the clojure or clojurescript repl. I will now choose cider-jack-in-cljs. I now have to choose between


I will choose clojure-cli for clojurescript. then, choose figwheel-main to have hot reloading and more in your browser. You should also be able to choose your dev.cljs.edn build from earlier. A repl window should also open up, as well as the browser running the compiled, hot reloaded javascript.

Note, as the cider repl is starting, you should see:

Please reevaluate when nREPL is connected

And you will have to evaluate the block again later, like so.

 [1 2 3]
Please reevaluate when nREPL is connected

If you open the console in the browser and evaluate the following block

(js/console.log "hello world")

You should see “hello world” there.

1.3 Notes

1.3.1 use :exports both

This will export your results blocks

1.3.2 use :eval no-exports

For each clojure source block, I do not want to make the decision when I am exporting my org notes to pdf or html which repl to use. Since all of them simply define BEGIN_SRC clojure, It would not make sense to excecute them every single time I export the page. With this in mind, I add :eval no-exports to each block, so it ’stores’ the results for export.

Author: John Doe

Created: 2021-04-25 Sun 15:53