Tools for wrapping build tasks in CLIs.
Like cli-matic, this provides a higher-level wrapper over
clojure.tools.cli. However, trident.cli is designed specifically for
making build tasks easily reusable (including tasks not defined using
trident.cli).
See _cli_format.
Most of the time, the only thing you'll need from this namespace is
defmain. See the [[trident.build]] source for some non-contrived example
usage.
Tools for wrapping build tasks in CLIs. Like `cli-matic`, this provides a higher-level wrapper over `clojure.tools.cli`. However, `trident.cli` is designed specifically for making build tasks easily reusable (including tasks not defined using `trident.cli`). See [[_cli_format]]. Most of the time, the only thing you'll need from this namespace is [[defmain]]. See the [[trident.build]] source for some non-contrived example usage.
Build task interfaces are defined using a cli object. Example:
(defn hello
"Give a friendly greeting."
[{:keys [capitalize]} the-name]
(println "Hello," (cond-> the-name capitalize clojure.string/capitalize)))
(def options {:capitalize ["-c" nil "Capitalize the name"]
:foo ["-x" "FOO" "Stores an argument in `:foo`."]})
(def cli {:fn #'hello
:prog "clj -m hello"
:options options
:option-keys [:capitalize]})
(defmain cli)
; Normally `main-fn` will shutdown the JVM, but we can prevent this using
; `trident.cli.util/with-no-shutdown`:
=> (with-no-shutdown (-main "--help"))
Usage: clj -m hello [options]
Give a friendly greeting.
Options:
-c, --capitalize Capitalize the name
--edn EDN Additional options. Overrides CLI options.
-h, --help
0 ; 0 is the return value/exit code.
=> (with-no-shutdown (-main "--capitalize" "alice"))
Hello, Alice
0
options are the same as described in clojure.tools.cli/parse-opts except
that the long option is defined as a key in the map, not as the second
argument in the vector. Instead of writing:
(def options [["-f" "--foo FOO" "The foo"]
["-b" "--bar" "Toggle the bar"]])
You would write:
(def options {:foo ["-f" "FOO" "The foo"]
:bar ["-b" nil "Toggle the bar"})
Options are defined like this so that they can be easily reused by other build tasks.
cli can have the following keys:
:fn: a function or function var. If present, dispatch will apply this
function to the parsed options and any remaining arguments, as returned by
clojure.tools.cli/parse-opts. If not present, :subcommands must be
present.
:desc: a seq of strings describing this task, used in the --help output.
If :desc is omitted and :fn is a var, this will be derived from the
function's docstring.
:options: see above.
:option-keys: a seq of keys in the :options map This defines which
options are actually used for this command. --edn and --help options
will be added automatically unless :fn does its own CLI processing.
See validate-args and cli-processing?.
:config: a seq of filenames. If any of the files exist, their contents
will be read as EDN and merged (in the order given) with the results of
parse-opts. Config files will override default option values but will
be overridden by any explicitly provided CLI options. Config files can
contain keys not included in the CLI options.
:subcommands: a map from strings to more cli maps. If :fn is omitted,
dispatch will treat the first argument as a key in :subcommands
and continue dispatching recursively.
:prog: text to use for the program name in the "Usage: ..." line in
--help output, e.g. "clj -m my.namespace".
:args-spec: a specification of the non-option arguments to use in the
"Usage: ..." line in --help output, e.g. "[foo1 [foo2 ...]]".
:cli-processing?: see cli-processing?.
See the [[trident.build]] source for some more in-depth examples.
Reusing build tasks
You can use build tasks that aren't defined with trident.cli. Example:
(ns some.ns.pom)
(defn -main
"Some pom task"
[& args]
(when (= (first args) "--help")
(println "hello"))
(System/exit 0))
...
(ns your.ns
(:require [trident.cli :refer [defmain]]
[trident.cli.util :refer [with-no-shutdown]]))
; For convenience, `#'some.ns.pom/-main` is the same as
; `{:fn #'some.ns.pom/-main}`.
(def cli {:subcommands {"pom" #'some.ns.pom/-main
"jar" #'some.ns.jar/-main}})
(defmain cli)
=> (with-no-shutdown (-main "--help"))
Usage: <program> [options] <subcommand> [<args>]
Options:
-h, --help
Subcommands:
pom Some pom task
jar Some jar task
See `<program> <subcommand> --help` to read about a specific subcommand.
0
=> (with-no-shutdown (-main "pom" "--help"))
hello
0
Build task interfaces are defined using a `cli` object. Example:
```
(defn hello
"Give a friendly greeting."
[{:keys [capitalize]} the-name]
(println "Hello," (cond-> the-name capitalize clojure.string/capitalize)))
(def options {:capitalize ["-c" nil "Capitalize the name"]
:foo ["-x" "FOO" "Stores an argument in `:foo`."]})
(def cli {:fn #'hello
:prog "clj -m hello"
:options options
:option-keys [:capitalize]})
(defmain cli)
; Normally `main-fn` will shutdown the JVM, but we can prevent this using
; `trident.cli.util/with-no-shutdown`:
=> (with-no-shutdown (-main "--help"))
Usage: clj -m hello [options]
Give a friendly greeting.
Options:
-c, --capitalize Capitalize the name
--edn EDN Additional options. Overrides CLI options.
-h, --help
0 ; 0 is the return value/exit code.
=> (with-no-shutdown (-main "--capitalize" "alice"))
Hello, Alice
0
```
`options` are the same as described in `clojure.tools.cli/parse-opts` except
that the long option is defined as a key in the map, not as the second
argument in the vector. Instead of writing:
```
(def options [["-f" "--foo FOO" "The foo"]
["-b" "--bar" "Toggle the bar"]])
```
You would write:
```
(def options {:foo ["-f" "FOO" "The foo"]
:bar ["-b" nil "Toggle the bar"})
```
Options are defined like this so that they can be easily reused by other build
tasks.
`cli` can have the following keys:
- `:fn`: a function or function var. If present, [[dispatch]] will apply this
function to the parsed options and any remaining arguments, as returned by
`clojure.tools.cli/parse-opts`. If not present, `:subcommands` must be
present.
- `:desc`: a seq of strings describing this task, used in the `--help` output.
If `:desc` is omitted and `:fn` is a var, this will be derived from the
function's docstring.
- `:options`: see above.
- `:option-keys`: a seq of keys in the `:options` map This defines which
options are actually used for this command. `--edn` and `--help` options
will be added automatically unless `:fn` does its own CLI processing.
See [[validate-args]] and [[cli-processing?]].
- `:config`: a seq of filenames. If any of the files exist, their contents
will be read as EDN and merged (in the order given) with the results of
`parse-opts`. Config files will override default option values but will
be overridden by any explicitly provided CLI options. Config files can
contain keys not included in the CLI options.
- `:subcommands`: a map from strings to more `cli` maps. If `:fn` is omitted,
[[dispatch]] will treat the first argument as a key in `:subcommands`
and continue dispatching recursively.
- `:prog`: text to use for the program name in the "Usage: ..." line in
`--help` output, e.g. `"clj -m my.namespace"`.
- `:args-spec`: a specification of the non-option arguments to use in the
"Usage: ..." line in `--help` output, e.g. `"[foo1 [foo2 ...]]"`.
- `:cli-processing?`: see [[cli-processing?]].
See the [[trident.build]] source for some more in-depth examples.
**Reusing build tasks**
You can use build tasks that aren't defined with `trident.cli`. Example:
```
(ns some.ns.pom)
(defn -main
"Some pom task"
[& args]
(when (= (first args) "--help")
(println "hello"))
(System/exit 0))
...
(ns your.ns
(:require [trident.cli :refer [defmain]]
[trident.cli.util :refer [with-no-shutdown]]))
; For convenience, `#'some.ns.pom/-main` is the same as
; `{:fn #'some.ns.pom/-main}`.
(def cli {:subcommands {"pom" #'some.ns.pom/-main
"jar" #'some.ns.jar/-main}})
(defmain cli)
=> (with-no-shutdown (-main "--help"))
Usage: <program> [options] <subcommand> [<args>]
Options:
-h, --help
Subcommands:
pom Some pom task
jar Some jar task
See `<program> <subcommand> --help` to read about a specific subcommand.
0
=> (with-no-shutdown (-main "pom" "--help"))
hello
0
```(cli-processing? cli)Returns true if arguments should be parsed before passing them to (:fn cli).
Parsing is disabled if :fn is specified but :option-keys and :config
aren't. This can be overridden by setting :cli-processing?.
Returns true if arguments should be parsed before passing them to `(:fn cli)`. Parsing is disabled if `:fn` is specified but `:option-keys` and `:config` aren't. This can be overridden by setting `:cli-processing?`.
(defmain cli)Defines -main as an entry point for cli.
cli's --help output is used as the docstring. See _cli_format, help
and main-fn.
Defines `-main` as an entry point for `cli`. `cli`'s `--help` output is used as the docstring. See [[_cli_format]], [[help]] and [[main-fn]].
(description cli)Returns cli's description as a seq of lines.
The description will be derived from cli's fn's docstring if :desc isn't
present.
Returns `cli`'s description as a seq of lines. The description will be derived from cli's fn's docstring if `:desc` isn't present.
(dispatch cli args)Parses args and calls the function or subcommand specified by cli.
Returns an integer exit code. If the dispatched function returns an integer,
that will be the exit code, otherwise it will be 0. If System/exit is called
during execution, dispatch will disable the call and return the exit code.
Calls to shutdown-agents will also be disabled.
Parses `args` and calls the function or subcommand specified by `cli`. Returns an integer exit code. If the dispatched function returns an integer, that will be the exit code, otherwise it will be 0. If `System/exit` is called during execution, `dispatch` will disable the call and return the exit code. Calls to `shutdown-agents` will also be disabled.
(help cli)Returns the --help output for cli.
Returns nil if cli's function does its own CLI processing. See
cli-processing?.
Returns the `--help` output for `cli`. Returns nil if `cli`'s function does its own CLI processing. See [[cli-processing?]].
(main-fn cli)Returns a function suitable for binding to -main.
Calls through to dispatch and passes the return value to System/exit.
Returns a function suitable for binding to `-main`. Calls through to [[dispatch]] and passes the return value to `System/exit`.
(usage {:keys [subcommands args-spec config prog] :as cli} summary)Returns a usage string.
summary is returned from clojure.tools.cli/parse-opts.
Returns a usage string. `summary` is returned from `clojure.tools.cli/parse-opts`.
(validate-args {:keys [options option-keys config subcommands] :as cli} args)Parses args using clojure.tools.cli/parse-opts.
Adds --edn and --help opts. --edn is similar to the clj -Sdeps <EDN>
option. Returns a map that includes either :opts and :args OR :code and
:exit-msg.
Parses `args` using `clojure.tools.cli/parse-opts`. Adds `--edn` and `--help` opts. `--edn` is similar to the `clj -Sdeps <EDN>` option. Returns a map that includes either `:opts` and `:args` OR `:code` and `:exit-msg`.
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |