I have a program that accepts a number of options at the CLI that I allow to be specified in a config file as well. That way, instead of passing --quiet
to all calls, one can put into .splint.edn
the map {quiet true}
to have it enabled automatically. It is valuable sometimes to override the config file by passing the option at the CLI so when building the options map, I first load the config file and then merge in the CLI options: (merge local-config cli-options)
However, if I specify a default in the tools.cli spec, I lose that behavior because the defaulted option will unconditionally overwrite the config file when merged as it is always present in the CLI options map.
I've taken to leaving out the :default
key from my tools.cli specs, opting to just write "Defaults to true."
in the option description string. For example, [nil "--[no-]parallel" "Run splint in parallel. Defaults to true."]
and then later (get config :parallel true)
and then later (merge local-config cli-options)
. This means my summary doesn't have the pretty-printed FALSE
in the option. (For example, --[no]-parallel FALSE Run splint in parallel.
)
I've a few ideas about how to solve this little snag for me (beyond "You've already solved it, do nothing!"):
1) return an additional key from cli/parse-opts
, something like :defaults
. It would be a seq or set of the options that used the defaults. That way, I can add some logic like (merge (select-keys cli-options defaults) local-config (apply dissoc cli-options defaults))
.
2) Add a :default-display
to the cli/parse-opts
specs, which will print the default without adding it to the options map. It would be on the user (dev) to ensure it's actually added to the options map or used in some way.
3) Add some functionality that allows for specifying a default in the summary but puts something else in the map. For example, --[no]-parallel FALSE
but the map gets {:parallel :false}
. This would let me choose the right value as appropriate.
Thanks so much!