# GSoC Final Submission
Contributor: shanmu([@shanmu](https://github.com/shannmu))
Mentor: Ed Page([@epage](https://github.com/epage))
Project: Move cargo shell completions to Rust
Organization: The Rust Foundation
## Overview
The goal of this project can be divided into two phases.
The first phase is related to the [clap](https://github.com/clap-rs/clap), where a new command-line completion system ([clap_complete](https://github.com/clap-rs/clap/tree/master/clap_complete)) will be built on top of the existing [clap](https://github.com/clap-rs/clap). This will allow users to implement multiple shell completions with a single Rust codebase, and it will make it easier for users to extend and add completion results.
The second phase is related to [Cargo](https://github.com/rust-lang/cargo). Since [Cargo](https://github.com/rust-lang/cargo)'s CLI is built using [clap](https://github.com/clap-rs/clap), we can use [clap_complete](https://github.com/clap-rs/clap/tree/master/clap_complete) to add Rust code for cargo completions. This will make it easier to implement complex completion scripts (e.g., workspace-related or network-related tasks) directly in Rust code. Our goal is to align with the existing hand-written completion scripts.
**Before I started this project**, there were already some infrastructure had already been established. See [feat(complete): Skeleton for Rust-driven completions](https://github.com/clap-rs/clap/pull/3656)
## Current State of project
At present, we could use rust-native cargo completions easily. See [Native-completions](https://github.com/rust-lang/cargo/blob/master/src/doc/src/reference/unstable.md#native-completions) to get the new feature and expect your feedback.
Also, user could use `clap_complete` to add their completion feature for their cli application. See [clap_complete::env](https://docs.rs/clap_complete/latest/clap_complete/env/index.html).
### What work has done
- **clap part**
What we support now:
- Completie subcommands, including the subcommands themselves and their aliases.
- Completie optional flags, including visible_aliases and hidden_aliases
- Completie positional arguments.
- Completie values of optional flags, including support for completing multi-values of a single optional flag.
- Support for adding predefined completions for arguments, including possible values of value_parser and valuehint (mainly for completing filenames).
- Support for adding custom completions for arguments (this feature makes dynamic truly dynamic).
- Supported shells: bash, fish, zsh, and elvish.
**Related PR:**
- [Support flags with values `--flag bar` and `-f bar` in native completions](https://github.com/clap-rs/clap/pull/5539)
- [Add native completion support for elvish](https://github.com/clap-rs/clap/pull/5544)
- [Add native completion support for zsh](https://github.com/clap-rs/clap/pull/5545)
- [Add support for visible subcommand aliases](https://github.com/clap-rs/clap/pull/5549)
- [Add powershell support for native completion(partly merged)](https://github.com/clap-rs/clap/pull/5549)
- [Support `-fbar` and `-f=bar` in native completions](https://github.com/clap-rs/clap/pull/5576)
- [Support hiding long flags and their long aliases](https://github.com/clap-rs/clap/pull/5583)
- [Support hiding long flags and their long aliases](https://github.com/clap-rs/clap/pull/5584)
- [Support hiding possible values](https://github.com/clap-rs/clap/pull/5585)
- [Add document comments how to source dynamic completions](https://github.com/clap-rs/clap/pull/5586)
- [Support multiple values in native completions](https://github.com/clap-rs/clap/pull/5601)
- [Support delimited values in native completions](https://github.com/clap-rs/clap/pull/5602)
- [**Support dynamic value of argument completion**](https://github.com/clap-rs/clap/pull/5621)
- **cargo part**
- Add rust-native completions feature under the `nightly-features`
- Add a series of custom completions. What we support:
- `cargo build --example <TAB>`
- `cargo uninstall <TAB>`
- `cargo build --bin=<TAB>`
- `cargo build --bench=<TAB>`
- `cargo test --test=<TAB>`
- `cargo help <TAB>`
- `cargo -Z <TAB>`
- `cargo build --target=<TAB>`
**Related PR:**
- [**Add native comlpetion with CompleteEnv under the nightly**](https://github.com/rust-lang/cargo/pull/14493)
- [Add custom completer for completing example names](https://github.com/rust-lang/cargo/pull/14531)
- [Add custom completer for completing benchmark names](https://github.com/rust-lang/cargo/pull/14532)
- [Add custom completer for completing bin names](https://github.com/rust-lang/cargo/pull/14533)
- [Add custom completer for completing installed binaries](https://github.com/rust-lang/cargo/pull/14534)
- [Add custom completer for completing target triple](https://github.com/rust-lang/cargo/pull/14535)
- [Add custom completer for completing unstable flags](https://github.com/rust-lang/cargo/pull/14536)
- [Add custom completer for completing test names](https://github.com/rust-lang/cargo/pull/14548)
- [Add custom completer for completing help subcommands](https://github.com/rust-lang/cargo/pull/14557)
### What is left to do
What is left to do of the project could be roughly tracked through the following two tracking issues:
- [Stablize Rust-Native Completion Engine Tracking Issue](https://github.com/clap-rs/clap/issues/3166)
- [Tracking Issue for native-completion](https://github.com/rust-lang/cargo/issues/14520)
In fact, there is still a lot of work to be done—there’s always room for improvement. After GSoC 2024 ends, I will continue to be involved in this project until the release of the stable version.
### Others
- [completest](https://github.com/assert-rs/completest)
The `completest` relies on interactive shells, or more specifically, PTY devices. This approach is quite general, and I believe it would be very meaningful to add support for more shells and platforms, as there are currently many libraries related to shell completion but a lack of end-to-end CI testing (if we added bin target).
## What I learned
I think what I've learned can be divided into two parts:**how to work with community** and **some code skills**.
### How to work with community
- If we encounter problems, seek help from the community rather than trying to solve them on our own by looking through the source code and search engines. This is also the fastest way to integrate into the community, starting with discussions on issues.
- Project management is important. Discuss our solutions under issues, discuss the specific code implementation in PRs, and after a PR is merged, provide feedback on the issue updates (such as a tracking comment or closing the issue), ensuring the progress of the project is always traceable. A tracking issue is also very important. It forces us to review all potential problems. When we need to implement a major feature, creating a tracking issue is absolutely necessary.
- In Rust, documentation is also important because it is user-facing. We can't expect others to have to check our repository (whether it's code or issues) when using new features. We should aim to make the documentation simple and easy to understand, with clear and easy-to-understand examples.
### Code skills
- Be proficient in using combinators, but avoid overusing them to ensure the code remains easy to read and review.
- Flatten code using `if let` and `match` with the `?` operator, making it easier to handle errors and perform code reviews.
- `cargo_test` made me realize that the `test` macro can actually be extended, which might give me ideas for adding tests to low-level code in the future.
## Acknowledgement
I am extremely grateful to my mentor for providing me with so much help, both in guiding the project from a broader perspective and reviewing the details of my code, as well as being patient with my poor English. I also want to sincerely thank the Rust Foundation and the other GSoC contributors, from whom I have learned a lot.