tools.cli

potential incorrect parsing

Details

  • Type: Defect Defect
  • Status: Resolved Resolved
  • Priority: Major Major
  • Resolution: Completed
  • Affects Version/s: None
  • Fix Version/s: None
  • Component/s: None
  • Labels:
    None

Description

If i have these options defined

(def cli-options [ ["-i" "--interactive" "interactive cli mode"]
["-H" "--help" "show help"]
["h" "-host host" "hostname"
["-u" "--user user" "username to login to rulegate"]])

if I enter a command as follows

myprog -h myhost -u foo

my option output looks like { :host myhost :user foo }

however if I leave the host value off
{:host -u}

It appears to be treating the -u as the value for -h. I would expect a missing argument error. Is this the correct behavior?

Activity

Hide
John Walker added a comment -

I am not able to reproduce this behavior. Would you create a gist or use code tags?

Show
John Walker added a comment - I am not able to reproduce this behavior. Would you create a gist or use code tags?
Hide
Sean Corfield added a comment -

Repro case:

(require '[clojure.tools.cli :as cli])
nil
user> (def opts [["-h" "--host host" "hostname"] ["-u" "--user user" "username"]])
#'user/opts
user> (cli/parse-opts ["-h" "localhost" "-u" "fred"] opts)
{:options {:host "localhost", :user "fred"}, :arguments [], :summary "  -h, --host host  hostname\n  -u, --user user  username", :errors nil}
user> (cli/parse-opts ["-h" "-u" "fred"] opts)
{:options {:host "-u"}, :arguments ["fred"], :summary "  -h, --host host  hostname\n  -u, --user user  username", :errors nil}

This is expected behavior insofar as you've specified the argument to -h is required, by providing a placeholder name for its argument. Since -u follows -h, it is treated as that required argument.

You could argue that it should realize that -u is also an argument and deduce that the actual required argument to -h is missing... but that would mean you could never pass a value to an option that happened to coincide with another option (so, for example -h -u -u fred would be illegal... although perhaps that should be illegal?).

I'll see if there's an easy way to check for this condition (I suspect not) and add an option to enable / disable that checking if it is easy.

Show
Sean Corfield added a comment - Repro case:
(require '[clojure.tools.cli :as cli])
nil
user> (def opts [["-h" "--host host" "hostname"] ["-u" "--user user" "username"]])
#'user/opts
user> (cli/parse-opts ["-h" "localhost" "-u" "fred"] opts)
{:options {:host "localhost", :user "fred"}, :arguments [], :summary "  -h, --host host  hostname\n  -u, --user user  username", :errors nil}
user> (cli/parse-opts ["-h" "-u" "fred"] opts)
{:options {:host "-u"}, :arguments ["fred"], :summary "  -h, --host host  hostname\n  -u, --user user  username", :errors nil}
This is expected behavior insofar as you've specified the argument to -h is required, by providing a placeholder name for its argument. Since -u follows -h, it is treated as that required argument. You could argue that it should realize that -u is also an argument and deduce that the actual required argument to -h is missing... but that would mean you could never pass a value to an option that happened to coincide with another option (so, for example -h -u -u fred would be illegal... although perhaps that should be illegal?). I'll see if there's an easy way to check for this condition (I suspect not) and add an option to enable / disable that checking if it is easy.
Hide
Sean Corfield added a comment -

Will be in 0.3.3.

New option :strict - if true, will treat required option arguments that match other options as "missing" (but will not attempt to re-parse the options). The default is nil, which maintains the previous behavior.

Show
Sean Corfield added a comment - Will be in 0.3.3. New option :strict - if true, will treat required option arguments that match other options as "missing" (but will not attempt to re-parse the options). The default is nil, which maintains the previous behavior.

People

Vote (0)
Watch (0)

Dates

  • Created:
    Updated:
    Resolved: