Reputation: 30568
I often find myself typing (ns user)
and pressing C+c M+n repeatedly when I work on clojure source code. The problem is that I often use functions like source
and doc
and they are in clojure.repl
and I don't want to :require
them to my namespaces. What are experienced clojurians doing in this case?
Clarification: I know how clojure's namespacing works. What I want to achieve is to be able to call (source myfunc)
,(doc myfunc)
etc. without the need to use fully qualified names in the REPL and without the need to require the functions from clojure.repl
in each of my namespaces.
Upvotes: 3
Views: 342
Reputation: 91597
Thanks for clearing up what you are asking for.
Leiningen has a feature called :injections which you can combine with vinyasa to get this effect If you put something like this in your leiningen profile:
~/lein/profiles.clj:
{:user {:plugins []
:dependencies [[im.chit/vinyasa "0.1.8"]]
:injections [(require 'vinyasa.inject)
(vinyasa.inject/inject
'clojure.core '>
'[[clojure.repl doc source]
[clojure.pprint pprint pp]])]}}
Because this is in your profiles.clj it only affects you. Other people who work on the project won't be affected.
My ~/.lein/profiles.clj:
{:user
{:plugins []
:dependencies [[spyscope "0.1.4"]
[org.clojure/tools.namespace "0.2.4"]
[io.aviso/pretty "0.1.8"]
[im.chit/vinyasa "0.4.7"]]
:injections
[(require 'spyscope.core)
(require '[vinyasa.inject :as inject])
(require 'io.aviso.repl)
(inject/in ;; the default injected namespace is `.`
;; note that `:refer, :all and :exclude can be used
[vinyasa.inject :refer [inject [in inject-in]]]
[clojure.pprint :refer [pprint]]
[clojure.java.shell :refer [sh]]
[clojure.repl :refer [doc source]]
[vinyasa.maven pull]
[vinyasa.reflection .> .? .* .% .%> .& .>ns .>var])]}}
which works like this:
hello.core> (./doc first)
-------------------------
clojure.core/first
([coll])
Returns the first item in the collection. Calls seq on its
argument. If coll is nil, returns nil.
nil
hello.core> (in-ns 'new-namespace)
#namespace[new-namespace]
new-namespace> (./doc first)
nil
new-namespace> (clojure.core/refer-clojure)
nil
new-namespace> (./doc first)
-------------------------
clojure.core/first
([coll])
Returns the first item in the collection. Calls seq on its
argument. If coll is nil, returns nil.
nil
Upvotes: 4
Reputation: 4513
To achieve this, you may use vinyasa library, in particular its inject
functionality. Basically you need to add needed functions from clojure.repl
namespace to clojure.core
namespace. After you won't need to require them explicitly. See the following:
user> (require '[vinyasa.inject :refer [inject]])
nil
;; injecting `source` and `doc` symbols to clojure.core
user> (inject '[clojure.core [clojure.repl source doc]])
[]
;; switching to some other namespace
user> (require 'my-project.core)
nil
user> (in-ns 'my-project.core)
#namespace[my-project.core]
;; now those functions are accessible w/o qualifier
my-project.core> (doc vector)
-------------------------
clojure.core/vector
([] [a] [a b] [a b c] [a b c d] [a b c d e] [a b c d e f] [a b c d e f & args])
Creates a new vector containing the args.
nil
Upvotes: 1