-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Description
I would like to be able to compute the possible values of an argument dynamically, based on the values provided for some other argument(s).
Use case
I'm working on a CLI which has a goal similar to make
.
$ make --help
Usage: make [options] [target] ...
Options:
-f FILE, --file=FILE, --makefile=FILE
Read FILE as a makefile.
The file lists the available targets. Given a value of FILE
, I am able to load a list of available target names. I would like to use that list as the possible values for target
.
This would affect the validation of target
. Ideally, this would also affect its autocompletion.
Currently, possible_values
is expected to be provided as an array slice (&[&str]
) as the App
is being built.
Line 1712 in 9d03c84
pub fn possible_values(mut self, names: &[&'help str]) -> Self { |
At that time, the value of
FILE
is not available yet.
Wanted solution
I would like instead to be able to provide a closure that would compute the possible values for my argument. This closure would take the values of the other app arguments as a parameter.
Workaround
It is already possible to obtain this behavior by parsing the arguments twice (the second time with refined validation):
fn get_app(allowed_target_names: Option<Vec<&str>>) -> App {
let target_arg = Arg::with_name("target");
let target_arg = if let Some(allowed_target_names) = allowed_target_names {
target_arg.possible_values(&allowed_target_names)
} else {
target_arg
};
App::new("make")
.arg(target_arg)
[...]
}
fn main() {
let arg_matches = get_app(None).get_matches();
let config = Config::load(arg_matches.value_of("config_file"));
let all_target_names = config.list_target_names();
let app_args = get_app(Some(all_target_names)).get_matches();
[...]
}
However, this workaround doubles the overhead of parsing arguments. Also, this solution does not cover the autocompletion part.