From 30711645f40a9d99c2f03a77ce63a315974b80f5 Mon Sep 17 00:00:00 2001 From: rami3l Date: Fri, 21 Nov 2025 21:51:58 +0100 Subject: [PATCH 1/3] refactor(cli/rustup-mode): use new-style string formatting --- src/cli/rustup_mode.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/cli/rustup_mode.rs b/src/cli/rustup_mode.rs index fe9666e345..1bc53c1c10 100644 --- a/src/cli/rustup_mode.rs +++ b/src/cli/rustup_mode.rs @@ -1877,9 +1877,7 @@ fn output_completion_script( Shell::Zsh => "/share/zsh/site-functions/_cargo", _ => { return Err(anyhow!( - "{} does not currently support completions for {}", - command, - shell + "{command} does not currently support completions for {shell}", )); } }; From c037aeca9e926f397e2ea65a1af4ac2162a7db1b Mon Sep 17 00:00:00 2001 From: rami3l Date: Fri, 21 Nov 2025 21:53:39 +0100 Subject: [PATCH 2/3] refactor(cli/rustup-mode): merge duplicate match arms --- src/cli/rustup_mode.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/cli/rustup_mode.rs b/src/cli/rustup_mode.rs index 1bc53c1c10..9d2a136736 100644 --- a/src/cli/rustup_mode.rs +++ b/src/cli/rustup_mode.rs @@ -1868,13 +1868,12 @@ fn output_completion_script( ); } CompletionCommand::Cargo => { - if let Shell::Zsh = shell { - writeln!(process.stdout().lock(), "#compdef cargo")?; - } - let script = match shell { Shell::Bash => "/etc/bash_completion.d/cargo", - Shell::Zsh => "/share/zsh/site-functions/_cargo", + Shell::Zsh => { + writeln!(process.stdout().lock(), "#compdef cargo")?; + "/share/zsh/site-functions/_cargo" + } _ => { return Err(anyhow!( "{command} does not currently support completions for {shell}", From fad89bfcaaf0c844c7fea537093ea7948320e8b4 Mon Sep 17 00:00:00 2001 From: rami3l Date: Fri, 21 Nov 2025 21:54:54 +0100 Subject: [PATCH 3/3] feat(cli/rustup-mode): support `rustup` completion for nushell --- Cargo.lock | 11 ++++ Cargo.toml | 1 + src/cli/rustup_mode.rs | 57 +++++++++++++++++-- ..._completions_cmd_help_flag.stdout.term.svg | 2 +- 4 files changed, 66 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6f1406f038..6ef78c1d51 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -358,6 +358,16 @@ dependencies = [ "clap", ] +[[package]] +name = "clap_complete_nushell" +version = "4.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "685bc86fd34b7467e0532a4f8435ab107960d69a243785ef0275e571b35b641a" +dependencies = [ + "clap", + "clap_complete", +] + [[package]] name = "clap_derive" version = "4.5.49" @@ -2146,6 +2156,7 @@ dependencies = [ "clap", "clap-cargo", "clap_complete", + "clap_complete_nushell", "console", "curl", "effective-limits", diff --git a/Cargo.toml b/Cargo.toml index 8d3e0e0d1c..6e8ee7a5a1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -49,6 +49,7 @@ chrono = { version = "0.4", default-features = false, features = ["std"] } clap = { version = "4", features = ["derive", "wrap_help", "string"] } clap-cargo = "0.18.3" clap_complete = "4" +clap_complete_nushell = "4.5" console = "0.16" curl = { version = "0.4.44", optional = true } effective-limits = "0.5.5" diff --git a/src/cli/rustup_mode.rs b/src/cli/rustup_mode.rs index 9d2a136736..7d22fad90e 100644 --- a/src/cli/rustup_mode.rs +++ b/src/cli/rustup_mode.rs @@ -281,7 +281,7 @@ enum RustupSubcmd { /// Generate tab-completion scripts for your shell #[command(after_help = completions_help(), arg_required_else_help = true)] Completions { - shell: Shell, + shell: CompletionShell, #[arg(default_value = "rustup")] command: CompletionCommand, @@ -1853,8 +1853,57 @@ impl fmt::Display for CompletionCommand { } } +#[derive(clap::ValueEnum, Clone, Copy, Debug)] +enum CompletionShell { + Bash, + Elvish, + Fish, + Nushell, + PowerShell, + Zsh, +} + +impl fmt::Display for CompletionShell { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(match self { + CompletionShell::Bash => "bash", + CompletionShell::Elvish => "elvish", + CompletionShell::Fish => "fish", + CompletionShell::Nushell => "nushell", + CompletionShell::PowerShell => "powershell", + CompletionShell::Zsh => "zsh", + }) + } +} + +impl clap_complete::Generator for CompletionShell { + fn file_name(&self, name: &str) -> String { + match self { + CompletionShell::Bash => Shell::Bash.file_name(name), + CompletionShell::Elvish => Shell::Elvish.file_name(name), + CompletionShell::Fish => Shell::Fish.file_name(name), + CompletionShell::PowerShell => Shell::PowerShell.file_name(name), + CompletionShell::Zsh => Shell::Zsh.file_name(name), + + CompletionShell::Nushell => clap_complete_nushell::Nushell.file_name(name), + } + } + + fn generate(&self, cmd: &clap::Command, buf: &mut dyn Write) { + match self { + CompletionShell::Bash => Shell::Bash.generate(cmd, buf), + CompletionShell::Elvish => Shell::Elvish.generate(cmd, buf), + CompletionShell::Fish => Shell::Fish.generate(cmd, buf), + CompletionShell::PowerShell => Shell::PowerShell.generate(cmd, buf), + CompletionShell::Zsh => Shell::Zsh.generate(cmd, buf), + + CompletionShell::Nushell => clap_complete_nushell::Nushell.generate(cmd, buf), + } + } +} + fn output_completion_script( - shell: Shell, + shell: CompletionShell, command: CompletionCommand, process: &Process, ) -> Result { @@ -1869,8 +1918,8 @@ fn output_completion_script( } CompletionCommand::Cargo => { let script = match shell { - Shell::Bash => "/etc/bash_completion.d/cargo", - Shell::Zsh => { + CompletionShell::Bash => "/etc/bash_completion.d/cargo", + CompletionShell::Zsh => { writeln!(process.stdout().lock(), "#compdef cargo")?; "/share/zsh/site-functions/_cargo" } diff --git a/tests/suite/cli_rustup_ui/rustup_completions_cmd_help_flag.stdout.term.svg b/tests/suite/cli_rustup_ui/rustup_completions_cmd_help_flag.stdout.term.svg index 4016f4f778..93425f1ba3 100644 --- a/tests/suite/cli_rustup_ui/rustup_completions_cmd_help_flag.stdout.term.svg +++ b/tests/suite/cli_rustup_ui/rustup_completions_cmd_help_flag.stdout.term.svg @@ -30,7 +30,7 @@ Arguments: - <SHELL> [possible values: bash, elvish, fish, powershell, zsh] + <SHELL> [possible values: bash, elvish, fish, nushell, power-shell, zsh] [COMMAND] [default: rustup] [possible values: rustup, cargo]