Fix clj-refactor Libspec Stealing
(This post is regarding a very particular issue at the intersection of Emacs, Clojure, and CIDER, so most readers can probably skip it, but I figured the solution deserved to be somewhere on the internet.)
CIDER has this awesome feature via clj-refactor where it can
automatically add missing libspecs to your
ns form as soon as you
type an aliased var name using an
:as alias you have previously used
for that namespace:
You can define a preferred set of (
:as) aliases via
cljr-magic-require-namespaces in your Emacs config, and, whether
you’ve done that or not, CIDER tries hard to be smart, offering you
choices if you’ve previously used the same alias for different
namespaces in different places in your project (e.g.
clojure.spec some places and the same for
clojure.string in other
Moreover, CIDER evaluates the namespace form, bringing in the new requires, allowing you to just keep typing and coding, without breaking your flow.
This is all fantastic, but I ran across one particular scenario where
this kept biting me: my
dev/user.clj file, I had a number of commands for managing the
state of my program during development (viz. reloaded.repl and
friends) that I used constantly, including while testing out various
functions I’d just written in the current namespace (e.g.
(new-db-query (user/db))). But I also happen to have another
(rarely-used) namespace in my app which was, somewhere, aliased as
user. Something like
Since references to the (top-level)
user namespace never occur in
the (production-shared) broader codebase, every time I typed
CIDER immediately added a require for the namespace I didn’t want
(the only usage of the alias in the codebase) and loaded it.
Meaning I not only had to remove it, but also undefine the alias (
C-c C-u)—and hopefully not accidentally trigger the same thing yet
again though muscle memory….
I tried everything I could think of to fix this, including just
user, but nothing worked, so I suspect a proper solution
is going to require an upstream patch.
In the meantime, a quick and dirty solution is just to use advice in Emacs:
;; Don't auto add `require' form for `user' namespace.
(defun cljr--unresolved-alias-ref--unless-user (alias-ref)
(unless (string= "user" alias-ref)
(advice-add 'cljr--unresolved-alias-ref :before-while
If the advice function here
essentially tells clj-refactor that an alias is already handled and it
doesn’t need to worry about adding an import for it.