CIDER jack-in to Clojure CLI projects from Spacemacs
Running a Clojure project created with CLI tools or clj-new
may require you to pass in an alias for the REPL to pick up the right libraries.
A few days ago I created a new ClojureScript and reagent project, using the Clojure CLI tools and clj-new
project creation tool, which converts Leiningen and Boot templates into a deps.edn based project. Unfortunately when I created a project from the fighwheel-main template the REPL failed to run from CIDER using cider-jack-in-cljs
, saying that figwheel-main was not found. All that was required was to specify the :fig
alias when running a REPL.
This article covers two approaches to running Clojure CLI projects from CIDER jack-in that require setting of an alias or multiple aliases e.g. -A:fig:build:party:hammock
See Getting started with Clojure CLI tools for background to this article.
Understanding the problem
I created a new project with the Clojure CLI tools and the figwheel-main template (using clj-new). This is the first time with this approach, so I may have missed something.
clj -A:new figwheel-main practicalli/study-group-guide -- --reagent
I ran cider-jack-in-cljs
from Spacemacs and was prompted for the build tool. I selected figwheel-main
and rather than being prompted for the name of the build to run, I got an error in the mini-buffer.
error in process filter: Figwheel-main is not available. Please check https://docs.cider.mx/cider/basics/clojurescript
The same error was seen when looking at the output in the *messages*
buffer.
[nREPL] Starting server via /usr/local/bin/clojure -Sdeps '{:deps {nrepl {:mvn/version "0.6.0"} cider/piggieback {:mvn/version "0.4.1"} refactor-nrepl {:mvn/version "2.5.0-SNAPSHOT"} cider/cider-nrepl {:mvn/version "0.22.0-beta8"}}}' -m nrepl.cmdline --middleware '["refactor-nrepl.middleware/wrap-refactor", "cider.nrepl/cider-middleware", "cider.piggieback/wrap-cljs-repl"]'...
[nREPL] server started on 40737
[nREPL] Establishing direct connection to localhost:40737 ...
[nREPL] Direct connection to localhost:40737 established
error in process filter: user-error: Figwheel-main is not available.
The web page for the ClojureScript did not automatically open because figwheel-main is not running and the application was not built.
The project fails to run when using cider-jack-in-cljs
as it cannot find the figwheel-main namespace. This is because CIDER is not being called with the -A:fig
alias, which has a configuration to include figwheel-main as a dependency.
Hacking the CIDER jack-in command
Its very easy to hack the cider-jack-in-* commands command that CIDER uses to start a REPL using the universal argument.
SPC u , "
or SPC u , s j s
calls cider-jack-in-cljs
with the universal argument. This will display an editable prompt for Cider jack-in in the mini-buffer.
Use the arrow keys to edit this command and add the -A:fig
option just after the /usr/local/bin/clojure
executable name.
/usr/local/bin/clojure -A:fig -Sdeps '{:deps {nrepl {:mvn/version "0.6.0"} cider/piggieback {:mvn/version "0.4.1"} refactor-nrepl {:mvn/version "2.5.0-SNAPSHOT"} cider/cider-nrepl {:mvn/version "0.22.0-beta8"}}}' -m nrepl.cmdline --middleware '["refactor-nrepl.middleware/wrap-refactor", "cider.nrepl/cider-middleware", "cider.piggieback/wrap-cljs-repl"]'...
Emacs would use C-u before a cider-jack-in-* keybinding,
C-u C-c M-J
for the same results.
The *messages*
buffer also shows the edited command line used to start a ClojureScript REPL.
[nREPL] Starting server via /usr/local/bin/clojure -A:fig -Sdeps '{:deps {nrepl {:mvn/version "0.6.0"} cider/piggieback {:mvn/version "0.4.1"} refactor-nrepl {:mvn/version "2.5.0-SNAPSHOT"} cider/cider-nrepl {:mvn/version "0.22.0-beta8"}}}' -m nrepl.cmdline --middleware '["refactor-nrepl.middleware/wrap-refactor", "cider.nrepl/cider-middleware", "cider.piggieback/wrap-cljs-repl"]'...
[nREPL] server started on 35247
[nREPL] Establishing direct connection to localhost:35247 ...
[nREPL] Direct connection to localhost:35247 established
Adding CIDER configuration with .dir-locals.el
Rather than edit the cider jack-in command options each time, a local configuration file can be created to set a variable defining the :fig alias we want to include when running a REPL for this project.
.dir-locals.el
is an Emacs configuration file in which you can set variables for use with all files within the current directory or its child directories.
SPC SPC add-dir-local-variable
is a simple wizard function to help you create the .dir-locals.el
file. It will prompt you for the major mode, a variable name and variable value.
This variable will be used with the clojure-mode
(using nil
rather than clojure-mode
the variable would be applied to all modes).
A variable called cider-clojure-clj-global-options
will be used to set the :fig
alias.
((clojure-mode . ((cider-clojure-cli-global-options . "-A:fig"))))
SPC SPC revert-buffer
on one of the project source code files will load the variable from .dir-locals.el
into Spacemacs. Otherwise, you can close the project buffer(s) and re-open them to load this variable into Emacs. Once the buffer is loaded again, running cider-jack-in-cljs
works perfectly.
You can check the results by looking at the *mesages*
buffer and you will see the details of the command that cider-jack-in-cljs
function ran.
The
.dir-locals.el
is a list of lists. Each inner list contains which maps major mode names (symbols) to alists (see Association Lists). Each alist entry consists of a variable name and the directory-local value to assign to that variable, when the specified major mode is enabled. Instead of a mode name, you can specify ‘nil’, which means that the alist applies to any mode; or you can specify a subdirectory (a string), in which case the alist applies to all files in that subdirectory.
Understanding the :fig alias
deps.edn has a top-level key called :aliases
that can include one or more alias definitions as maps. This example is from the figwheel-main
template and has an extra dependency for the figwheel-main
and rebel-readline-cljs
libraries. So when starting a REPL with this alias, both those dependencies are available in the project.
:aliases
{:fig
{:extra-deps
{com.bhauman/rebel-readline-cljs {:mvn/version "0.1.4"}
com.bhauman/figwheel-main {:mvn/version "0.1.9"}}
The alias keeps these develop time libraries out of our application dependencies, as they are not required for running the application.
Leiningen includes figwheel-main as a dependency in the
project.clj
file in the:profiles {:dev ,,,}
section. Thedev
profile is used by Leiningen by default, so the figwheel-main dependency is always there.
Summary
Using CIDER with projects created with Clojure CLI tools and clj-new
works very well and only requires specification of which alias to use when starting the REPL from within Spacemacs.
If you have multiple aliases needed each time, you can chain them together:-A:fig:build:custom
by editing the jack-in command line or including those aliases in the .dir-locals.el
Thank you. @jr0cket
Practicalli - free online books on Spacemacs and Clojure development