Skip to content

(clap_complete): Aditional context for Arguments with multiple args ["unstable-dynamic"] #6284

@feraxhp

Description

@feraxhp

Please complete the following tasks

Clap Version

clap complete = "4.5.66"

Describe your use case

Lets say you have an argument that supports multiple arguments but, no all of the arguments are the same.

Example

-u or --set-upstream

it will get 2 arguments the remote and the branch

lets say you type myApp -u _ at this point the completer needs the remote name, so you will provide the remote names for the completion, but in the next argument myApp -u main _ now the desired completion would be the branches.

Why not use -u as a flag and remote and branch as a separed arguments?

imagine you have this command:

grp pull [config] [remote] [branch]

and you want to add the -u flag, for that to work properly you would need to make mandatory [remote] and [branch]. but there is a problem, currently clap does not support override a positional optional value. so here is a problem:

  • this is what you want:
    grp pull [config] -u <remote> <branch>
  • this is what clap resolves to:
    grp pull -u <config> <remote> <branch>
    it make sense, but if the user wants to use the default configuration... this forces the user to write down the config even if the app already knows what the default configuration is.

to solve or work around it, you will create a -u argument that receives and conflicts with [remote] and [branch]. that way you will have both cases how you want.

grp pull [config] [remote] [branch]
grp pull [config] -u <remote> <branch>

So you in the completion part (unstable-dynamic) of it, you will have a problem, which is that you can only add one completion for argument even if it receives x number of parameters. And currently there is no way to know which of the x sub-arg is triggering the completion.

Describe the solution you'd like

add a positional index in the method complete of the trait ValueCompleter.

like:

pub trait ValueCompleter: Send + Sync {
    fn complete(&self, current: &OsStr, position: u8 /*or any unsigned int*/) -> Vec<CompletionCandidate>;
}

this way in the custom completer you will get the current prefix, and the position of the value:

fn canditates(current: &OsStr, position: u8) -> Vec<CompletionCandidate> {
    match position {
        0 => Remote::canditates(current),
        1 => Branch::canditates(current),
        _ => unrechable!(),
    }
}

[!Information]
i mannage to solve this by goin into the env::args() and re parse it. but this is not ideal.

Alternatives, if applicable

Another way to implement it is in the argument factory like:

Arg::new("set-upstream").short('u').long("set-upstream")
       .num_args(2)
       .value_names(["remote", "branch"])
       .adds([Remote::complete(), Branch::complete()]) // new method

Additional Context

If you want to know how i mannage to solve it, see: grp upstream complete

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-completionArea: completion generatorC-enhancementCategory: Raise on the bar on expectationsE-easyCall for participation: Experience needed to fix: Easy / not much

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions