I am updating the contrib project tools.cli to fix a couple of issues
that were pointed out to me by someone trying to use it, and would
appreciate some feedback on the the solution I have implemented before
i push it.
The main issue was the inability to provide arguments that you do not
want processed as "options". For example:
java -cp my.jar --foo bar myfile.txt
where "foo" is an option to be set to "bar" and "myfile.txt" is a
parameter that is not to be parsed, but is needed in the program
execution. My solution to this problem is to use the BASH standard of
"--" to signify the end of the options to the program:
java -cp my.jar --foo bar -- myfile.txt
This allows for a simple implementation and seems like a reasonable
thing to do, as the standard is already there and people are
(possibly) familiar with it. These arguments then get added to the
resulting command line args map assoc'd to a key of :trailing-args:
{:foo "bar"
:trailing-args ["myfile.txt"]}
The other option I was considering was to instead return a tuple of
[options-map, trailing-args] but this breaks the existing contract and
it didnt seem particularly clearer to me.
Any thoughts / suggestions are much appreciated :D
Cheers!
Gaz
I've used tools.cli recently and also noticed the same issue. I'd be
ok with the "--" solution, but I'd prefer support for getting trailing
arguments without it. Most CLI parsers I've used work that way. In
other news, it would also be nice if it was possible to customize the
failure behavior. I'd prefer cli throw an exception or call an error
handling function rather than just calling System/exit.
Cheers,
Dave
> --
> You received this message because you are subscribed to the Google Groups "Clojure Dev" group.
> To post to this group, send email to cloju...@googlegroups.com.
> To unsubscribe from this group, send email to clojure-dev...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/clojure-dev?hl=en.
>
>
Gaz,
I've used tools.cli recently and also noticed the same issue. I'd be
ok with the "--" solution, but I'd prefer support for getting trailing
arguments without it. Most CLI parsers I've used work that way. In
other news, it would also be nice if it was possible to customize the
failure behavior. I'd prefer cli throw an exception or call an error
handling function rather than just calling System/exit.
Cheers,
Dave
I don't like this at all. I don't feel it's a standard at all. I can't
think of a single program I interact with that needs -- to indicate
the start of the "trailing" args.
IMO, the first argument that doesn't begin with "-" (or "--" of
course) should start the trailing args.
--
Sean A Corfield -- (904) 302-SEAN
An Architect's View -- http://corfield.org/
World Singles, LLC. -- http://worldsingles.com/
Railo Technologies, Inc. -- http://www.getrailo.com/
"Perfection is the enemy of the good."
-- Gustave Flaubert, French realist novelist (1821-1880)
That can work, but that implies that the arity of options is known and
fixed. the example above can only be parsed unambiguously if we know
that --foo always takes exactly one argument ("bar") in this case. I
don't know tools.cli well enough to know if that's the case. (If it
isn't, perhaps it should be.)
The "--" is a common convention, but it's usually only used when one
of the trailing arguments might otherwise be confused with an option:
i.e. a file name that begins with a hyphen. In practice that's quite
rare.
// Ben
The only reason I've used -- to indicate end of arguments was to
specifically pass arguments that start with - to the underlying tool.
It doesn't feel natural to require it for the above example.
--
Cosmin Stejerean
http://offbytwo.com
At around the same time Gareth was starting on clargon (now
tools.cli), I built a mostly-working option parser named clojopts. I
tried to add too many features and configurable bits, so it's not
really ready for prime-time, but I think it's relevant here because
rather than rolling my own parsing I used the java port of GNU getopt,
which parses arguments in exactly the way everyone is used to. Gareth,
have you considered the possibility of using that? Basically I took a
map from the user, which I used to build a getopt string and then do
further clojure-oriented processing on the results from getopt.
Interestingly enough, the "--" is also used by GNU getopt java port to
signify end of arguments:
http://www.urbanophile.com/~arenn/hacking/getopt/gnu.getopt.Getopt.html#_top_
(not that I'm suggesting that is a reason to use "--").
I'll have a think, and try implementing some of the suggestions.
cheers,
gaz
> --
> You received this message because you are subscribed to the Google Groups
> "Clojure Dev" group.
> To view this discussion on the web visit
> https://groups.google.com/d/msg/clojure-dev/-/akSLwM1S30IJ.
https://github.com/clojure/tools.cli/tree/next
in summary:
* no more magic functions, plain vector to create a spec
* exceptions while parsing bubble up and need to be handled by the app
* grouping or 'nested' arguments removed to simplify and make less wacky
* bugs around boolean/flag handling no longer exist
* trailing args are collected and found under a :args key in the resulting map
feedback welcome...
--
And what is good, Phaedrus,
And what is not good—
Need we ask anyone to tell us these things?
$ myprog -n1 bar.clj -x # cmd 1
$ myprog -n1 -- bar.clj -x # cmd 2
with a definition like:
(cli ["-n1" "bar.clj" "-x"]
["-n1" :flag true]
["-x" :flag true])
(1) results in {:n1 true :x true :args ["bar.clj"]} (matches GNU getopt)
(2) results in exception telling you "--" is not a valid argument.
adding support to make it match GNU getopt for "--" is trivial, and it
seems to make sense to do so.
On Mon, Oct 24, 2011 at 12:53 PM, Alan Malloy <al...@malloys.org> wrote:
> bar.clj
i kind of feel like all i would do in the hook would be to print the
banner to stdout and then system/exit...
suggestions for alternative solutions for the --help scenario are
completely acceptable. hook function with banner passed as arg?
i kind of feel like all i would do in the hook would be to print the
banner to stdout and then system/exit...
(defn -main [& args]
(let [[options extra banner] (cli args
["-h" "--help" "HALP!" :default
false :flag true]
["-f" "--faux" "The faux du fafa"]
["-c" "--conchords" "How many
conchords?" :default 2 :parse-fn #(Integer. %)])]
(when (:help options)
(println banner)
(System/exit 0))
(println "options:" options)
(println "extra:" extra)))
i think this addresses all the concerns / original issues (no magic
functions, no System/exits, consistent access to trailing / extra
arguments, booleans) and im pretty happy with the interface so i will
likely merge this into master...