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

Compute argument possible values based on other arguments #1910

Closed
fbecart opened this issue May 6, 2020 · 7 comments
Closed

Compute argument possible values based on other arguments #1910

fbecart opened this issue May 6, 2020 · 7 comments
Labels
A-validators Area: ArgMatches validation logi C-enhancement Category: Raise on the bar on expectations S-wont-fix Status: Closed as there is no plan to fix this
Milestone

Comments

@fbecart
Copy link

fbecart commented May 6, 2020

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.

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.

Related issues

@pksunkara pksunkara added this to the 3.1 milestone May 6, 2020
@pksunkara
Copy link
Member

I think this can be achieved by the hooks proposal mentioned in #1471.

@fbecart
Copy link
Author

fbecart commented May 7, 2020

Thanks @pksunkara for looking into it. I see how #1471 is related, as it suggests to have a closure returning the default value of an argument.

This issue remains unique in the following ways:

  • It is about computing the possible values of an argument.
  • It requires access to the arguments that have already been provided.
  • It should influence auto-completion.
  • It is not related to prompting the user -- which is the primary motive for default value hooks.

@pksunkara
Copy link
Member

It is related because we can extend the hook proposal to allow defining possible values too. Prompts is a tangential issue.

Auto completion will probably be tied into the dynamic completion issue.

@fbecart
Copy link
Author

fbecart commented May 8, 2020

To illustrate the issue, here's a link to the project I'm working on: https://github.com/fbecart/zinoma/blob/9d2ea034d566a92a7464a7ca58c0b75cb87d7072/src/main.rs#L32-L37

@kbknapp
Copy link
Member

kbknapp commented May 11, 2020

Also potentially related #1880

@fbecart
Copy link
Author

fbecart commented Aug 5, 2020

Closely related to #1232, if not duplicate.

@epage
Copy link
Member

epage commented Dec 10, 2021

In #2832, I layout an idea for generalizing clap. This has the potential for opening the door to something like this.

With that said, I would generally recommend not doing this. Parsing a file sufficiently to know what future args should be during the parsing of the args feels like there is a can of worms of problems with it. I'm assuming make most other tools do it.

If you really want clap like errors, in 3.0.0, we are offering an App::error. For more native solutions, I feel like #1404 and #568 are more of what we want to provide. I did note this on #568 so we can remember to consider whether we should support this case or not.

In favor of those options I listed, I'm leaning towards closing this. If there are concerns that are not covered, feel free to speak up!

@epage epage closed this as completed Dec 10, 2021
@epage epage added the S-wont-fix Status: Closed as there is no plan to fix this label Jan 11, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-validators Area: ArgMatches validation logi C-enhancement Category: Raise on the bar on expectations S-wont-fix Status: Closed as there is no plan to fix this
Projects
None yet
Development

No branches or pull requests

4 participants