Added completions for NuShell (#513)

* Added a CompletionShell enum and implemented required methods for it

* CompletionsOpts now uses CompletionShell enum to be able to call NuShell as well

* CompletionsOpts now uses CompletionShell enum to be able to call NuShell as well

* CompletionShell implements the generate method - simplifies the code

* Added clap_complete_nushell as a dependency

* Updated readme

* Added nushell completion

* Cargo fmt errors
This commit is contained in:
cojmeister 2025-08-13 10:27:08 +03:00 committed by GitHub
parent 671f4904e9
commit 5c4f586558
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 96 additions and 5 deletions

View File

@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- Added option to specify Crosstool-NG version, using `-c` or `--crosstools-toolchain-version`
- Added an option for [NuShell](https://www.nushell.sh/) completion
### Fixed

11
Cargo.lock generated
View File

@ -292,6 +292,16 @@ dependencies = [
"clap",
]
[[package]]
name = "clap_complete_nushell"
version = "4.5.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a0c951694691e65bf9d421d597d68416c22de9632e884c28412cb8cd8b73dce"
dependencies = [
"clap",
"clap_complete",
]
[[package]]
name = "clap_derive"
version = "4.5.41"
@ -597,6 +607,7 @@ dependencies = [
"bytes",
"clap",
"clap_complete",
"clap_complete_nushell",
"directories",
"env_logger",
"flate2",

View File

@ -18,6 +18,7 @@ async-trait = "0.1.88"
bytes = "1.10.1"
clap = { version = "4.5.38", features = ["derive", "env"] }
clap_complete = "4.5.50"
clap_complete_nushell = "4.5.8"
directories = "6.0.0"
env_logger = "0.11.8"
flate2 = "1.1.1"

View File

@ -116,13 +116,13 @@ Options:
```
### Completions Subcommand
For detailed instructions on how to enable tab completion, see [Enable tab completion for Bash, Fish, Zsh, or PowerShell](#enable-tab-completion-for-bash-fish-zsh-or-powershell) section.
For detailed instructions on how to enable tab completion, see [Enable tab completion for Bash, Fish, Zsh, PowerShell or NuShell](#enable-tab-completion-for-bash-fish-zsh-or-powershell) section.
```
Usage: espup completions [OPTIONS] <SHELL>
Arguments:
<SHELL> Shell to generate completions for [possible values: bash, elvish, fish, powershell, zsh]
<SHELL> Shell to generate completions for [possible values: bash, zsh, fish, powershell, elvish, nushell]
Options:
-l, --log-level <LOG_LEVEL> Verbosity level of the logs [default: info] [possible values: debug, info, warn, error]
@ -295,6 +295,10 @@ $ espup completions zsh > ~/.zfunc/_espup
$ espup completions powershell >> $PROFILE.CurrentUserCurrentHost
# or
$ espup completions powershell | Out-String | Invoke-Expression
# NuShell
$ mkdir -p ~/.config/nushell/completions
$ espup completions nushell > ~/.config/nushell/completions/espup.nu
```
**Note**: you may need to restart your shell in order for the changes to take

View File

@ -1,8 +1,8 @@
//! Command line interface.
use crate::completion_shell::CompletionShell;
use crate::targets::{Target, parse_targets};
use clap::Parser;
use clap_complete::Shell;
use std::{collections::HashSet, path::PathBuf};
#[derive(Debug, Parser)]
@ -11,7 +11,7 @@ pub struct CompletionsOpts {
#[arg(short = 'l', long, default_value = "info", value_parser = ["debug", "info", "warn", "error"])]
pub log_level: String,
/// Shell to generate completions for.
pub shell: Shell,
pub shell: CompletionShell,
}
#[derive(Debug, Parser)]

72
src/completion_shell.rs Normal file
View File

@ -0,0 +1,72 @@
use clap::ValueEnum;
use clap_complete::Shell;
use clap_complete_nushell::Nushell;
use std::fmt;
use std::str::FromStr;
#[derive(Debug, Clone)]
pub enum CompletionShell {
Clap(Shell),
Nushell,
}
impl CompletionShell {
pub fn generate(&self, cmd: &mut clap::Command, bin_name: &str, out: &mut dyn std::io::Write) {
match self {
CompletionShell::Clap(sh) => {
clap_complete::generate(*sh, cmd, bin_name, out);
}
CompletionShell::Nushell => {
clap_complete::generate(Nushell, cmd, bin_name, out);
}
}
}
}
impl ValueEnum for CompletionShell {
fn value_variants<'a>() -> &'a [Self] {
use Shell::*;
// Static list of variants, one for each possible shell
const VARIANTS: &[CompletionShell] = &[
CompletionShell::Clap(Bash),
CompletionShell::Clap(Zsh),
CompletionShell::Clap(Fish),
CompletionShell::Clap(PowerShell),
CompletionShell::Clap(Elvish),
CompletionShell::Nushell,
];
VARIANTS
}
fn to_possible_value(&self) -> Option<clap::builder::PossibleValue> {
Some(match self {
CompletionShell::Clap(sh) => sh.to_possible_value()?,
CompletionShell::Nushell => clap::builder::PossibleValue::new("nushell"),
})
}
}
impl fmt::Display for CompletionShell {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
CompletionShell::Clap(shell) => write!(f, "{shell}"),
CompletionShell::Nushell => write!(f, "nushell"),
}
}
}
impl FromStr for CompletionShell {
type Err = String;
fn from_str(input: &str) -> Result<Self, Self::Err> {
match input.to_ascii_lowercase().as_str() {
"bash" | "zsh" | "fish" | "powershell" | "elvish" => input
.parse::<Shell>()
.map(CompletionShell::Clap)
.map_err(|e| e.to_string()),
"nushell" => Ok(CompletionShell::Nushell),
_ => Err(format!("unsupported shell: {input}")),
}
}
}

View File

@ -1,4 +1,5 @@
pub mod cli;
mod completion_shell;
pub mod env;
pub mod error;
pub mod host_triple;

View File

@ -43,7 +43,8 @@ async fn completions(args: CompletionsOpts) -> Result<()> {
info!("Generating completions for {} shell", args.shell);
clap_complete::generate(args.shell, &mut Cli::command(), "espup", &mut stdout());
args.shell
.generate(&mut Cli::command(), "espup", &mut stdout());
info!("Completions successfully generated!");