You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This is a proposal to add better shell completion support to Cargo. The outline of the strategy is:
Add a cargo completions subcommand to assist with completion support.
cargo completions <shell> will output a completion script for the given shell (bash, zsh, etc.).
The completion script will execute cargo completions to implement the work of actually emitting completions. This can significantly simplify the work of supporting completions for different shells. The completion script is very small (see npm completion for an example). This also means all the logic can be written in one language (Rust) and can be more easily tested.
Benefits:
Support richer completions (such as --bin or --example completing the target name).
Maintain consistent completions across shells.
Easier to test.
(Maybe) easier to keep in sync with clap.
More easily discoverable (who knows the completions even exist?).
Completions automatically stay in sync with the release via rustup.
Drawbacks:
More stuff to maintain.
Minor performance drawback compared to native-shell code. Many of the existing completions already execute commands, so in many cases it is a wash. Cargo's launch speed isn't terrible (~50ms for me).
Won't be backwards compatible with older versions of Cargo.
Please let me know if you have any thoughts or objections.
Reacted by Dale Wijnand, Katharina Fey, Jacob Greenfield, Jukka Palomäki, Scott Steele, Daniele D'Orazio, Isaac de Andrade, Pat Walsh, Oliver Schneider, Christian Nicolai and 32 more
Reacted by Mateusz Mikuła, Mikael Mello, maxwell8888, Felipe S. S. Schneider, Hanoch Arega, Ricardo Fernández Serrata and Alex
cargo completions <shell> will output a completion script for the given shell (bash, zsh, etc.)
I don't know how this works at all, but why do some tool's shell completions just work (e.g., Git) whereas the Rust tools seem to need some kind of opt-in step? Of course, I think it would be nice if we didn't need this opt-in step.
It depends on how rust/cargo is installed. Some installers (like ubuntu) will automatically add the completion file to the global location (such as /usr/share/bash-completion/completions/) and it will "just work" assuming your shell is configured to load them. rustup does not do that, since it avoids touching files outside of the user's home directory. rustup could install them in the user's home directory ($XDG_DATA_HOME/bash-completion/completions, and probably something similar for other shells). That would need to be a decision for rustup to make, if it is acceptable to dump files in various locations.
@scooter-dangle In a sense, it will be a clap addon, because it will probably be looking at the (hidden) clap internals to infer the options. My impression is that clap development has stalled and v3 has a long ways to go, so I don't think it is something we can use in the foreseeable future, and there's no indication how new features like this would make progress. There is an issue for this (clap-rs/clap#810), but there's no sense from the issue if it will support custom extensions or how it will work.
Reacted by ૮༼⚆︿⚆༽つ, Sergey A., Max “Goldstein” Siling, Qinxuan Chen, tranzystorekk, superwf, Victor Fedorenko, Weihang Lo, Bryan Hoang, Siphalor and 2 more
As a workaround, for now I just added a symlink to the installed completions for my current toolchain, in my local completions. On Linux, stable toolchain:
I would like to add an enhancement to the original feature request.
Interactive fuzzy completions
I got this idea after writing custom fzf wrappers over cmake like this one:
find all cmakelists in a project, grep all invocations of add_library and add_executable, pipe that to fzf, pipe the target selected by the user to cmake build.
Once I wrote this bash function, i could drop into any new cmake project, run my pt-build and have an interactive selector for the tests, libraries or executables that I might want to build.
since cargo already provides a uniform way to build any rust projects, I think it would be great to enable developers to interactively select the build target.
user story
cargo build --example <TAB><TAB># a fuzzy finder window appears with all buildable examples as defined in Cargo.toml or examples/
cargo build --bin i_already_know_the_name --features <TAB><TAB># a fuzzy finder window appears with all available features to complete
cargo bench <TAB><TAB># a fuzzy finder window with all benchmarks appears
Required building blocks
2 components are required - quickly producing a list of relevant targets (filtered by type) and exposing a fuzzy interface to the user.
Query cargo for all targets to complete with
Bazel and buck build systems have query subcommands that can produce lists of targets filtered by labels like build, test, bench. Cargo should be able to analyze the workspace and list:
binary targets to pass to --bin
example targets to pass to --example
bench targets to pass to --bench
Add a fuzzy completion interface
The fzf-like rust crate is called skim and it provides us with the primitives to expose a fuzzy finder to the user.
Once this exists, the bash completion functions can call the corresponding cargo fuzzy-picker depending on the tokens already typed on the command line.
Prior Art/Other build systems
As i was writing this, I found this open feature request on the bazel repo. Great minds think alike! bazelbuild/bazel#11644
Under-explored
Since cargo enables people to write their own plugins, like cargo fuzz, the target types defined by those need to be made available to original cargo, so they can be listed as completion options. I am not sure how that would work.
ps: as a gopher, I have used https://github.com/spf13/cobra to build command line tools for a long time, which provides a basic support for generating completion script for bash, zsh, powershell, etc.
It works like ./myapp completion bash > .bash_myapp and add source ~/.bash_myapp into .bashrc.
ps: as a gopher, I have used https://github.com/spf13/cobra to build command line too for a long time, which provides a basic support for generating completion script for bash, zsh, powershell, etc.
It works like ./myapp completion bash > .bash_myapp and add source ~/.bash_myapp into .bashrc.
It seems weirdly inconsistent that rustup completions <bash/zsh/...> is a thing, but cargo completions bash isn't a thing.
For those arriving in the future, the work around to enable these manually (Tested Ubuntu 22.04/20.04) is: cat $(rustc --print sysroot)/etc/bash_completion.d/cargo > ~/.local/share/bash-completion/completions/cargo
How will this handle security with respect to path specifications in rust-toolchain.toml? It would be pretty bad if doing a cargo command completion inside a malicious repo would cause arbitrary code execution. And even for a non-malicious repo have to wait for rustup to download the toolchain if it isn't already when trying to get completions is annoying. Will the shell completions ensure that they invoke the cargo from which they were generated without going through the rustup wrapper?
#14084 proposes an idea that the completion script could learn available learn options from .cargo/config.toml. We might want to consider that when generating completion scripts as well.
I'd like to be alias-aware but not going to block the work on it as it adds a lot of extra complexity to clap_complete as we now need cargo to interject itself directly into the parsing process.
Activity
nrc commentedon Feb 27, 2019
I don't know how this works at all, but why do some tool's shell completions just work (e.g., Git) whereas the Rust tools seem to need some kind of opt-in step? Of course, I think it would be nice if we didn't need this opt-in step.
ehuss commentedon Feb 27, 2019
It depends on how rust/cargo is installed. Some installers (like ubuntu) will automatically add the completion file to the global location (such as
/usr/share/bash-completion/completions/) and it will "just work" assuming your shell is configured to load them. rustup does not do that, since it avoids touching files outside of the user's home directory. rustup could install them in the user's home directory ($XDG_DATA_HOME/bash-completion/completions, and probably something similar for other shells). That would need to be a decision for rustup to make, if it is acceptable to dump files in various locations.jpalomaki commentedon Apr 13, 2019
FWIW, I just started learning Rust (cargo), using rustup, and this was pretty much the first thing I hit. 😄
If we want to keep stuff in the user's home directory (as opposed to e.g.
/etc/bash_completion.d), one way to do this (for bash) is:I use said approach with kubectl: https://kubernetes.io/docs/tasks/tools/install-kubectl/#enabling-shell-autocompletion
scooter-dangle commentedon Apr 23, 2019
@ehuss, had you considered looking at how to include something like this in clap (or as an add-on to clap) rather than directly in cargo?
ehuss commentedon Apr 23, 2019
@scooter-dangle In a sense, it will be a clap addon, because it will probably be looking at the (hidden) clap internals to infer the options. My impression is that clap development has stalled and v3 has a long ways to go, so I don't think it is something we can use in the foreseeable future, and there's no indication how new features like this would make progress. There is an issue for this (clap-rs/clap#810), but there's no sense from the issue if it will support custom extensions or how it will work.
andradei commentedon Apr 30, 2019
I used
rustup completions zsh cargoand it is not working. Thanks for the work on this.Related issue: rust-lang/rustup#1821
tesuji commentedon Jun 22, 2019
See more:
pickfire commentedon Jul 12, 2019
Is it possible to reduce cargo start time or optionally use generated completions as it is faster only a one-time cost?
ehuss commentedon Jul 15, 2019
I'm not sure what you mean here. Cargo should launch in about 25ms, depending on your system. I think that should be plenty fast for completion.
hsandt commentedon Dec 18, 2019
As a workaround, for now I just added a symlink to the installed completions for my current toolchain, in my local completions. On Linux, stable toolchain:
This will work for a specific toolchain, but the file seems to be a copy of cargo.bashcomp.sh, so I guess it doesn't matter too much.
petr-tik commentedon Jul 22, 2021
I would like to add an enhancement to the original feature request.
Interactive fuzzy completions
I got this idea after writing custom fzf wrappers over cmake like this one:
find all cmakelists in a project, grep all invocations of
add_libraryandadd_executable, pipe that to fzf, pipe the target selected by the user to cmake build.Once I wrote this bash function, i could drop into any new cmake project, run my
pt-buildand have an interactive selector for the tests, libraries or executables that I might want to build.since cargo already provides a uniform way to build any rust projects, I think it would be great to enable developers to interactively select the build target.
user story
Required building blocks
2 components are required - quickly producing a list of relevant targets (filtered by type) and exposing a fuzzy interface to the user.
Query cargo for all targets to complete with
Bazel and buck build systems have
querysubcommands that can produce lists of targets filtered by labels like build, test, bench. Cargo should be able to analyze the workspace and list:binary targets to pass to
--binexample targets to pass to
--examplebench targets to pass to
--benchAdd a fuzzy completion interface
The fzf-like rust crate is called skim and it provides us with the primitives to expose a fuzzy finder to the user.
https://github.com/lotabout/skim
Once this exists, the bash completion functions can call the corresponding cargo fuzzy-picker depending on the tokens already typed on the command line.
Prior Art/Other build systems
As i was writing this, I found this open feature request on the bazel repo. Great minds think alike!
bazelbuild/bazel#11644
Under-explored
Since cargo enables people to write their own plugins, like cargo fuzz, the target types defined by those need to be made available to original cargo, so they can be listed as completion options. I am not sure how that would work.
hitzhangjie commentedon Aug 21, 2021
If cargo support this, it would be better.
ps: as a gopher, I have used https://github.com/spf13/cobra to build command line tools for a long time, which provides a basic support for generating completion script for bash, zsh, powershell, etc.
It works like
./myapp completion bash > .bash_myappand addsource ~/.bash_myappinto .bashrc.scooter-dangle commentedon Aug 21, 2021
FYI: Clap generates completions like that (
App::gen_completions_to), but the application needs to expose it. E.g., here's how starship does that.epage commentedon Apr 21, 2022
Relevant clap issues:
nuzzles commentedon May 5, 2022
It seems weirdly inconsistent that
rustup completions <bash/zsh/...>is a thing, butcargo completions bashisn't a thing.For those arriving in the future, the work around to enable these manually (Tested Ubuntu 22.04/20.04) is:
cat $(rustc --print sysroot)/etc/bash_completion.d/cargo > ~/.local/share/bash-completion/completions/cargobjorn3 commentedon Jan 12, 2024
How will this handle security with respect to path specifications in rust-toolchain.toml? It would be pretty bad if doing a cargo command completion inside a malicious repo would cause arbitrary code execution. And even for a non-malicious repo have to wait for rustup to download the toolchain if it isn't already when trying to get completions is annoying. Will the shell completions ensure that they invoke the cargo from which they were generated without going through the rustup wrapper?
epage commentedon Jan 12, 2024
I don't think that will be a change from the status quo. The existing completions may call cargo or rustup, depending on the argument.
weihanglo commentedon Jun 17, 2024
#14084 proposes an idea that the completion script could learn available learn options from
.cargo/config.toml. We might want to consider that when generating completion scripts as well.Rudxain commentedon Jun 19, 2024
Does that include aliases? It would be convenient if completions were alias-aware
epage commentedon Jun 21, 2024
I'd like to be alias-aware but not going to block the work on it as it adds a lot of extra complexity to clap_complete as we now need cargo to interject itself directly into the parsing process.
Auto merge of #14493 - shannmu:dynamic_switch, r=epage
BrentHuang commentedon Nov 20, 2024
Make rustup support command line autocompletion under bash:
refer to: https://rust-lang.github.io/rustup/installation/index.html?highlight=Comple#enable-tab-completion-for-bash-fish-zsh-or-powershell
Make cargo support command line autocompletion:
rustup completions bash cargo >> ~/.bashrcRestart a new command line window and try.
epage commentedon Nov 6, 2025
Going to close in favor of the tracking issue, #14520