Use Option for optional arguments
canadaduane opened this issue · comments
This would potentially be a breaking API change, but I'd like to suggest that the Option
type be used for optional arguments.
Currently, Option
seems to be superfluous, as arguments are still optional unless the "required" meta flag is set.
In addition, the following scenario seems to be unachievable with the current implementation:
- an optional argument that optionally accepts a value
- has a default value when not set
As an example, let's say a command-line tool normally has output that is unsorted. If you pass the -s
argument in, then output should become sorted in some default way (e.g. alphabetically). Additionally, if you pass a value to the -s
argument, you can specify the way in which the sort occurs (e.g. "-sa" for alphabetical, "-sn" for numerical).
In my case, the "principal of least surprise" led me to think that the following might achieve that result:
#[derive(Debug, Options)]
struct GramsOptions {
#[options(help = "sort tallied output: a=alphabetic [DEFAULT], n=numeric")]
sort: Option<String>,
}
I expected I might be able to parse this as follows:
let sort: Option<Sort> = match opts.sort.as_ref().map(|s| &s[..]) {
Some("a") => Some(Sort::Alphabetic),
Some("n") => Some(Sort::Numeric),
None => Some(Sort::Alphabetic),
};
In addition, the following scenario seems to be unachievable with the current implementation:
- an optional argument that optionally accepts a value
- has a default value when not set
Not true. There are at least two ways of accomplishing this:
#[derive(Options)]
struct OptionA {
sort: Option<String>
}
let opts = OptionA::parse_args_default_or_exit();
// Your code handling the option provides the default value
let sort = match opts.sort.as_ref().map(|s| &s[..]) {
Some("a") => Sort::Alphabetic,
Some("n") => Sort::Numeric,
Some(_) => // error
None => Sort::Alphabetic,
};
Or:
#[derive(Options)]
struct OptionB {
#[options(default = "a")]
sort: String,
}
let opts = OptionB::parse_args_default_or_exit();
// gumdrop provides the default value
let sort = match &opts.sort[..] {
"a" => Sort::Alphabetic,
"n" => Sort::Numeric,
_ => // error
};
The OptionA
example is quite similar to your provided example. In what way is this not working as expected?