Leiningen 1.3 Upgrade Plugin Classpath - clojure

I have a plugin that used to use command-line from contrib with the following in ns,
(:use [leiningen.compile :only [eval-in-project]]
[clojure.contrib command-line logging])
that used to work, I am guessing since leiningen also uses clojure and contrib it is automatically on its classpath with the new contrib structure above becomes,
(:use [leiningen.compile :only [eval-in-project]]
[clojure.tools cli logging])
it seems leiningen does not include jars from the lib/ on its class path and this fails, is there a workaround this?

Right. Unless you use eval-in-project, your code runs in Leiningen's classpath. Any code on lein's classpath is thus available to your project. These, however, are not.
Is the code that uses cli and logging inside of the eval-in-project call? If so, those jars need to be dependencies on the projects that you call the plugin in, and the use call must be passed to eval-in-project (see the documentation of eval-in-project for more info).
If the code that uses cli and logging is not inside of an eval-in-project call, then you can add those dependencies to your plugin project and it should just work. If you try to test the plugin inside of the plugin project itself, you'll need to add :eval-in-leiningen true to your project.clj.
If this doesn't help, please expand your question with more details/code.

Related

Local dependencies in Leiningen without creating a Maven repo?

I'm building a Compojure web application, and I'd like it to use functions from another Clojure project I wrote. I'm not at all familiar with Maven, and from what I've heard, it has a very steep learning curve. Unfortunately, everything I've seen suggests using a private Maven repo as a dependency and doesn't suggest an alternative. I'd really like to avoid struggling with Maven if possible. Does anyone know of an alternative? I'm currently using the latest version of Leiningen.
If the other project is also a lein project, you just need to do a "lein install" and that will take care of creating all the local maven repo stuff. Then you can just depend on that project as you would do with any other lib. For example:
(defproject mylib "1.0"
....)
lein install
(defproject myotherproject "a.b.c"
:dependencies [[mylib "1.0"]]
.....)
If you are sharing "myotherproject" with other people and you want to remove some of the inconvenience of doing a "lein install" every time you change the mylib project, have a look at the lein checkouts feature and then use the equivalent of svn externals of your VCS of choice.
'lein checkout' appears to be another way to achieve the same goal. a lot more details here and here. In general, the idea is to create a symlink to the local copy of the dependency, but the process does require one lein install. I also found this lein plugin that might be even better, but I've yet to try it myself.

Getting Leiningen to download dependencies outside of a project

I'm learning Clojure, but I'm not really building whole projects for each little code snippet, I just drop them into a REPL. Occasionally code snippets I'm exploring require a dependency (usually something that is/was in clojure.contrib).
The only way I know how to get those dependencies onto my computer is to have an empty leiningen project, add the dependency to project.clj and run lein deps.
Is there any way I can download libraries globally, outside of a project? If it's that I really really don't want to, why?
I have a small project that I use for testing code snippets and answering SO questions, and am also constantly adding dependencies. The project.clj for this project includes Pomegranate as a dependency which then makes dynamically loading other dependencies as easy as:
(use '[cemerick.pomegranate :only (add-dependencies)])
(add-dependencies :coordinates '[[my-dependency "1.2.3"]])
Give lein-try a go. It's a leiningen plugin I wrote that lets you say something like lein try [my-dependency 1.0.0] or even lein try my-dependency at the command line and drop into a REPL with the dependency available.
If you are using lein-exec as your way of running one-off scripts, you can now use a little snippet at the top of the script. Add:
(use '[leiningen.exec :only (deps)])
(deps '[[clj-time "0.8.0"]])
to the top of your clj. Now running lein exec [example.clj] will automatically pull down the requirement.
If you are new to lein exec, just add {:user {:plugins [[lein-exec "0.3.4"]]}} to your ~/.lein/profiles.clj and you can begin running lein exec on your clj files. It is a great and quick way to run code without a project.

Installing libraries with leiningen without creating project

I am learning Clojure and coming from a Ruby background.
I am looking for something analogous to gem install <library>. The various incantations of lein install do not seem to fit this bill.
Is there a way to simply install a library locally so that it can be referenced in the REPL without the need to create a project?
Seems like, you want to install a library with lein. Here is the plugin, install it and use like
lein localrepo install <filename> <[groupId/]artifactId> <version>
If your aim is merely to load libraries in the REPL consider using alembic. It loads dynamically classpaths, resolve dependencies and automatically pulls libraries from the repositories.
Here is a use case:
(require 'alembic.still)
(alembic.still/distill '[enlive "1.1.1"])
It simply requires you to add the following entry to your .lein/project.clj:
{:dev {:dependencies [[alembic "0.1.1"]]}}
See this answer.
Java and thus clojure do not generally have the the idea of globally installed libraries. You should always be creating a classpath with the minimal set of dependencies. You need somehow to specify and manage this classpath and the easiest way to do this is with leiningen, which requires a project.
leiningen automates the process of retrieving the remote libraries and placing them in your local repository which is somewhat analogous to gem install, but these libraries do not become automatically available to a REPL.
The easiest way to have a set of libraries always available is to have a 'scratch' project which you use for REPL experiments before starting a new project. It's not too much of an overhead.
In lein 2 you can update profiles.clj with package you want to install:
~\user\.lein\profiles.clj
With the first run of any project with lein, the local repo will be updated with what was incereased in profiles.clj.
Sometimes I just run lein deps without being in a project folder, this will update the local repo for you.
This way you can add any library to your project.clj or call it from repl and it will be extracted from local repo.
If you don’t have a project, you add your dependencies in your global lein user profile instead located at ~/.lein/profiles.clj.
The doc isn’t great for lein to be honest. So this part is confusing. But you edit that file as such:
{:user {:plugins [[lein-pprint "1.1.1"]]
:dependencies [[slamhound "1.3.1"]]}}
In the :plugins vector you add whatever global lein plugin you want to have. And in the :dependencies vector you add whatever library you want available globally.
Then anywhere you start a lein repl you’d have those dependencies available to you. And everywhere you run lein you’ll have the additional plugin features available to you.
If you use tools.deps instead of lein, aka, the clj command instead of the lein command. Then it is a bit different. You instead want to modify your ~/.clojure/deps.edn file. Where you’d add dependencies there instead:
{:deps {clj-time {:mvn/version "0.14.2"}}}
So if you put the above in your user deps.edn whenever you run clj command the clj-time library will be available to you.

Noir uberjar only works in build directory

I am attempting to distribute a small web application build with the clojure web framework noir. It works as expected when run with lein run. When I run lein uberjar and then java -jar project-1.0.0-standalone.jar it works as expected. However, if I move the jar file (project-1.0.0-standalone.jar) it runs, but every page results in a 404. My project.clj is the default one generated by lein noir new except I added :omit-source true and :aot :all.
I'm using:
leiningen 1.7.1
clojure 1.2.1
noir 1.2.1
How can I make a jar that can be distributed to others without source?
if you have not already added gen-class calls to your namespace definitions, adding them may fix this. You can test this by running
lein clean
lein compile
and make sure you see each of your classes being built
I believe the problem you are experiencing is because of the way noir.server/load-views requires the namespaces. If you move it from the target/ directory, it can no longer find the views directory you passed into load-views.
The workaround is to explicitly require all you're views in lieu of using the load-views function. Then you should be able run the uberjar anywhere.

writing and installing your own leiningen plugin

I have been able to run a custom plugin from within my projects project.clj, and even leiningen/plugin.clj (ie just a private plugin) - but when I go to put this plugin in its own project - I am unable to get it to work at all.
Following the advice, I should create a new project, and have a namespace of leiningen.myplugin etc etc... but the jar that I produce doesn't seem to provide the new task in the project (either via jar, or via clojars).
http://nakkaya.com/2010/02/25/writing-leiningen-plugins-101/
https://github.com/technomancy/leiningen/blob/stable/doc/PLUGINS.md
Anyone who has published a plugin care to confirm if the above is correct - or is there some crucial step I am missing? (I assume my task goes in core.clj in the plugin project)
Do you have the :eval-in-leiningen option set to true in the project.clj?
In addition if you want to use the task all around with your leiningen without having to add it to the dev dependencies of the project where you need to use it you need to use lein plugin install
Or did i miss something about your problem
Note that eval-in-leiningen doesn't need to be used for very simple project-specific plugins or tasks, and it can sometimes wreak build havoc. You can enable a Leiningen task for a given project by just using .lein-classpath for that project. More information here:
Project-level Leiningen Plugin