How to setup deps.edn project with cider

I am creating a project based on cli tools and deps.edn (I don’t want to use lein) I would like to use emacs (spacemacs) and cider to cider-jack-in my project as if I am using lein.
Specifically, I want the repl to switch a specified ns on startup.
How to do that ?

According to the CIDER documentation jack-in should work automatically with a deps.edn project. I don’t use CIDER or nREPL at all so I’ve no idea about why you’d want to be in any namespace other than user when you start up (I never type into the REPL anyway: I only evaluate code from my editor, which auto-selects a namespace for evaluation).

2 Likes

You can start a CLI REPL in a specific namespace via something like this:

$ clj -e "(require,'usermanager.main)(in-ns,'usermanager.main)" -r

So CIDER’s jack-in for deps.edn could certainly do this automatically for you but I suspect there’s no standard way to tell it which is the “main” namespace – whereas Leiningen’s project.clj has a :main key for that.

I will give it a try.
When I type (in-ns 'foo.core) then (require '[cheshire.core :as json]) I have the following error:
Syntax error compiling at (REPL:1:1). Unable to resolve symbol: require in this context

You must (require 'foo.core) first, then (in-ns 'foo.core) – look at the -e option I provided to clj: it has both because you need both.

1 Like

When developing with source code buffers rather than directly in the REPL buffer, setting the main namespace is not required as all evaluation is done with respect to the namespace of the active source code buffer.

In Spacemacs the source code buffers and REPL buffers are all connected to the running REPL process. What you do in one is available from the other as its all in the REPL process.

In the source code buffer:

SPC m s n or , s n set the namespace in the REPL and therfore update the REPL buffer. This would be the same as (in-ns 'namespace) in the REPL buffer.

SPC m e b or , e b will evaluate the buffer, loading in the namespace and all Clojure code into the REPL, making them accessible in the REPL buffer.

SPC m e f or , e f evaluates whole expressions in the REPL, making them accessible in the REPL buffer.

Evaluating code within the source code buffer is simpler than using the REPL buffer and provides a simple way to save code to a Clojure file.
https://practicalli.github.io/spacemacs/evaluating-clojure/

It is possible to configure aspects REPL starts up and a common approach is to use the default user namespace to evaluate code. Typically this code is put into a dev/user.clj file with a :dev alias that included the dev/ directory in the class path.
http://practicalli.github.io/clojure/clojure-tools/configure-repl-startup.html

In CIDER (Spacemacs/Emacs), create a .dir-locals.el file to include the :dev alias which should then run the code from the dev/user.clj file.

((clojure-mode . ((cider-preferred-build-tool . clojure-cli)
                  (cider-clojure-cli-global-options . "-A:dev"))))  

https://practicalli.github.io/spacemacs/clojure-projects/project-configuration.html

2 Likes

thank you very much indeed.

That’s a surprise to know giving how many open source projects you’re involved with. May I ask what’s your editor/IDE setup?

You should check Sean’s videos out, where he explains your exact question: https://www.youtube.com/watch?v=ZhzMoEz4j1k&t=176s

1 Like

A small add-on of my workflow. With , e f, , e e and , e b I evaluate a form and a complete buffer respectively. So no need to ‘set the repl right’.

What I often do if i’m trying out my code is to put a (comment .... ) block below it, and inside that try my code by calling it. If i’m happy it’s then easy to make a test out of it (by evaluating that code using , e e etc), if I wish, but often times I leave a (comment ...) section below in my source code as some sort of interactive documentation.

This is unrelated to your direct question, but I felt it might be of help.

1 Like

As @Kah0ona says, I have videos up of my Atom/Chlorine workflow with Cognitect’s REBL. I’ve also been using @vlaaad’s Reveal quite a bit recently but I miss some datafy/nav conveniences from REBL: the ability to navigate through namespaces and Var definitions and use graphs (both “uses” and “used by”), as well as the more intuitive table-based datafy/nav approach. That said, Reveal is a great alternative to REBL for folks who don’t want to pay $3/month to Cognitect’s Patreon and don’t already have a Datomic license (when REBL is free). And of course REBL is closed-source whereas Reveal is open source.

I used Emacs on and off for about twenty years. I never really found a configuration that I liked and I found the ecosystem rather fragile in that updates to packages often broke things, or changed my workflows in ways I did not like. Along the way, I tried lots of other editors and IDEs. When I got into Clojure a decade ago, I settled back into Emacs but still wasn’t happy with the experience. When I saw ProtoREPL demo’d at a Clojure conference, with its inline result display, I decided to switch to Atom, and I really enjoyed it: a modern editor, with a great ecosystem of packages.

I still wasn’t really happy with the nREPL side of things: we ran REPLs in several production processes as well as locally for development and I didn’t like that we needed nREPL plus middleware bundled into our non-development processes, just to be able to connect to them and have a working editor setup.

ProtoREPL fell into disrepair (I think it was completely broken at one point by some combination of Atom and/or Ink package updates) so I was looking for a) something well-maintained for a modern editor and b) something that could work with fewer, or preferably no dependencies.

Enter Chlorine. It requires only a Socket REPL, which you can start via a JVM option for any Clojure process at all, with no dependencies at all. That was a major improvement as far as I was concerned. Early on, it still required Compliment to get auto-completion but that requirement has since been dropped and it will use it if present but has a really good auto-completion story built-in. It also supports nREPL now, for those who want to continue using that. And it has the inline display of results I liked so much from ProtoREPL.

My goal here is a rich, modern editor with a very simple toolchain on the Clojure side: no additional dependencies, and the same editor-based workflow for local and remote processes.

It’s also worth mentioning that, although we started with Leiningen a decade ago at work, we switched to Boot in 2015 and to the CLI/deps.edn in 2018. I like minimal, composable tooling. Eric Normand talks about this in his (excellent) REPL-Driven Development course, and Stu Halloway has also talked about this in Running With Scissors, REPL-Driven Development, and various podcasts. Rich has also historically used a very minimal set of tooling as well.

And finally I should talk about REBL. Since it’s something that came out of Cognitect – and therefore is favored by Stu (and Rich et al) – I wanted to try it alongside my existing editor setup. REBL can be started as your primary REPL and it opens a “viewer” based on OpenJFX, so it can also start up with a Socket REPL and therefore serve as my local REPL process for Atom/Chlorine. I love that I can see everything I evaluate in multiple view formats and use datafy/nav to explore data structures etc. REBL can render HTML pages so you can work with a web app using it, or you can view documentation inline. It can display Vars as data, showing their metadata (including docstring), their source, their uses (what has called them dynamically in the current REPL session), and the things they in turn call, and you can navigate around your code that way. As soon as datafy/nav were announced for Clojure 1.10, I added some support to clojure.java.jdbc (and built it right into next.jdbc) so that you could navigate through foreign key relationships in your data from a database. next.jdbc adds more (optional) datafication so you can also navigate into the actual structure of your database and look at tables and metadata from the database itself.

Which brings me back to a wonderful feature of Chlorine: you can write your own commands in ClojureScript and it uses sci to execute them (and you can bind keys to those dynamically added commands in Atom). Atom has always allowed for user-level extension, through CoffeeScript (or JS or TypeScript), via an init script that is loaded at startup (something I wish VS Code supported), but the ClojureScript extension point in Chlorine lets you edit/add new commands on-the-fly, while you are working, without needing to restart/reload anything. Yes, I know you can program “anything” in Emacs using elisp but a) elisp is not as nice as ClojureScript and b) the API surface area you need to know to get anything done with elisp is huge – Chlorine provides a very nice, fairly high-level API to the ClojureScript extensions, and Atom’s API is also very well documented.

Oh, and one last thing: Chlorine’s REPL console panel is readonly – you can’t type into it. That’s deliberate. It encourages you to use comment forms in your code and always evaluate from an editor so you get used to keeping your scratch code around, you have full editor support on that scratch code, and it’s easy to evolve it into tests or additional production code. It’s a good workflow – something that Rich, Stu, and Eric all do :slight_smile:

5 Likes

Sean, I think you can use REBL’s datafy/nav in Reveal as well. I made reveal to support datafy/nav better, just make sure you are on the latest version, and I would guess to get REBL’s datafy/nav extensions all you need to do is require it somewhere.

Given that REBL is closed source, I don’t know what namespace(s) would need requiring for that but it seems strange to end up with both REBL and Reveal on the classpath for development.

I’ll take a look at the latest changes in ea29 (I was on ea28 the last time I powered it up).

But I guess if I add a dependency to the class path, I will have to reload the repl ?

There are ways to load new dependencies into a running REPL, depending on which tooling you are and how you started your REPL.

I use a branch of tools.deps.alpha with an add-lib function on it (per my deps.edn in my dot-clojure repo) but that code is being reworked and some form of it will end up in Clojure itself or in an updated version of tools.deps.alpha at some point.

There’s also a library called Pomegranate (which Leiningen uses) which provides a way to “hot load” new dependencies into your REPL.

3 Likes

As of today, REBL is completely free as part of the new Cognitect dev-tools – Datomic dev-local and REBL – although it remains closed-source.

3 Likes