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

optional takes_value #367

Closed
lipanski opened this issue Dec 20, 2015 · 5 comments
Closed

optional takes_value #367

lipanski opened this issue Dec 20, 2015 · 5 comments
Labels
A-parsing Area: Parser's logic and needs it changed somehow. E-medium Call for participation: Experience needed to fix: Medium / intermediate
Milestone

Comments

@lipanski
Copy link

hello!

is there a way to make takes_value optional? if you think it's fairly easy and you'd like to include this as a feature, I could look into that myself.

in my little script I imagined the following syntax:

# enforce a value for key
command --key something

# user is prompted to select a value for key (via its index) from a longer list of possible values
command --key

# assume a default value for key
command

I know about the empty_vals flag but I was just wondering if there would be a way to not pass the empty string every time.

thanks! 🍰

@kbknapp
Copy link
Member

kbknapp commented Dec 22, 2015

@lipanski Thanks for suggesting this! I think this isn't a bad idea with a few changes to your proposal.

  1. I'd be ok implementing allowing options to use 0 or more values (via Arg::min_values), although one it would have to be caveated that it could lead to poor CLI design if you're not careful. i.e. if you have an option which allows 0 values, and you have positional values the following could lead to confusing errors for the user
$ program --option pos
  is pos a value for --option, or a positional value?
$ program --option -- pos
  now pos is clearly a positional argument, but users may not think to use --
  1. If the user simply provides the option without a value --key I don't believe it should be a function of clap to ask for a value, that should be more on the consumer of library. Because those requirements could be incredibly different from program to program. And this should be trivial to do, i.e. check if a value was provided or not
if matches.value_of("key").is_none() { 
    // ask for a value or assume default
}
  1. Leaving the option off entirely and defaulting to some sane value can already be accomplished
let key = matches.value_of("key").unwrap_or("default_key");

So I'll place it on the map to add 0 or more values, because this does seem to be something people ask about from time to time. Thanks again for taking the time to file this! 👍

@kbknapp kbknapp added T: new feature A-parsing Area: Parser's logic and needs it changed somehow. E-medium Call for participation: Experience needed to fix: Medium / intermediate labels Dec 22, 2015
@kbknapp kbknapp added this to the 1.6.0 milestone Dec 22, 2015
@lipanski
Copy link
Author

if you have an option which allows 0 values, and you have positional values the following could lead to confusing errors for the user

didn't really think about that :\ would positional arguments take precedence over key arguments in that case?

If the user simply provides the option without a value --key I don't believe it should be a function of clap to ask for a value, that should be more on the consumer of library.

I totally agree - that was just an example / my own use case.

Leaving the option off entirely and defaulting to some sane value can already be accomplished

Under which conditions would this evaluate to None / the default? Given:

Arg::with_name("hello").long("hello").takes_value(true)

# The argument '--hello <hello>' requires a value but none was supplied
cargo run -- command --hello

# Works, but matches.value_of("hello") produces Some("")
cargo run -- command --hello ""

And given:

Arg::with_name("hello").long("hello").takes_value(false)

# Found argument 'something', but command wasn't expecting any
cargo run -- command --hello "something"

thanks for your quick reply and for considering this!

@kbknapp
Copy link
Member

kbknapp commented Dec 24, 2015

Ah ok, you're talking about with required arguments having default values. That in particular isn't possible yet, and I have mixed feelings on if it'd be a good idea or not.

I would say it'd probably be better idea to to not make the argument required if you want it to have a default value. Because if the user leaves it off, it uses the default value, but if the user uses it, it still has a value. So there's not really a circumstance where it doesn't have a value (making the requirement piece less needed).

didn't really think about that :\ would positional arguments take precedence over key arguments in that case?

The way clap works now, if you specify something takes a value, it looks for the next argument unless that next argument starts with a - character. So clap has no way of knowing whether the argument provided after an option is either a positional argument, or the value for an option.

What would happen in that case is the positional argument would end up being stored as a value to that option. This can be mitigated by designing the CLI so that there either are no positional arguments, or all options take at least one value (even if it's empty). This is why I'm ok with implementing this feature, because the default will still be 1 or more values, but if the consumer of the library knows that they either have no positional values, or isn't concerned about the possible confusion, they can opt out by specifying a min_values of 0.

@kbknapp kbknapp modified the milestones: v2.0, 1.6.0 Jan 23, 2016
@kbknapp
Copy link
Member

kbknapp commented Jan 26, 2016

Closed with #386

@kbknapp kbknapp closed this as completed Jan 26, 2016
@lipanski
Copy link
Author

💃 thx

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-parsing Area: Parser's logic and needs it changed somehow. E-medium Call for participation: Experience needed to fix: Medium / intermediate
Projects
None yet
Development

No branches or pull requests

2 participants