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).
Most of the time you will need only make-cli. 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`). Most of the time you will need only [[make-cli]]. See the [[trident.build]] source for some non-contrived example usage.
(dispatch cli args)Parses args and calls the function specified by cli.
If cli contains :fn but not :cli-options, dispatch will pass args
to :fn without parsing them first. See expand-cli for complete
information about the format of 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 specified by `cli`. If `cli` contains `:fn` but not `:cli-options`, `dispatch` will pass `args` to `:fn` without parsing them first. See [[expand-cli]] for complete information about the format of `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.
(expand-cli compact-cli)(expand-cli compact-cli options)Returns an expanded form of compact-cli, suitable for dispatch.
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"})
compact-cli is a map that 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
documentation output. If :desc is omitted and :fn is a var, this will
be derived from the function's docstring.
:cli-options: a seq of keys in options. This will be replaced with a
value in the format specified by parse-opts. If :cli-options is
present, --help and --edn options will also be added. --edn is
similar to the clj -Sdeps <EDN> option.
: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 compact-cli maps. If :fn is
omitted, dispatch will treat the first non-option argument as a key in
:subcommands and continue dispatching recursively. expand-cli will
also recursively expand the values of :subcommands.
: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 ...]]".
Reusing build tasks
For convenience, compact-cli can be a function or function var instead of a
map. In this case, it will be replaced with {:fn <fn>}. This can be
useful for curating build tasks as subcommands, especially build tasks not
defined with trident.cli. For example:
(expand-cli {:subcommands {"pom" #'some.ns.pom/-main
"jar" #'some.ns.jar/-main}})
Since the subcommands are vars, the --help option output will include the
first line of their docstrings. (If the functions don't have docstrings,
you can always use the map form for compact-cli and include :desc
yourself).
Since make-cli returns the expanded cli map, you can reuse it:
(expand-cli
{:subcommands
(merge
; Regular build tasks, not defined with trident.build
{"pom" #'some.ns.pom/-main
"jar" #'some.ns.jar/-main}
(:subcommands some.ns.deploy/cli))})) ; `cli` defined with `make-cli`
expand-cli is idempotent, so it's safe to give it CLI maps that have already
been expanded.
Returns an expanded form of `compact-cli`, suitable for [[dispatch]].
`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"})
```
`compact-cli` is a map that 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`
documentation output. If `:desc` is omitted and `:fn` is a var, this will
be derived from the function's docstring.
- `:cli-options`: a seq of keys in `options`. This will be replaced with a
value in the format specified by `parse-opts`. If `:cli-options` is
present, `--help` and `--edn` options will also be added. `--edn` is
similar to the `clj -Sdeps <EDN>` option.
- `: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 `compact-cli` maps. If `:fn` is
omitted, [[dispatch]] will treat the first non-option argument as a key in
`:subcommands` and continue dispatching recursively. [[expand-cli]] will
also recursively expand the values of `:subcommands`.
- `: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 ...]]"`.
**Reusing build tasks**
For convenience, `compact-cli` can be a function or function var instead of a
map. In this case, it will be replaced with `{:fn <fn>}`. This can be
useful for curating build tasks as subcommands, especially build tasks not
defined with `trident.cli`. For example:
```
(expand-cli {:subcommands {"pom" #'some.ns.pom/-main
"jar" #'some.ns.jar/-main}})
```
Since the subcommands are vars, the `--help` option output will include the
first line of their docstrings. (If the functions don't have docstrings,
you can always use the map form for `compact-cli` and include `:desc`
yourself).
Since `make-cli` returns the expanded `cli` map, you can reuse it:
```
(expand-cli
{:subcommands
(merge
; Regular build tasks, not defined with trident.build
{"pom" #'some.ns.pom/-main
"jar" #'some.ns.jar/-main}
(:subcommands some.ns.deploy/cli))})) ; `cli` defined with `make-cli`
```
`expand-cli` is idempotent, so it's safe to give it CLI maps that have already
been expanded.(main-fn cli)Returns a function suitable for binding to -main. See make-cli.
Returns a function suitable for binding to `-main`. See [[make-cli]].
(make-cli compact-cli)(make-cli compact-cli options)Returns a map with the keys :cli, :main-fn and :help.
cli: an expanded form of compact-cli and options, suitable for passing to
dispatch. See expand-cli for the format of compact-cli and options,
including tips about how to reuse other build tasks.
main-fn: a function suitable for binding to -main. It will call
dispatch, afterwards calling System/exit with the function's return
value (if it's an integer) as the exit code.
help: the auto-generated --help output for this task. Good for including in
-main's docstring.
Example:
(defn hello
"Give a friendly greeting."
[{:keys [capitalize]} the-name]
(println "Hello," (cond-> the-name capitalize clojure.string/capitalize)))
(def compact-cli {:fn #'hello
:cli-options [:capitalize]})
(def options {:capitalize ["-c" nil "Capitalize the name"]})
(let [{:keys [cli main-fn help]} (make-cli compact-cli options)]
(def ^{:doc help} -main main-fn)
; `cli` is exposed so it can be reused if needed.
(def cli 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: <program> [options]
Give a friendly greeting.
Options:
-c, --capitalize Capitalize the name
-h, --help
0 ; 0 is the return value/exit code.
=> (with-no-shutdown (-main "--capitalize" "alice"))
Hello, Alice
0
Returns a map with the keys `:cli`, `:main-fn` and `:help`.
`cli`: an expanded form of `compact-cli` and `options`, suitable for passing to
[[dispatch]]. See [[expand-cli]] for the format of `compact-cli` and `options`,
including tips about how to reuse other build tasks.
`main-fn`: a function suitable for binding to `-main`. It will call
[[dispatch]], afterwards calling `System/exit` with the function's return
value (if it's an integer) as the exit code.
`help`: the auto-generated `--help` output for this task. Good for including in
`-main`'s docstring.
Example:
```
(defn hello
"Give a friendly greeting."
[{:keys [capitalize]} the-name]
(println "Hello," (cond-> the-name capitalize clojure.string/capitalize)))
(def compact-cli {:fn #'hello
:cli-options [:capitalize]})
(def options {:capitalize ["-c" nil "Capitalize the name"]})
(let [{:keys [cli main-fn help]} (make-cli compact-cli options)]
(def ^{:doc help} -main main-fn)
; `cli` is exposed so it can be reused if needed.
(def cli 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: <program> [options]
Give a friendly greeting.
Options:
-c, --capitalize Capitalize the name
-h, --help
0 ; 0 is the return value/exit code.
=> (with-no-shutdown (-main "--capitalize" "alice"))
Hello, Alice
0
```(usage {:keys [summary subcommands desc args-spec config prog] :as cli})Returns a usage string.
summary is returned from clojure.tools.cli/parse-opts. See expand-cli
for the other keys.
Returns a usage string. `summary` is returned from `clojure.tools.cli/parse-opts`. See [[expand-cli]] for the other keys.
(validate-args {:keys [cli-options config subcommands] :as cli} args)Parses args using clojure.tools.cli/parse-opts.
Returns a map that includes either :opts and :args OR :code and
:exit-msg.
See expand-cli for the format of cli.
Parses `args` using `clojure.tools.cli/parse-opts`. Returns a map that includes either `:opts` and `:args` OR `:code` and `:exit-msg`. See [[expand-cli]] for the format of `cli`.
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 |