Full Clojure project in 5 seconds!
Every time you start a new Clojure project, there is a lot of boilerplate that needs to be added:
deps.edn
with aliases to run tests and build actionsbuild.clj
with build actions.gitignore
README.md
- you name it…
Creating all these can be easily automated with deps-new.
Install deps-new
deps-new
intended to be installed as a "tool" for Clojure CLI.
"Tools" in Clojure CLI
Tools are 3rd party libraries that can be installed and than invoked from Clojure CLI using clj -T
option. They use their own classpath and do not interfere with the project's deps.edn
if you run tool commands from the project directory.
Few commands you may need:
clj -Ttools list
- to view already installed tools
clj -Ttools remove :tool tool-name
- to remove the tool
clj -Ttools install tool-path tool-version :as tool-name
- to install a new tool
More info about tools you can find in this video.
Installing deps-new
tool
Here is a command to add deps-new
to your system
clojure -Ttools install io.github.seancorfield/deps-new '{:git/tag "v0.4.13"}' :as new
:as new
part of the command means that "new" is now a name for deps-new
tool on your system. You can use any name you want.
Let's check our list of tools now:
$ clj -Ttools list
TOOL LIB TYPE VERSION
new io.github.seancorfield/deps-new :git v0.4.13
tools io.github.clojure/tools.tools :git v0.2.8
To check what functions new
tool exposes you can run the command:
clojure -A:deps -Tnew help/doc
Create a library
Now, when deps-new
is installed, we can use it to create a new library.
The following command will create a library with root namespace vkjr
and one source file mycoollib.clj
in it
$ clojure -Tnew lib :name vkjr/mycoollib
Creating project from org.corfield.new/lib in mycoollib
And here is a content of new library:
mycoollib
├── .gitignore
├── CHANGELOG.md
├── LICENSE
├── README.md
├── build.clj
├── deps.edn
├── doc
│ └── intro.md
├── pom.xml
├── resources
│ └── .keep
├── src
│ └── vkjr
│ └── mycoollib.clj
└── test
└── vkjr
└── mycoollib_test.clj
Top level directory of the library was also named mycoollib
but you can override this behavior by providing additional key/value pair to the library creation command :target-dir some-folder-name
.
Content of created library
As you can see, there are plenty of automatically generated files in our new lib.
deps.edn
from the start contains aliases for testing and build actions
{:paths ["src" "resources"]
:deps {org.clojure/clojure {:mvn/version "1.11.1"}}
:aliases
{:test
{:extra-paths ["test"]
:extra-deps {org.clojure/test.check {:mvn/version "1.1.1"}
io.github.cognitect-labs/test-runner
{:git/tag "v0.5.1" :git/sha "dfb30dd"}}}
:build {:deps {io.github.seancorfield/build-clj
{:git/tag "v0.8.2" :git/sha "0ffdb4c"}}
:ns-default build}}}
src/vkjr/mycoollib.clj
contains a dummy function
(ns vkjr.mycoollib)
(defn foo
"I don't do a whole lot."
[x]
(prn x "Hello, World!"))
And in test/vkjr/mycoollib_test.clj
already exists one failing test
(ns vkjr.mycoollib-test
(:require [clojure.test :refer :all]
[vkjr.mycoollib :refer :all]))
(deftest a-test
(testing "FIXME, I fail."
(is (= 0 1))))
build.clj
contains build actions test
, ci
, install
and deploy
(ns build
(:refer-clojure :exclude [test])
(:require [clojure.tools.build.api :as b] ; for b/git-count-revs
[org.corfield.build :as bb]))
(def lib 'net.clojars.vkjr/mycoollib)
(def version "0.1.0-SNAPSHOT")
#_ ; alternatively, use MAJOR.MINOR.COMMITS:
(def version (format "1.0.%s" (b/git-count-revs nil)))
(defn test "Run the tests." [opts]
(bb/run-tests opts))
(defn ci "Run the CI pipeline of tests (and build the JAR)." [opts]
(-> opts
(assoc :lib lib :version version)
(bb/run-tests)
(bb/clean)
(bb/jar)))
(defn install "Install the JAR locally." [opts]
(-> opts
(assoc :lib lib :version version)
(bb/install)))
(defn deploy "Deploy the JAR to Clojars." [opts]
(-> opts
(assoc :lib lib :version version)
(bb/deploy)))
Note, that build.clj
implements actions using the build-clj library instead of standard Clojure's tools.build
. That library hides some unnecessary details and provides the functionality of deploying to Clojars, which is missed in tools.build
There are a bunch of other useful files also: .gitignore
, README.md
, pom.xml
, LICENSE
.. real time-saver, ha?
Create an application
Creating an application with deps-new
as simple as a library:
$ clojure -Tnew app :name vkjr/mycoolapp
Creating project from org.corfield.new/app in mycoolapp
And here is a folder structure:
mycoolapp
├── .gitignore
├── CHANGELOG.md
├── LICENSE
├── README.md
├── build.clj
├── deps.edn
├── doc
│ └── intro.md
├── pom.xml
├── resources
│ └── .keep
├── src
│ └── vkjr
│ └── mycoolapp.clj
└── test
└── vkjr
└── mycoolapp_test.clj
Main differences from the library project:
src/vkjr/mycoolapp.clj
contains the (-main)
and (greet)
functions
(ns vkjr.mycoolapp
(:gen-class))
(defn greet
"Callable entry point to the application."
[data]
(println (str "Hello, " (or (:name data) "World") "!")))
(defn -main
"I don't do a whole lot ... yet."
[& args]
(greet {:name (first args)}))
deps.edn
has additional aliases run-m
and run-x
to run (main) and (greet) functions respectively
...
{:run-m {:main-opts ["-m" "vkjr.mycoolapp"]}
:run-x {:ns-default vkjr.mycoolapp
:exec-fn greet
:exec-args {:name "Clojure"}}
...
}
build.clj
creates an uberjar instead of a jar and doesn't have (install) and (deploy) functions
...
(defn ci "Run the CI pipeline of tests (and build the uberjar)." [opts]
(-> opts
(assoc :lib lib :version version :main main)
(bb/run-tests)
(bb/clean)
(bb/uber)))
Create a minimal "scratch" project
For the cases when you don't need a full-blown application, but merely a playground, deps-new
supports creating a "scratch" projects:
$ clojure -Tnew scratch :name playground
Creating project from org.corfield.new/scratch in playground
Folder structure for such "scratch":
playground
├── deps.edn
└── src
└── scratch.clj
With almost empty deps.edn
and scratch.clj
with (-main) and (greet) functions, like in the application example
Using deps-new
you can create your own project template, but this is another story… ;)