# My slides for Clojure Conj 2010
# (c) 2010 Phil Hagelberg
# Use epresent to view: http://github.com/technomancy/epresent
# Load it up and hit M-x epresent-run-frame in this buffer
* @Making Leiningen work for You
[images/leiningen.png ]
** Clojure Conj 2010
** Phil Hagelberg
* @Making Leiningen work for You
# Simple aspirations:
** Designed to not set your hair on fire
**  
** Started 31 October 2009... released 17 November
** 
** 50+ contributors; 20000+ downloads
** 
** Used by ~70% of OSS Clojure projects (c. July)
* @Usage
** You know the drill:
**  
=$ lein new marabunta=
=$ find . -type f=
=./README=
=./project.clj=
=./src/marabunta/core.clj=
=./test/marabunta/test/core.clj=
=./.gitignore=
# lein new marabunta
# cd marabunta; tree
# lein repl # deps happens automatically, talk about socket repl
# lein test # this is just a sanity check, not a TDD aid
* @Usage: project.clj
  -|clojure-mode
    (defproject marabunta "1.0.0-SNAPSHOT"
      :description "A sample project"
      :url "http://example.com/marabunta"
      :dependencies [[clojure "1.2.0"]
                     [robert/hooke "1.0.2"]]
      :dev-dependencies [[lein-difftest "1.0.0"]
                         [swank-clojure "1.2.1"]]
      :repositories {"private" {:url "http://private.repo"
                                :username "milgrim"
                                :password "locative.1"}})|
* @Usage: Dependencies
[images/clojars.png ]
* @Usage: Publishing
=$ lein jar && lein pom=
=$ scp pom.xml *jar clojars.org:=
** 
** Now everyone can depend on it.
* @Advanced: Test Selectors
** New in 1.4
** 
  -|clojure-mode
    ;; in project.clj:
    :test-selectors {:integration :integration
                     :default (fn [m] [...])
                     :all (constantly true)}|
** 
=$ lein test :integration=
** 
** Will skip deftests without :integration in metadata.
** 
** You can create/compose arbitrary predicates.
* @Advanced: User Plugins
=$ ln -s swank-clojure.jar ~/.lein/plugins=
** 
=$ lein help swank=
=Arguments: ([] [port] [port host & opts])=
=Launch swank server for Emacs [...]=
** 
** Doesn't need to be added to every project.clj file.
** 
** Coming in 1.4: plugin task to manage installation.
* @Advanced: Checkout Deps
=$ mkdir checkouts=
=$ ln -s ~/src/ring checkouts=
=$ lein classpath # has ring's src=
**  
** Useful for hacking two projects in parallel.
** 
** No need for the "install, switch projects, deps, restart" dance.
* @Advanced: Shell Wrappers
=$ lein install swank-clojure 1.3.0-SNAPSHOT=
=$ ~/.lein/bin/swank-clojure=
=#<ServerSocket ServerSocket[...]>=
**  
** Nicer if you put ~/.lein/bin on your $PATH.
* @Advanced: Shell Wrappers
** Customizing Shell Wrappers
**  
  -|clojure-mode
    ;; in project.clj

    :shell-wrapper {:bin "bin/marabunta"
                    :main marabunta.core}|
** 
** Classpath and -main are interpolated into %s with format.
**  
** Let's improve the state of CLI Clojure.
* @Writing Tasks
** Tasks are just functions.
** 
  -|clojure-mode
    (ns leiningen.mytask)

    (defn mytask [project]
      (println "My project:" project))|
** 
** Q: How should X be represented?
** A: clojure.lang.IFn
**  
** Can leverage memoize, composability, etc.
** 
** Project arg detected from arglists.
* @Writing Tasks: JVM Isolation
** We can't allow Leiningen's code to mix with the project.
** 
** Launches a subprocess with the project's classpath.
** 
** Allows projects to use any Clojure version.
** 
  -|clojure-mode
    (eval-in-project project
      `(doseq [n# '~namespaces]
         (when-not ~*silently*
           (println "Compiling" n#))
         (clojure.core/compile n#)))|
# Packaging tasks up as jars.
* @Extending Tasks
** Robert Hooke!
** 
  -|clojure-mode
    (defn spacing [f x]
      (f (apply str (interpose " " x))))

    (defn embiggen [f x]
      (f (.toUpperCase x)))

    (add-hook #'println spacing)
    (add-hook #'println embiggen)

    (println "foobar") ;; => F O O B A R|
* @Extending Tasks: Robert Hooke
** Hooke gives you total control over function execution.
** 
*** binding (see test selectors)
** 
*** decide not to continue
** 
*** modify arguments
** 
*** add side-effects
** 
*** return different value
# want to be evil? use serializable-fn and pick f apart!
* @Extending Tasks: Guidelines
** Normally add hooks to Leiningen tasks or eval-in-project.
** 
** ... but you can hook any function.
** 
** 
** 
** Caveats:
** 
*** Don't bother hooking functions you control.
** 
*** Accept the same ranges of arguments as the original.
** 
*** Hooking multimethods makes new defmethods impossible.
* @Community
** Leiningen is the most-contributed-to Clojure project.
** 
[images/impact.png ]
** 
** 50+ contributors as of early October:
** 
** http://www.ohloh.net/p/leiningen/contributors
* @Community
** How do you make your project easy to contribute to?
** 
*** Communicate low hanging fruit. (LHF)
** 
*** Document internals, maintain a hacking guide.
** 
*** Accept patches promptly.
** 
*** Trust people! Commit rights should be easy to get.
** 
*** Oh yeah, and stickers.
* @Community: Plugins
** Plugins are just jars that define tasks or include hooks.
** 
*** lein-multi
** 
*** lein-difftest
** 
*** radagast
** 
*** leiningen-war
** 
*** ...and many more:
** 
** http://github.com/technomancy/leiningen/wiki/Plugins
* @The Future
** • 1.4 release: test selectors, plugin consolidation.
** 
** • Aether: aka Maven, the Good Parts.
** 
** • Explicit public API.
** 
** • Better Nailgun support for quick test runs.
** 
** • Use jars straight out of ~/.m2/repository.
** 
** • Make it easier to use Hudson. (CloudBees)
* @Thanks!
** 
** Questions?
** 
** 
** 
** 
=$ git clone git://enigma.local/lein.git=
** 
** http://github.com/technomancy/leiningen
** 
** http://technomancy.us
** 
** http://p.hagelb.org/conj-2010-slides.org.html

Generated by Phil Hagelberg using scpaste at Fri Oct 22 13:55:31 2010. PDT. (raw)