Moldable Emacs: a Clojure Playground with Babashka
Too long; didn't read
The problem
When I finished to implement my first mold, the Playground, I remember I had this thought: "wouldn't it be cool to have a Playground in the language you like?". That was also the first issue of moldable-emacs. Then I moved on and I forgot about it.
Until the other day, when I had this cool work task about finding out team ratio between planned and unplanned work. Long story short, moldable-emacs was a great ally to solve it. After a couple of hours of hacking, there I go with a reproducible analysis. Here my problem: reproducible only by me. Unluckily few people use Emacs at work and I am the only one using my mode.
The thing my colleagues have in common though is that they are Clojurians. So even if they don't use Emacs, they do use Clojure. The Playground is in Elisp. So... clomacs? Not this time. For work stuff I want to write my scripts in Clojure!
Then another analysis task comes along, moldable-emacs would be great again! What shall I do?!?
It is a problem indeed
Apart of the need to reproduce work (to spot errors and improve upon it), a polyglot workflow is fun. Indeed, Org Babel is a show-off of marvels. When I chain Bash, JavaScript, and Elisp to get what I need is a joy. Each language has strengths. It feels an amazing freedom to compose these strengths into a flow of data. Moldable-emacs works well to unify data representations, but its main language remains Elisp. I mean you can move to JSON to a plist and back, but you still have to express yourself in Elisp. Even if JavaScript is just better at surfing JSON.
Can we do a first step in that direction?
And there is a solution
Since I need to share Clojure with others, let's start from there. I wanted a way to easily reproduce a Clojure script. In the sense that I don't want to create a project, if I were to need some external library. In Scala I would have picked something like Ammonite to back up my foreign Playground. So, I ended up learning that the cool Clojure kid of the block is babashka these days. And I totally agree. The beautiful mind that gave us clj-kondo gave as a nice way of scripting in Clojure too. And babashka fits perfectly with cider, the mode I use to enhance my Clojure dev experience. So I wrote a new mold.
The main dependency of this mold is cider. Babashka is just an insurance that the code in my Playground is going to be easy to share.
I made also an "Eval With Clojure" mold to evaluate the last Clojure sexp. Let me show how it all works together.
As you can see, I picked the babashka example that fetches the latest
tag of the project here. After connecting cider
, I evaluate the
require
and the function, and I get the latest tag! And by the way,
you can see that I can also evaluate self
(in the Elisp REPL).
That is indeed the bit that I care about: data integration. The implementation of the mold follows.
(me-register-mold :key "Playground Clojure" :given (:fn (and (me-require 'clojure-mode))) :then (:fn (let* ((tree (ignore-errors self))) (with-current-buffer buffername (clojure-mode) (erase-buffer) (insert ";; Tips:\n;; Use `self' to access the mold context.\n;; You can access the previous mold context through `mold-data'.\n\n") (ignore-errors (when (cider-connected-p) (cider-nrepl-sync-request:eval (format "(def self '%s)" (let ((x self)) (with-temp-buffer (me-print-to-buffer x) (buffer-string))))))) (setq-local self tree)))) :docs "You can play around with code in Clojure." :examples ...)
You can see that the self
is only set if cider is connected (the bit
with (cider-connected-p)
). This is pretty sketchy because the
setting of self
may fail. Also we miss mold-data
, which contains
old mold information. It is still available from the Elisp side, but
not in the cider session. Still, I believe it is a good first&tiny
step for polyglot molding!
And I could share how I made my analysis with my colleagues: so success!
The way I did was to develop my Playground, add a #!/usr/bin/env bb
at the top and that was it. Before developing I just needed to:
- run babashka nrepl:
(async-shell-command "bb nrepl-server 1667")
- connect cider to that with
cider-connect-clj
You can connect to any nrepl session. We leverage cider superpowers!
Conclusion
The first polyglot mold! As you can see, even if others don't use moldable-emacs, you can still share your data transformation. It is a bit ad-hoc, but it is possible. And if you are a Clojurian, well it is ready to use.
Happy polyglotting!