Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix exec args priority #74

Merged
merged 2 commits into from
Nov 14, 2023
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
58 changes: 47 additions & 11 deletions API.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,18 @@
- [`coerce`](#coerce) - Coerce string <code>s</code> using <code>f</code>
- [`dispatch`](#dispatch) - Subcommand dispatcher.
- [`format-opts`](#format-opts)
- [`format-table`](#format-table)
- [`merge-opts`](#merge-opts) - Merges babashka CLI options.
- [`number-char?`](#number-char?)
- [`opts->table`](#opts->table)
- [`pad`](#pad)
- [`pad-cells`](#pad-cells)
- [`parse-args`](#parse-args) - Same as <code>parse-opts</code> but separates parsed opts into <code>:opts</code> and adds
- [`parse-cmds`](#parse-cmds) - Parses sub-commands (arguments not starting with an option prefix) and returns a
- [`parse-keyword`](#parse-keyword) - Parse keyword from <code>s</code>
- [`parse-opts`](#parse-opts) - Parse the command line arguments <code>args</code>, a seq of strings.
- [`spec->opts`](#spec-opts) - Converts spec into opts format.
- [`rows`](#rows)
- [`spec->opts`](#spec->opts) - Converts spec into opts format
- [`babashka.cli.exec`](#babashkacliexec)
- [`-main`](#-main) - Main entrypoint for command line usage.
- [`main`](#main)
Expand Down Expand Up @@ -79,14 +84,21 @@ Subcommand dispatcher.
Each entry in the table may have additional [`parse-args`](#parse-args) options.

Examples: see [README.md](README.md#subcommands).
<br><sub>[source](https://github.com/babashka/cli/blob/main/src/babashka/cli.cljc#L544-L588)</sub>
<br><sub>[source](https://github.com/babashka/cli/blob/main/src/babashka/cli.cljc#L567-L611)</sub>
## `format-opts`
``` clojure

(format-opts {:keys [spec indent order header], :or {indent 2}})
(format-opts {:as cfg, :keys [indent], :or {indent 2}})
```

<sub>[source](https://github.com/babashka/cli/blob/main/src/babashka/cli.cljc#L504-L569)</sub>
<sub>[source](https://github.com/babashka/cli/blob/main/src/babashka/cli.cljc#L556-L560)</sub>
## `format-table`
``` clojure

(format-table {:keys [rows indent]})
```

<sub>[source](https://github.com/babashka/cli/blob/main/src/babashka/cli.cljc#L516-L527)</sub>
## `merge-opts`
``` clojure

Expand All @@ -103,6 +115,27 @@ Merges babashka CLI options.
```

<sub>[source](https://github.com/babashka/cli/blob/main/src/babashka/cli.cljc#L53-L55)</sub>
## `opts->table`
``` clojure

(opts->table {:keys [spec order]})
```

<sub>[source](https://github.com/babashka/cli/blob/main/src/babashka/cli.cljc#L537-L554)</sub>
## `pad`
``` clojure

(pad len s)
```

<sub>[source](https://github.com/babashka/cli/blob/main/src/babashka/cli.cljc#L506-L506)</sub>
## `pad-cells`
``` clojure

(pad-cells rows)
```

<sub>[source](https://github.com/babashka/cli/blob/main/src/babashka/cli.cljc#L508-L514)</sub>
## `parse-args`
``` clojure

Expand All @@ -113,7 +146,7 @@ Merges babashka CLI options.

Same as [`parse-opts`](#parse-opts) but separates parsed opts into `:opts` and adds
`:cmds` and `:rest-args` on the top level instead of metadata.
<br><sub>[source](https://github.com/babashka/cli/blob/main/src/babashka/cli.cljc#L459-L466)</sub>
<br><sub>[source](https://github.com/babashka/cli/blob/main/src/babashka/cli.cljc#L484-L491)</sub>
## `parse-cmds`
``` clojure

Expand All @@ -125,7 +158,7 @@ Same as [`parse-opts`](#parse-opts) but separates parsed opts into `:opts` and a
Parses sub-commands (arguments not starting with an option prefix) and returns a map with:
* `:cmds` - The parsed subcommands
* `:args` - The remaining (unparsed) arguments
<br><sub>[source](https://github.com/babashka/cli/blob/main/src/babashka/cli.cljc#L203-L213)</sub>
<br><sub>[source](https://github.com/babashka/cli/blob/main/src/babashka/cli.cljc#L205-L215)</sub>
## `parse-keyword`
``` clojure

Expand Down Expand Up @@ -173,16 +206,19 @@ Parse the command line arguments `args`, a seq of strings.
;; => throws 'Unknown option --qux' exception b/c there is no :qux key in the spec
```

<br><sub>[source](https://github.com/babashka/cli/blob/main/src/babashka/cli.cljc#L250-L457)</sub>
<br><sub>[source](https://github.com/babashka/cli/blob/main/src/babashka/cli.cljc#L257-L482)</sub>
## `rows`
<sub>[source](https://github.com/babashka/cli/blob/main/src/babashka/cli.cljc#L530-L532)</sub>
## `spec->opts`
``` clojure

(spec->opts spec)
(spec->opts spec {:keys [exec-args]})
```


Converts spec into opts format.
<br><sub>[source](https://github.com/babashka/cli/blob/main/src/babashka/cli.cljc#L184-L201)</sub>
Converts spec into opts format. Pass existing opts as optional second argument.
<br><sub>[source](https://github.com/babashka/cli/blob/main/src/babashka/cli.cljc#L184-L203)</sub>
# babashka.cli.exec


Expand All @@ -207,11 +243,11 @@ Main entrypoint for command line usage.
clojure -M:exec clojure.core prn :a 1 :b 2
;;=> {:a "1" :b "2"}
```
<br><sub>[source](https://github.com/babashka/cli/blob/main/src/babashka/cli/exec.clj#L67-L81)</sub>
<br><sub>[source](https://github.com/babashka/cli/blob/main/src/babashka/cli/exec.clj#L88-L101)</sub>
## `main`
``` clojure

(main & args)
```

<sub>[source](https://github.com/babashka/cli/blob/main/src/babashka/cli/exec.clj#L63-L65)</sub>
<sub>[source](https://github.com/babashka/cli/blob/main/src/babashka/cli/exec.clj#L83-L86)</sub>
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 (2023-11-14)

- Prioritize `:exec-args` over spec `:default`s

## v0.7.53 (2023-09-28)

- [#72](https://github.com/babashka/cli/issues/72): add possibility to add a header to format-opts ([@Sohalt](https://github.com/Sohalt))
Expand Down
38 changes: 20 additions & 18 deletions src/babashka/cli.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -182,23 +182,25 @@
(assoc acc current-opt arg))))

(defn spec->opts
"Converts spec into opts format."
[spec]
(reduce
(fn [acc [k {:keys [coerce alias default require validate]}]]
(cond-> acc
coerce (update :coerce assoc k coerce)
alias (update :alias
(fn [aliases]
(when (contains? aliases alias)
(throw (ex-info (str "Conflicting alias " alias " between " (get aliases alias) " and " k)
{:alias alias})))
(assoc aliases alias k)))
require (update :require (fnil #(conj % k) #{}))
validate (update :validate assoc k validate)
default (update :exec-args assoc k default)))
{}
spec))
"Converts spec into opts format. Pass existing opts as optional second argument."
([spec] (spec->opts spec nil))
([spec {:keys [exec-args]}]
(reduce
(fn [acc [k {:keys [coerce alias default require validate]}]]
(cond-> acc
coerce (update :coerce assoc k coerce)
alias (update :alias
(fn [aliases]
(when (contains? aliases alias)
(throw (ex-info (str "Conflicting alias " alias " between " (get aliases alias) " and " k)
{:alias alias})))
(assoc aliases alias k)))
require (update :require (fnil #(conj % k) #{}))
validate (update :validate assoc k validate)
default (update :exec-args (fn [new-exec-args]
(assoc new-exec-args k (get exec-args k default))))))
{}
spec)))

(defn parse-cmds
"Parses sub-commands (arguments not starting with an option prefix) and returns a map with:
Expand Down Expand Up @@ -289,7 +291,7 @@
opts (if spec
(merge-opts
opts
(spec->opts spec))
(spec->opts spec opts))
opts)
coerce-opts (:coerce opts)
aliases (or
Expand Down
9 changes: 7 additions & 2 deletions test/babashka/cli_test.cljc
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@
:to :keyword, :paths []},
:alias {:i :from, :o :to, :p :pretty},
:exec-args {:from :edn, :to :json, :paths ["src" "test"]}}
(cli/spec->opts spec)))
(cli/spec->opts spec nil)))
(is (= (str/trim "
-p, --pretty Pretty-print output.
--paths src test Paths of files to transform.
Expand All @@ -214,7 +214,12 @@
(is (submap?
#:deps{:root "the-root"}
(cli/parse-opts ["--deps/root" "the-root"]
{:spec [[:deps/root {:desc "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}}))))
(is (nil? (:foo (cli/parse-opts [] {:spec {:foo {:default 1}}
:exec-args {:foo nil}})))))))

(deftest args-test
(is (submap? {:foo true} (cli/parse-opts ["--foo" "--"])))
Expand Down
Loading