Tuesday, May 11, 2010

Short tutorial on extending Leiningen

We all use and love leiningen, the ultimate Clojure build tool. Sometimes, though, we want leiningen to do something it doesn't know how to do. Here is a short and simple tutorial on making your own leiningen tasks. In your project.clj, after the (defproject ...) form, add the following:
(ns leiningen.hello)
(defn hello
(println "Hello Leiningen!")
(println "ants"))

Now, when you run lein hello, you will see it print out a message to Leiningen from the ants.

So, to make a new leiningen task, all you need to do is define a new namespace under leiningen and define a function by the same name. The project variable passed to the function is a hash map containing all project information. For example, here is a slight modification of the hello task.
(ns leiningen.hello)
(defn hello
(println (format "Hello from %s project!" (:name project))))

This should print you a greeting from your project. To see what other information is in the project variable, I came up with the following task.
(ns leiningen.info
"Print all project variables and their values"
(:use [clojure.contrib.pprint :only [pprint pprint-indent]]))
(defn info
(doseq [key (keys project)] 
(println (format "%s:" (name key)))
(pprint (get project key))))

This is almost all there is to it, there are a couple of additional notes.
  • All extra arguments after the task name will be also passed to the task function, so if you want to handle arguments, define your task handler like this (defn sometask [project & args] ... )
  • Your new task will not appear in the list of available tasks and running help task on it will generate error. This is because leiningen help task uses classpath to look for tasks and will not find anything that is inside the project.clj file. If this is important to you, you can put your task into a separate project, generate a jar file and copy it into the lib directory of your main project.
  • If you do go for the task jar solution, the help task looks for the doc string in your namespace definition for the help message to display. So, your namespace definition should look like this
    (ns leiningen.silly
    "This task does something silly")
    (defn silly 
    (println "Your project SUCKS!"))
This is it kids.

No comments:

Post a Comment