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

clap_complete: Allow access to previous args in completion function #5784

Open
2 tasks done
LucasPickering opened this issue Oct 21, 2024 · 5 comments
Open
2 tasks done
Labels
A-completion Area: completion generator C-enhancement Category: Raise on the bar on expectations S-waiting-on-design Status: Waiting on user-facing design to be resolved before implementing

Comments

@LucasPickering
Copy link

Please complete the following tasks

Clap Version

clap 4.4.2, clap_complete 4.5.29

Describe your use case

In a ArgValueCompleter function, it would be nice to have access to what has been parsed so far when generating completions. My use case is that I'm loading the arguments from a YAML file, but the file to load from can be overridden by a prior -f argument. Another identical example is docker-compose run: You can run docker-compose run <service> in which case it will load services from docker-compose.yml, or you can do docker-compose -f different/compose/file.yml run <service>, in which case it should load from different/compose/file.yml.

Describe the solution you'd like

Access to what has already been parsed as an argument to the ArgValueCompleter function. This would most likely be a breaking change because it requires adding an argument to ValueCompleter::complete. The user impact could be mitigated though by keeping the blanket impl on fn(&OsStr) -> Vec<CompletionCandidate>. I imagine most users are not implementing ValueCompleter themselves.

The best I can think of is the additional argument is just a &[&OsStr] containing what's already been parsed. The completer would then be responsible for iterating over that and figuring out the semantic meaning. It'd be great if we could get the prior arguments in a more structured form, but doing that without the full command present is probably not possible. So an example completion function for something like docker-compose run would look like:

fn complete_service(current: &OsStr, previous: &[&OsStr]) -> Vec<CompletionCandidate> {
    let file_arg_index = previous.iter().position(|arg| arg == "-f" || arg == "--file");
    let path = if let Some(file_index) = file_arg_index {
        previous[file_arg_index + 1]
    } else {
        "docker-compose.yml"
    };
    let Ok(config) = load_config(path) else {return vec![]};
    config
        .services
        .into_iter()
        .map(|service| CompletionCandidate::new(service.name))
        .collect()
}

(this is pseudocode, I'm sure it doesn't actually compile but it should get the idea across)

Alternatives, if applicable

  • Manually parse std::env::args and look for -f or --file. This requires you to manually skip over the first few items to get to where the arguments start, which is fragile
  • Use my app's Command struct to parse std::env::args, but this requires everything already present to constitute a valid command, i.e. it can't be used to complete a required argument (unless at least one character has already been typed)

Additional Context

@LucasPickering LucasPickering added the C-enhancement Category: Raise on the bar on expectations label Oct 21, 2024
@epage epage added the A-completion Area: completion generator label Oct 21, 2024
@epage
Copy link
Member

epage commented Oct 21, 2024

Huh, I thought we had an issue for this but can't find one. Passing in an OsStr slice wouldn't be ideal as people would have to hack-in their own parsing. We'd likely want ‘ArgMatchesor something like it. The challenge withArgMatches` is we've not exposed the API for making one. More generally, #5515 is a good intermediate step.

@epage epage added the S-waiting-on-design Status: Waiting on user-facing design to be resolved before implementing label Oct 21, 2024
@LucasPickering
Copy link
Author

Yes ArgMatches seems perfect. Is there a need to expose the construction of it? I would think the completion engine could construct the ArgMatches then pass it into the user's completer functions.

@epage
Copy link
Member

epage commented Oct 22, 2024

ArgMatches lives in clap and so the constructor would need to be exposed so clap_complete could make one and pass it to the users completer.

@LucasPickering
Copy link
Author

Ah of course. What can I do to help with this? I don't have a ton of time to dedicate to it but I'd like to help if possible.

@epage
Copy link
Member

epage commented Oct 23, 2024

This is one of the lower priority tasks as we are focusing on

  • feature parity with existing completion generator
  • feature parity with cargo's hand written completions as that is our primary test case for the design

As such, I'm not going to be setting aside the time to help drive the design of this forward for this to be resolved atm.

Previously, I said that #5784 might be initial step but I just realized that there is some extra complexity to that that I had overlooked.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-completion Area: completion generator C-enhancement Category: Raise on the bar on expectations S-waiting-on-design Status: Waiting on user-facing design to be resolved before implementing
Projects
None yet
Development

No branches or pull requests

2 participants