diff --git a/CHANGELOG.md b/CHANGELOG.md index 0956ec4..211a3d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,13 @@ For breaking changes, check [here](#breaking-changes). [Babashka CLI](https://github.com/babashka/cli): turn Clojure functions into CLIs! -## v0.8.65 +## v0.8.66 (2025-07-12) + +- [#122](https://github.com/babashka/cli/issues/122): introduce new + `:repeated-opts` option to enforce repeating the option for accepting multiple + values (e.g. `--foo 1 --foo 2` rather than `--foo 1 2`) + +## v0.8.65 (2025-04-14) - [#119](https://github.com/babashka/cli/issues/119): `format-table` now formats multiline cells appropriately ([@lread](https://github.com/lread)) diff --git a/src/babashka/cli.cljc b/src/babashka/cli.cljc index 4077abf..04288f0 100644 --- a/src/babashka/cli.cljc +++ b/src/babashka/cli.cljc @@ -281,6 +281,7 @@ * `:validate` - a map of validator functions. See [validate](https://github.com/babashka/cli#validate). * `: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). + * `:repeated-opts` - `true`. Forces writing the option name for every value, e.g. `--foo a --foo b`, rather than `--foo a b` * `: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). @@ -414,12 +415,12 @@ (let [k (if negative? (keyword (str/replace (str k) ":no-" "")) k) - next-args (cons (not negative?) #_"true" next-args)] + next-args (cons (not negative?) next-args)] (recur (process-previous acc current-opt added collect-fn) k added mode next-args a->o))) (recur (process-previous acc current-opt added collect-fn) - k added mode next-args + k nil mode next-args a->o))))))) (let [the-end? (or (and (= :boolean coerce-opt) @@ -428,6 +429,7 @@ (and (= added current-opt) (or (not collect-fn) + (:repeated-opts opts) (contains? (::dispatch-tree-ignored-args opts) (first args)))))] (if the-end? (let [{new-args :args diff --git a/test/babashka/cli_test.cljc b/test/babashka/cli_test.cljc index aeedabc..e8932d2 100644 --- a/test/babashka/cli_test.cljc +++ b/test/babashka/cli_test.cljc @@ -647,5 +647,10 @@ {:dispatch ["dns" "get"], :opts {:config ["config-dev.edn" "other.edn"]}, :args nil} - (cli/dispatch table ["--config" "config-dev.edn" "--config=other.edn" "dns" "get"])))) - ) + (cli/dispatch table ["--config" "config-dev.edn" "--config=other.edn" "dns" "get"]))))) + +(deftest repeated-opts-test + (is (= {:opts {:foo [1 2]}} + (cli/parse-args ["--foo" "1" "--foo" "2"] {:repeated-opts true :spec {:foo {:coerce []}}}))) + (is (= {:args ["2"], :opts {:foo [1]}} + (cli/parse-args ["--foo" "1" "2"] {:repeated-opts true :spec {:foo {:coerce []}}}))))