From 07c41551ab74f912effda5c338f4082dbfbc4902 Mon Sep 17 00:00:00 2001 From: 0xYYY <0xYYY@protonmail.com> Date: Mon, 28 Nov 2022 22:27:03 +0800 Subject: [PATCH 1/5] feat: fuelup completions --- Cargo.lock | 10 ++++++++++ Cargo.toml | 1 + src/commands/completions.rs | 21 +++++++++++++++++++++ src/commands/mod.rs | 1 + src/fuelup_cli.rs | 8 ++++++-- src/ops/fuelup_completions.rs | 11 +++++++++++ src/ops/mod.rs | 1 + 7 files changed, 51 insertions(+), 2 deletions(-) create mode 100644 src/commands/completions.rs create mode 100644 src/ops/fuelup_completions.rs diff --git a/Cargo.lock b/Cargo.lock index 59ab49fd4..58e96899b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -99,6 +99,15 @@ dependencies = [ "textwrap", ] +[[package]] +name = "clap_complete" +version = "3.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f7a2e0a962c45ce25afce14220bc24f9dade0a1787f185cecf96bfba7847cd8" +dependencies = [ + "clap", +] + [[package]] name = "clap_derive" version = "3.2.15" @@ -253,6 +262,7 @@ version = "0.12.2" dependencies = [ "anyhow", "clap", + "clap_complete", "component", "dirs", "flate2", diff --git a/Cargo.toml b/Cargo.toml index 716f73b06..505a94e85 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,6 +20,7 @@ path = "src/main.rs" [dependencies] anyhow = "1" clap = { version = "3.2", features = ["cargo", "derive", "env"] } +clap_complete = "3.2" component = { path = "component" } dirs = "4" flate2 = "1" diff --git a/src/commands/completions.rs b/src/commands/completions.rs new file mode 100644 index 000000000..c42109add --- /dev/null +++ b/src/commands/completions.rs @@ -0,0 +1,21 @@ +use anyhow::Result; +use clap::Parser; +use clap_complete::Shell; + +use crate::ops::fuelup_completions; + +/// Generate tab-completion scripts for your shell +#[derive(Debug, Parser)] +pub struct CompletionsCommand { + /// Specify shell to enable tab-completion for + /// + /// [possible values: zsh, bash, fish, powershell, elvish] + #[clap(short = 'S', long)] + pub shell: Shell, +} + +pub fn exec(command: CompletionsCommand) -> Result<()> { + fuelup_completions::completions(command)?; + + Ok(()) +} diff --git a/src/commands/mod.rs b/src/commands/mod.rs index 483446fb0..643631f39 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -1,4 +1,5 @@ pub mod check; +pub mod completions; pub mod component; pub mod default; pub mod fuelup; diff --git a/src/fuelup_cli.rs b/src/fuelup_cli.rs index a2f26d592..f1297465d 100644 --- a/src/fuelup_cli.rs +++ b/src/fuelup_cli.rs @@ -2,9 +2,10 @@ use anyhow::Result; use clap::Parser; use crate::commands::show::ShowCommand; -use crate::commands::{check, component, default, fuelup, show, toolchain, update}; +use crate::commands::{check, completions, component, default, fuelup, show, toolchain, update}; use crate::commands::check::CheckCommand; +use crate::commands::completions::CompletionsCommand; use crate::commands::component::ComponentCommand; use crate::commands::default::DefaultCommand; use crate::commands::fuelup::FuelupCommand; @@ -13,7 +14,7 @@ use crate::commands::update::UpdateCommand; #[derive(Debug, Parser)] #[clap(name = "fuelup", about = "Fuel Toolchain Manager", version)] -struct Cli { +pub struct Cli { #[clap(subcommand)] command: Commands, } @@ -22,6 +23,8 @@ struct Cli { enum Commands { /// Check for updates to Fuel toolchains and fuelup Check(CheckCommand), + /// Generate shell competions + Completions(CompletionsCommand), /// Add or remove components from the currently active toolchain #[clap(subcommand)] Component(ComponentCommand), @@ -44,6 +47,7 @@ pub fn fuelup_cli() -> Result<()> { match cli.command { Commands::Check(command) => check::exec(command), + Commands::Completions(command) => completions::exec(command), Commands::Component(command) => component::exec(command), Commands::Default_(command) => default::exec(command), Commands::Fuelup(command) => match command { diff --git a/src/ops/fuelup_completions.rs b/src/ops/fuelup_completions.rs new file mode 100644 index 000000000..48ca24bf2 --- /dev/null +++ b/src/ops/fuelup_completions.rs @@ -0,0 +1,11 @@ +use crate::commands::completions::CompletionsCommand; +use anyhow::Result; +use clap::CommandFactory; +use clap_complete::generate; + +pub fn completions(command: CompletionsCommand) -> Result<()> { + let mut cmd = super::super::fuelup_cli::Cli::command(); + let bin_name = cmd.get_name().to_string(); + generate(command.shell, &mut cmd, bin_name, &mut std::io::stdout()); + Ok(()) +} diff --git a/src/ops/mod.rs b/src/ops/mod.rs index b73f57f2d..27c3cfb84 100644 --- a/src/ops/mod.rs +++ b/src/ops/mod.rs @@ -1,4 +1,5 @@ pub mod fuelup_check; +pub mod fuelup_completions; pub mod fuelup_component; pub mod fuelup_default; pub mod fuelup_self; From 030d39c53565b48b69411e692189b5a5d0b65a69 Mon Sep 17 00:00:00 2001 From: 0xYYY <0xYYY@protonmail.com> Date: Mon, 28 Nov 2022 22:45:15 +0800 Subject: [PATCH 2/5] add test --- tests/commands.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests/commands.rs b/tests/commands.rs index 1f99591c5..86dc05146 100644 --- a/tests/commands.rs +++ b/tests/commands.rs @@ -536,3 +536,17 @@ You may create a custom toolchain using 'fuelup toolchain new '. })?; Ok(()) } + +#[test] +fn fuelup_completions() -> Result<()> { + testcfg::setup(FuelupState::LatestToolchainInstalled, &|cfg| { + let shells = ["zsh", "bash", "fish", "powershell", "elvish"]; + for shell in shells { + let output = cfg.fuelup(&["completions", "--shell", shell]); + + assert!(output.status.success()); + } + })?; + + Ok(()) +} From 04487b56e96753cd5af4691e5895b084bb6b2aef Mon Sep 17 00:00:00 2001 From: 0xYYY <0xYYY@protonmail.com> Date: Mon, 28 Nov 2022 22:45:49 +0800 Subject: [PATCH 3/5] add instruction in fuelup-init --- fuelup-init.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fuelup-init.sh b/fuelup-init.sh index 8c717a18c..e043b086b 100755 --- a/fuelup-init.sh +++ b/fuelup-init.sh @@ -137,7 +137,7 @@ main() { ignore rmdir "$_dir" printf '\n' - printf '%s\n' "fuelup ${_fuelup_version} has been installed in $FUELUP_DIR/bin. To fetch the latest toolchain containing the forc and fuel-core binaries, run 'fuelup toolchain install latest'." 1>&2 + printf '%s\n' "fuelup ${_fuelup_version} has been installed in $FUELUP_DIR/bin. To fetch the latest toolchain containing the forc and fuel-core binaries, run 'fuelup toolchain install latest'. To generate completions for your shell, run 'fuelup completions --shell=SHELL'." 1>&2 if [ "$allow_modify" = "yes" ]; then if echo "$PATH" | grep -q "$FUELUP_DIR/bin"; then From c10cfd178c81334b8efce857c4ce64eaa131881e Mon Sep 17 00:00:00 2001 From: 0xYYY <0xYYY@protonmail.com> Date: Tue, 29 Nov 2022 10:55:02 +0800 Subject: [PATCH 4/5] fix typo --- src/fuelup_cli.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fuelup_cli.rs b/src/fuelup_cli.rs index f1297465d..efa512698 100644 --- a/src/fuelup_cli.rs +++ b/src/fuelup_cli.rs @@ -23,7 +23,7 @@ pub struct Cli { enum Commands { /// Check for updates to Fuel toolchains and fuelup Check(CheckCommand), - /// Generate shell competions + /// Generate shell completions Completions(CompletionsCommand), /// Add or remove components from the currently active toolchain #[clap(subcommand)] From 0cd2eea016e87bd9ce8bbdacde5ebc5f7d889654 Mon Sep 17 00:00:00 2001 From: 0xYYY <0xYYY@protonmail.com> Date: Tue, 29 Nov 2022 11:53:23 +0800 Subject: [PATCH 5/5] doc: add completions doc --- docs/src/configuration.md | 108 ++++++++++++++++++++++++++++++++++++++ docs/src/examples.md | 1 + 2 files changed, 109 insertions(+) diff --git a/docs/src/configuration.md b/docs/src/configuration.md index 1007d9965..2ac0c53c1 100644 --- a/docs/src/configuration.md +++ b/docs/src/configuration.md @@ -3,3 +3,111 @@ _fuelup_ has a [TOML](https://github.com/toml-lang/toml) settings file at `.fuelup/settings.toml`. The schema for this file is not part of the public interface for _fuelup_ - the fuelup CLI should be used to query and set settings. + +## Generate Shell Completions + +Enable tab completion for Bash, Fish, Zsh, or PowerShell. The script prints output on `stdout`, +allowing one to re-direct the output to the file of their choosing. Where you place the file will +depend on which shell, and which operating system you are using. Your particular configuration may +also determine where these scripts need to be placed. + +Here are some common set ups for the supported shells under Unix and similar operating systems +(such as GNU/Linux). For these settings to take effect, you may have to log out and log back in to +your shell session. + +### BASH + +Completion files are commonly stored in `/etc/bash_completion.d/` for system-wide commands, but can +be stored in `~/.local/share/bash-completion/completions` for user-specific commands. + +```sh +mkdir -p ~/.local/share/bash-completion/completions +fuelup completions --shell=bash >> ~/.local/share/bash-completion/completions/fuelup +``` + +## BASH (macOS/Homebrew) + +Homebrew stores bash completion files within the Homebrew directory. With the `bash-completion` brew +formula installed. + +```sh +mkdir -p $(brew --prefix)/etc/bash_completion.d +fuelup completions --shell=bash > $(brew --prefix)/etc/bash_completion.d/fuelup.bash-completion +``` + +### FISH + +Fish completion files are commonly stored in `$HOME/.config/fish/completions`. + +```sh +mkdir -p ~/.config/fish/completions +fuelup completions --shell=fish > ~/.config/fish/completions/fuelup.fish +``` + +### ZSH + +ZSH completions are commonly stored in any directory listed in your `$fpath` variable. To use these +completions, you must either add the generated script to one of those directories, or add your own +to this list. + +Adding a custom directory is often the safest bet if you are unsure of which directory to use. First +create the directory; for this example we'll create a hidden directory inside our `$HOME` directory: + +```sh +mkdir ~/.zfunc +``` + +Then add the following lines to your `.zshrc` just before `compinit`: + +```sh +fpath+=~/.zfunc +``` + +Now you can install the completions script using the following command: + +```sh +fuelup completions --shell=zsh > ~/.zfunc/_fuelup +``` + +### POWERSHELL + +The powershell completion scripts require PowerShell v5.0+ (which comes with Windows 10, but can be +downloaded separately for windows 7 or 8.1). + +First, check if a profile has already been set + +```sh +Test-Path $profile +``` + +If the above command returns `False` run the following + +```sh +New-Item -path $profile -type file -force +``` + +Now open the file provided by `$profile` (if you used the `New-Item` command it will be +`${env:USERPROFILE}\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1`). + +Next, we either save the completions file into our profile, or into a separate file and source it +inside our profile. To save the completions into our profile simply use + +```sh +fuelup completions --shell=powershell >> ${env:USERPROFILE}\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1 +``` + +### ELVISH + +Elvish completions are commonly stored in [`epm`](https://elv.sh/ref/epm.html#the-epm-managed-directory)-managed +directories. + +```sh +fuelup completions --shell=elvish > ~/.local/share/elvish/lib/fuelup.elv +``` + +Then in [`rc.elv`](https://elv.sh/ref/command.html#rc-file), add the following line to activate the +generated completions. + +```sh +use fuelup +``` diff --git a/docs/src/examples.md b/docs/src/examples.md index 9fca544d6..47392dd63 100644 --- a/docs/src/examples.md +++ b/docs/src/examples.md @@ -13,6 +13,7 @@ | `fuelup check` | Checks for updates to distributable toolchains | | `fuelup show` | Shows the active toolchain and installed toolchains, as well as the host and fuelup home | | `fuelup toolchain help` | Shows the `help` page for a subcommand (like `toolchain`) | +| `fuelup completions --shell=zsh` | Generate shell completions for ZSH | [forc]: https://github.com/FuelLabs/sway/tree/master/forc [fuel-core]: https://github.com/FuelLabs/fuel-core