leinigen repl with profile - clojure

This question is a follow up to How does one pre-load a clojure file in the leiningen repl?.
My ~/.lein/profiles.clj looks as follows:
{
:user {:source-paths ["C:/Users/username/.lein/src"] }
}
My ~/.lein/src/user.clj might look as follows:
(ns user)
(println "user file loaded")
When I run lein repl within a folder containing a project.clj, then the user.clj file is executed, but when I run lein repl from another folder it doesn't load my user profile. Is there a workaround for this or is this behavior by design? In fact, I know that Leinigen is indeed loading my profile.clj (even when there is no project.clj) because there are also other things inside (taken from the excellent pimp my repl article). Leinigen is just having problems with my additional source-paths setting.
One other question related to this is the fact that I need to specify the full path of the folder for my user.clj file : "C:/Users/username/.lein/src". When I change that to "~/.lein/src" leiningen fails to load my file.

It sounds like you just want some code loaded for your lein repl sessions. This is done with the :init key of the :repl-options in your profiles.clj. You can load-file other files in init if you want to organize in that fashion.
{:user
{:repl-options
{:init (load-file "path-to-file/user.clj")}
...}}
Note: If you are using Windows-style path delimiters /, you'll need to escape them //.

Related

Can I start Gorilla REPL from an uberjar?

I play with this great Gorilla REPL powered project ( https://bitbucket.org/probprog/anglican-examples/ to be specific), and want to use it under certain restricted circumstances.
Is there a way to produce an uberjar that can be started using only a JVM?
Well, I know how to create an uberjar for this project, but can I start a Gorilla REPL from it? If not what do I have to add and how do I start it?
EDITED Note on Juraj's answer:
I added a start file src/gorillaproxy/gorillaproxy.clj with the following content:
(ns gorillaproxy.gorillaproxy
(:use [gorilla-repl.core :only [run-gorilla-server]])
(:gen-class))
(defn -main
[& args]
(run-gorilla-server {:port 8990}))
Then I added [gorilla-repl "0.4.0"] to the dependency list (in project.clj), and the line
:main gorillaproxy.gorillaproxy
In that way the uberjar started the Gorilla REPL, and when I put the worksheets (and data, resources, .. if needed) into the same directory, everything worked fine.
Gorilla is typically run via the lein-gorilla plugin and thus isn't a part of an uberjar.
If you really want to create a bundle containing gorilla repl dependencies, then you need to add it this capability manually to your project.
The question is why would you want to do that.
Do you want to distribute these samples to somebody else? If that's the case, you'll still need to have all those worksheets in the current directory from where your uberjar is run because that's how gorilla repl discovers worksheets.
You can look at lein-gorilla source code to see how gorilla repl can be started.
I'd then at the same code to your project (create new src/core.clj file or whatever) and configure it in your project.clj as :main.
You'll also need to add gorilla-repl as a dependency to your project.clj
Notice however, that you'll need to run that uberjar from a directory where your anglican worksheets are (or a parent directory of such a directory).

access library functions in leiningen REPL

For the development of a library I started from a lein project, invoked like so:
lein new mylib
if I call lein install now, I can access my library in other projects. But trying to immidiately test the functions I wrote failed:
lein repl
...
(dir mylib.core)
Exception No namespace: mylib.core found clojure.core/the-ns (core.clj:4008)
Do I have to add something to the project.clj file maybe?
In order to use a library you must cause the code to be loaded - that it be on the classpath is not sufficient.
You can do this easily in an ns declaration in a file of course, but in the repl it can be easier to use (require '[my-lib.whatever :as w]) after which one can call (w/foo) (w/bar) etc. as expected. You can also use (in-ns 'my-lib.whatever) in order to switch to the namespace, but this will not give you a good result unless you have previously used require or use or load-file etc. to get the definitions first.
Let's say you created a new library named clj-foo.
% lein new clj-foo
Start your repl.
% cd clj-foo
% lein repl
In the repl, load the main entry point to your library and switch to its namespace.
(load-file "src/clj_foo/core.clj")
(ns clj-foo.core)
Now you're in the clj-foo.core namespace, make sure to add back in the repl ns to get things like doc available.
(use 'clojure.repl)
That's it. You're all set to start calling functions in your library. Note that other library files will be available from the clj-foo.core namespace if they were loaded by namespace declaration at the top of clj_foo/core.clj. If not, then you'll need to invoke load-file with their path as well.
If you make changes in core.clj. You can invoke load-file again to pick up the new code. As you progress, you can use cider to facilitate loading of individual functions and files. But that's for another question. :)
You need to add a dependency to use your library from another project. To do this add a vector (a tuple-2) to the vector that is the value of the :dependencies key in the project.clj file. Here's an example:
:dependencies [[org.clojure/clojure "1.7.0"]
[org.clojure/clojurescript "1.7.170"]
[org.clojure/core.async "0.2.371"]
[default-db-format "0.1.0-SNAPSHOT"]
[com.andrewmcveigh/cljs-time "0.3.14"]]
My own local library is called default-db-format. Its really no different to adding a dependency for com.andrewmcveigh/cljs-time.
As you say you can already do this, but are having trouble getting a REPL connection to the project of the library itself. When you go (in-ns 'some-path), you need the single quote in front of some-path. Note that some-path is a different thing to the name of your library.
Rather than use lein repl you can use the figwheel repl - if your project is setup with figwheel. My library has only one entry point and that is lein figwheel devcards. After that I had no problem going to a namespace and trying out a function:
cljs.user=> (in-ns 'default-db-format.core)
nil
default-db-format.core=> (check 1 2)
As noisesmith mentioned having a REPL in your IDE is the best setup. No fiddly typing just bring up pre-configured REPLs (per namespace) with the click of a button (or keystroke). Figwheel/Cursive setup instructions here.
I was also facing the same issue with the following configuration:
Leiningen 2.9.0 on Java 1.8.0_201 Java HotSpot(TM) 64-Bit Server VM
My file looks like this, and from the repl I desired to invoke the foo function
(ns cljtest.test
(:gen-class))
(defn foo [input]
(assoc {} "a" 123))
Both these approaches worked fine for me on the repl.
1)Switch to the appropriate name space:
cljtest.core=> (in-ns 'cljtest.test)
#object[clojure.lang.Namespace 0x90175dd "cljtest.test"]
cljtest.test=> (foo nil)
{"a" 123}
cljtest.test=>
2)Require the appropriate name space:
cljtest.core=> (require '[cljtest.test :as test])
nil
cljtest.core=> (test/foo nil)
{"a" 123}
cljtest.core=>

Dependencies in profiles.clj aren't loaded in lein repl

.lein/profiles.clj has dependencies as,
{:user {}
:repl {:dependencies [[org.clojure/clojure "1.4.0"]
[ring/ring "1.1.6"]]
}}
in repl
(require 'ring.adapter.jetty)
throws,
java.io.FileNotFoundException: Could not locate ring/adapter/jetty__init.class or ring/adapter/jetty.clj on classpath: (NO_SOURCE_FILE:0)
This means, ring dependency is not loaded in repl shell. Any mistakes?
Firstly, I would recommend reading https://github.com/technomancy/leiningen/blob/stable/doc/PROFILES.md as I'm not sure you are using profiles correctly. In particular, at the end it shows a way of debugging your profiles, which will show you what is going on.
Secondly, I'm not sure about "there is no project - I am running it from bash shell". If your loading jetty and using ring, you will also need code which sets handlers, routes and probably middleware. this means code files, which means a project tree. Create a basic project with lein new and run from the root of that project.
However, if you really do need to do it as you say, I would suggest you just do
{:user {:dependencies [[....]]}} as your profiles.clj as I suspect that what is happening is that lein is not loading your :repl profile. You could also try running lein with the explicit profile i.e. lein with-profile +repl repl

How do I get Clojure to load a project-specific .clj file on REPL launch?

How do I get Clojure to load a project-specific .clj file on repl launch? I want to have some function available to me whenever I open up a new repl (I'm using nREPL on emacs, for what it's worth...)
Thanks
Add an entry to your project.clj's :repl-options like the following
:repl-options {:init (load-file "src/your-project-specific-file.clj") }
If you'd like your functions to be available in all your REPLs, add an entry the user profile in .lein/profiles.clj as follows:
{
:user
{:repl-options {:init (load-file "path/to/file.clj")}}
}

How to add classpath with emacs slime/conjure?

I setup emacs slime/clojure as written here.
When I run (doseq [p (.getURLs (java.lang.ClassLoader/getSystemClassLoader))] (println (.getPath p))) to get classpath, I get the following.
/Users/smcho/.swank-clojure/clojure-1.1.0-master-20091202.150145-1.jar
/Users/smcho/.swank-clojure/clojure-contrib-1.1.0-master-20091212.205045-1.jar
/Users/smcho/.swank-clojure/swank-clojure-1.1.0.jar
How can I add classpath for emacs/slime for clojure?
The procedure differs depending on whether you are using slime-connect to start slime (by connect to a remote swank server, created with lein swank, for example) or you are starting slime using M-X slime.
If you're using slime-connect, you'll need to modify the classpath of the java process that is running the swank server. If you're starting the swank server using lein swank, simply add the jars you want to be part of your classpath to the project's lib directory.
On the other hand, if you're starting slime using M-X slime, the following elisp code will do the magic for you (just place it in your ~/.emacs file).
(eval-after-load "swank-clojure"
'(progn
(add-to-list 'swank-clojure-classpath
"/Users/smcho/.clojure/")
(add-to-list 'swank-clojure-classpath
"/Users/smcho/.clojure/blah.jar")))
This will add /Users/smcho/.clojure/ and /Users/smcho/.clojure/blah.jar to the classpath. (Please note that you'll either need to restart emacs or reload the .emacs file: type M-X load-library and then type .emacs on the next prompt.)
I believe the advised way to fire up a clojure reple nowadays is to use lein swank, and use \M-x slime-connect. See http://github.com/technomancy/leiningen/ for a detailed description of this tool.
Using leiningen, you can configure your project using a configuration file, project.clj. On this file you may require remotely (maven-)published jars, and by running lein deps you will get a "lib" directory with all the jars. Since the lein swank command uses that directory as a classpath, all you have to do is to add your jars to that directory.
That said, if you're still using \M-x swank-clojure-project, it will also detect your jars under that directory.
However, if you're just using a plain \M-x slime to fire a clojure repl, then I think there's no "clean" solution (aside from adding the path to your global environment's $CLASSPATH or to use some elisp voodoo - like the one in seh's answer - to change the java vm command arguments. But I believe this is only intended to do some quite basic experiments, and shouldn't be used for any project-based work (exactly for this reason!)
If you're willing to hard-code the list of Jar files, this Emacs Lisp form should suffice:
(let ((base-path "/Users/smcho/.swank-clojure"))
(setq swank-clojure-classpath
(append
swank-clojure-classpath
(mapcar (lambda (d)
(expand-file-name d base-path))
'("clojure-1.1.0-master-20091202.150145-1.jar"
"clojure-contrib-1.1.0-master-20091212.205045-1.jar"
"swank-clojure/swank-clojure-1.1.0.jar")))))
That takes your list of Jar files and adds them to the variable swank-clojure-classpath. Note that this form must be evaluated by Emacs, not SLIME's Swank. It's used by Emacs to start up the Java process that will run Clojure and Swank within it.
There are more elaborate ways to set up the class path for a project, such as including Maven-style paths below a designated project root directory.