dynamic completions: register as external subcommand
Please complete the following tasks
- [x] I have searched the discussions
- [x] I have searched the open and rejected issues
Clap Version
4.5.51
Describe your use case
I was looking into adding dynamic completions (COMPLETE=shell) support for cargo fuzz. So I'd like to have it complete cargo fuzz <tab>.
By default, clap generates something like this on fish:
complete --keep-order --exclusive --command cargo-fuzz --arguments "(COMPLETE=fish "/path/to/cargo-fuzz" -- (commandline --current-process --tokenize --cut-at-cursor) (commandline --current-token))"
Changing that to --command 'cargo' -n '__fish_seen_subcommand_from fuzz' would make it complete cargo fuzz <tab> as well. I'm not sure if the other supported shells support something like this aswell though.
I also tried to do
#[derive(Parser)]
enum CargoArgs {
Fuzz(CargoFuzzSubcommand),
}
#[derive(clap::Args)]
struct CargoFuzzSubcommand {
#[clap(subcommand)]
subcommand: Command,
}
fn main() -> Result<()> {
CompleteEnv::with_factory(CargoArgs::command)
.bin("cargo")
.complete();
}
which works on fish, but on bash it completely replaces the original completion instead of adding to it.
Describe the solution you'd like
If something like fishs __fish_seen_subcommand_from can be done on other shells, maybe it could be exposed as
CompleteEnv::with_factory(Command::command)
.bin("cargo")
.only_complete_subcommand("fuzz")
.complete();
Alternatives, if applicable
Now that I think about it, it's not cargo-fuzzs responsibility to register completions for cargo.
Perhaps cargos completion script could instead complete unknown subcommands by letting the shell complete cargo-<subcommand> directly. On fish this is very easy with complete --do-complete "cargo-fuzz", again I have no idea how other shells compare here.
Additional Context
No response
We have a note for this in rust-lang/cargo#14520 but I'm not seeing anything in this repo. Probably because the assumption there is we'd make it part of cargos completions, rather than having plugins register for their own completions. If we did that and got alias to work, we'd then automatically get completions of alias for third-party subcommands, rather than nothing working for those.
If we can have the plugins also register for cargo, we could move forward with that in parallel.
Could you tell me why -n '__fish_seen_subcommand_from fuzz' is needed? Oh, is it that we keep going if we see an unknown subcommand, trying to recover on a failure which in this case will instead flood the user with redundant -h and -v completions? I wonder if we should have a built-in version of__fish_seen_subcommand_from that tells the completion parser to be strict about certain subcommands.
Oh, is it that we keep going if we see an unknown subcommand, trying to recover on a failure which in this case will instead flood the user with redundant -h and -v completions?
Yes, if you simply do COMPLETE=fish cargo fuzz | source, you'll have cargo <tab> complete cargo tmin, cargo list etc. which you only want for cargo fuzz tmin. cargo-fuzz doesn't have any options other than -h and -V but I suppose if it did, it would also complete them for cargo build --options-from-cargo-fuzz.
I agree that ideally this would be handled by cargo, I'll look into how it does its completion and if it would be possible to implement for not just fish but the other supported shells as well.