l3nz / cli-matic

Compact, hands-free [sub]command line parsing library for Clojure.
Eclipse Public License 2.0
361 stars 29 forks source link

Interactive mode - why not? #42

Open l3nz opened 5 years ago

l3nz commented 5 years ago

If we have:

OPTIONS:
   -a, --a1 N  0  First addendum [$AA]
   -b, --a2 N  0  Second addendum
   -?, --help

Why shouldn't we have:

$ toycalc add --interactive

First addendum (a1, def 0): 10
Second addendum (a2, def 0): 20

You are about to add 10 and 20 together. Are you sure you want to continue? Y
30
snorremd commented 5 years ago

A related requirement would be the possibility of specifying some, but not all, options as interactive, e.g. password options and the like. This is common in database command line clients where most options are specified on the command line, but the password is prompted for interactively. Thus, it would make sense to separate between masked (.readPassword System/console) and unmasked (read-line) input.

Edit: Thank you for putting together this very useful library. It is really appreciated!

l3nz commented 5 years ago

I was thinking of making some options "completable", that is, if missing, they would be asked for interactively. What do you think?

snorremd commented 5 years ago

That sounds like it would satisfy my requirement quite nicely! So long as it only tries asking for them if a tty is present. Otherwise it would cause weird behavior when running the app in daemon mode.

I just about mucked about implementing support for interactive options in a fork (ps not quite complete or tested): https://github.com/snorremd/cli-matic/commit/4293ea2684e433b880fc38a7060d5037159408d5

Line 163 in the parse-cmds-with-defaults function tripped me up as I can't understand how it would return anything other than the full list of environment options though.

The set-keys-in value is a clojure map with keywords -> option maps. Whereas each map in the env-options vector is a cli-matic option map. So when looking up the keyword in the cli-matic option map, it would return nil a falsy value, and then complement it returning true. E.g.:

(filter (complement #{:foo :bar}) [{:option "foo"} {:option "bar"}])
=> ({:option "foo"} {:option "bar"})

So that might be a bug?

Thanks again.