DEV Community

José Luis Lafuente
José Luis Lafuente

Posted on • Originally published at lafuente.me on

Custom Clojure helpers in your REPL

The problem #

Over time, I wrote several Clojure helper functions I use while I'm writing new code. I want to load those helpers every time I start a Clojure REPL. How can I make those helpers available in any Clojure project I'm working on? Especially in 3rd party projects I don't control.

The solution #

Traditionally, Clojure developers put development utilities in a user.clj file, since Clojure automatically loads any user.clj found in the classpath. In recent Clojure versions, Clojure CLI was introduced, and now we can call any Clojure function from the command line. Knowing that, a better alternative is to move all our helpers to their own project, and to create an alias in our ~/.config/clojure/deps.edn for those utilities.

As an example, let's suppose this is the main file for my helpers project:

(ns local-utils)

(defn init
  [{:keys [main]]
  (println "Loading helpers...")
  (load-file main))
Enter fullscreen mode Exit fullscreen mode

We can add an alias in our deps.edn file:

{:aliases
 {:user {:exec-fn local-utils/init
         :extra-deps {me.lafuente/clj-dev-utils {:local/root "$HOME/projects/clj-dev-utils"}}}}}
Enter fullscreen mode Exit fullscreen mode

Now, in any project, we can do clj -X:foo:bar:user :main "path/to/main.clj". In this example, we are just printing a message before loading the main entry point, but we can do whatever we want.

My personal Clojure helpers are here: https://github.com/jlesquembre/clj-dev-utils

My init function loads some helper utilities, initializes portal, enables malli instrumentation (if present in the classpath) and starts a nREPL server. We can also provide the main function to be loaded.

A library I'm using for my helpers is https://github.com/gfredericks/dot-slash-2 With it, I can create aliases under the . namespace. For example, ./sh points to clojure.java.shell/sh. The . namespace is loaded automatically, so I can evaluate (./sh "ls") in any file without an explicit require

Top comments (0)