Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ For breaking changes, check [here](#breaking-changes).

[Babashka CLI](https://github.com/babashka/cli): turn Clojure functions into CLIs!

## Unreleased

- [#116](https://github.com/babashka/cli/issues/116): Undeprecate `:collect` option to support custom transformation of arguments to collections

## v0.8.62 (2024-12-22)

- Fix [#109](https://github.com/babashka/cli/issues/109): allow options to start with a number
Expand Down
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,19 @@ Arguments that start with `--no-` arg parsed as negative flags (since 0.7.51):
;;=> {:colors false}
```

### Custom collection handling

Usually the above will suffice, but for custom transformation to a collection, you can use `:collect`.
Here's an example of parsing out `,` separated multi-arg-values:

``` clojure
(cli/parse-opts ["--foo" "a,b" "--foo=c,d,e" "--foo" "f"]
{:collect {:foo (fn [coll arg-value]
(into (or coll [])
(str/split arg-value #",")))}})
;; => {:foo ["a" "b" "c" "d" "e" "f"]}
```

### Auto-coercion

Since `v0.3.35` babashka CLI auto-coerces values that have no explicit coercion
Expand Down Expand Up @@ -430,6 +443,7 @@ An explanation of each key:
- `:require`: `true` make this opt required.
- `:validate`: a function used to validate the value of this opt (as described
in the [Validate](#validate) section).
- `:collect`: for custom collection/transformation of argument values

## Help

Expand Down
1 change: 1 addition & 0 deletions src/babashka/cli.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,7 @@
* `:exec-args` - a map of default args. Will be overridden by args specified in `args`.
* `:no-keyword-opts` - `true`. Support only `--foo`-style opts (i.e. `:foo` will not work).
* `:args->opts` - consume unparsed commands and args as options
* `:collect` - a map of collection fns. See [custom collection handling](https://github.com/babashka/cli#custom-collection-handling).

Examples:

Expand Down
26 changes: 20 additions & 6 deletions test/babashka/cli_test.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,10 @@
:coerce {:verbose []}}))))

(deftest spec-test
(let [spec {:from {:ref "<format>"
(let [multi-arg-val-collect (fn [coll arg-value]
(into (or coll [])
(str/split arg-value #":")))
spec {:from {:ref "<format>"
:desc "The input format. <format> can be edn, json or transit."
:coerce :keyword
:alias :i
Expand All @@ -189,18 +192,23 @@
:paths {:desc "Paths of files to transform."
:coerce []
:default ["src" "test"]
:default-desc "src test"}}]
:default-desc "src test"}
:multi {:desc "Custom multi-arg-val test."
:alias :m
:collect multi-arg-val-collect}}]
(is (= (str/trim "
-i, --from <format> edn The input format. <format> can be edn, json or transit.
-o, --to <format> json The output format. <format> can be edn, json or transit.
--paths src test Paths of files to transform.
-p, --pretty Pretty-print output.")
-p, --pretty Pretty-print output.
-m, --multi Custom multi-arg-val test.")
(str/trim (cli/format-opts {:spec spec
:order [:from :to :paths :pretty]}))))
:order [:from :to :paths :pretty :multi]}))))
(is (= {:coerce {:from :keyword,
:to :keyword, :paths []},
:alias {:i :from, :o :to, :p :pretty},
:exec-args {:from :edn, :to :json, :paths ["src" "test"]}}
:alias {:i :from, :o :to, :p :pretty :m :multi},
:exec-args {:from :edn, :to :json, :paths ["src" "test"]}
:collect {:multi multi-arg-val-collect}}
(cli/spec->opts spec nil)))
(is (= (str/trim "
-p, --pretty false Pretty-print output.
Expand All @@ -213,6 +221,11 @@
:coerce []
:default ["src" "test"]
:default-desc "src test"}]]}))))
(is (submap?
{:opts {:from :edn :to :json :paths ["src" "test"]
:multi ["a" "b" "c" "d" "e" "f" "g" "h"]}}
(cli/parse-args ["--multi" "a:b" "--multi" "c:d:e" "--multi" "f" "--multi" "g" "h"]
{:spec spec})))
(is (submap?
{:opts {:from :edn, :to :json, :paths ["src" "test"]}}
(cli/parse-args [] {:spec spec})))
Expand All @@ -222,6 +235,7 @@
#:deps{:root "the-root"}
(cli/parse-opts ["--deps/root" "the-root"]
{:spec [[:deps/root {:desc "The root"}]]})))

(testing "exec-args wins over spec"
(is (= 2 (:foo (cli/parse-opts [] {:spec {:foo {:default 1}}
:exec-args {:foo 2}}))))
Expand Down