Add CLI completions for Nushell

This commit is contained in:
Sebastian Holmin committed 2026-08-31 17:00:14 +02:00
1 parent 46deaacafd
commit 9ac15e5a31
9 files changed
+126 -84

No files matched your search

Generated
+56 -79
View File
@@ -67,21 +67,6 @@ version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299"
[[package]]
name = "anstream"
version = "0.6.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a"
dependencies = [
"anstyle",
"anstyle-parse 0.2.7",
"anstyle-query",
"anstyle-wincon",
"colorchoice",
"is_terminal_polyfill",
"utf8parse",
]
[[package]]
name = "anstream"
version = "1.0.0"
@@ -89,7 +74,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d"
dependencies = [
"anstyle",
"anstyle-parse 1.0.0",
"anstyle-parse",
"anstyle-query",
"anstyle-wincon",
"colorchoice",
@@ -103,15 +88,6 @@ version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000"
[[package]]
name = "anstyle-parse"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2"
dependencies = [
"utf8parse",
]
[[package]]
name = "anstyle-parse"
version = "1.0.0"
@@ -127,7 +103,7 @@ version = "1.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc"
dependencies = [
"windows-sys 0.60.2",
"windows-sys 0.61.2",
]
[[package]]
@@ -138,7 +114,7 @@ checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d"
dependencies = [
"anstyle",
"once_cell_polyfill",
"windows-sys 0.60.2",
"windows-sys 0.61.2",
]
[[package]]
@@ -777,9 +753,9 @@ dependencies = [
[[package]]
name = "clap"
version = "4.5.60"
version = "4.6.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2797f34da339ce31042b27d23607e051786132987f595b02ba4f6a6dffb7030a"
checksum = "473c7e07f409a8d772161724aa8db6a765a2532a70f9667eeb7b49d3d02fbdca"
dependencies = [
"clap_builder",
"clap_derive",
@@ -787,11 +763,11 @@ dependencies = [
[[package]]
name = "clap_builder"
version = "4.5.60"
version = "4.6.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24a241312cea5059b13574bb9b3861cabf758b879c15190b37b6d6fd63ab6876"
checksum = "7b48fea5a88e9ae728a2dcbedbfc0e730f7d60da42e1cb049a83c9fb8b789889"
dependencies = [
"anstream 0.6.21",
"anstream",
"anstyle",
"clap_lex",
"strsim",
@@ -807,15 +783,25 @@ dependencies = [
]
[[package]]
name = "clap_derive"
version = "4.5.55"
name = "clap_complete_nushell"
version = "4.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a92793da1a46a5f2a02a6f4c46c6496b28c43638adea8306fcb0caa1634f24e5"
checksum = "ffb66bc82eb9c92b1727310ae2c5868df22ae7cf46185bc5c544a4fa71955e49"
dependencies = [
"clap",
"clap_complete",
]
[[package]]
name = "clap_derive"
version = "4.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d012d2b9d65aca7f18f4d9878a045bc17899bba951561ba5ec3c2ba1eed9a061"
dependencies = [
"heck 0.5.0",
"proc-macro2",
"quote",
"syn 2.0.106",
"syn 3.0.3",
]
[[package]]
@@ -836,7 +822,7 @@ version = "3.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "faf9468729b8cbcea668e36183cb69d317348c2e08e994829fb56ebfdfbaac34"
dependencies = [
"windows-sys 0.60.2",
"windows-sys 0.61.2",
]
[[package]]
@@ -1321,7 +1307,7 @@ dependencies = [
"libc",
"option-ext",
"redox_users",
"windows-sys 0.60.2",
"windows-sys 0.61.2",
]
[[package]]
@@ -1533,7 +1519,7 @@ version = "0.11.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0621c04f2196ac3f488dd583365b9c09be011a4ab8b9f37248ffcc8f6198b56a"
dependencies = [
"anstream 1.0.0",
"anstream",
"anstyle",
"env_filter",
"log",
@@ -1569,7 +1555,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
dependencies = [
"libc",
"windows-sys 0.60.2",
"windows-sys 0.61.2",
]
[[package]]
@@ -1916,14 +1902,14 @@ dependencies = [
"rand_chacha",
"rand_core 0.6.4",
"ring",
"socket2 0.6.5",
"socket2",
"thiserror 1.0.69",
"tokio",
"tokio-util 0.7.18",
"tracing",
"tun 0.8.14",
"typed-builder 0.21.2",
"windows-sys 0.60.2",
"windows-sys 0.61.2",
"x25519-dalek",
"zerocopy",
]
@@ -2321,7 +2307,7 @@ dependencies = [
"libc",
"percent-encoding",
"pin-project-lite",
"socket2 0.5.10",
"socket2",
"tokio",
"tower-service",
"tracing",
@@ -2618,7 +2604,7 @@ version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4d40460c0ce33d6ce4b0630ad68ff63d6661961c48b6dba35e5a4d81cfb48222"
dependencies = [
"socket2 0.6.5",
"socket2",
"widestring",
"windows-registry",
"windows-result",
@@ -3221,6 +3207,7 @@ dependencies = [
"chrono",
"clap",
"clap_complete",
"clap_complete_nushell",
"futures",
"itertools 0.14.0",
"mullvad-management-interface",
@@ -3409,7 +3396,7 @@ dependencies = [
"log",
"nix 0.31.3",
"pnet_packet 0.35.0",
"socket2 0.6.5",
"socket2",
"talpid-windows",
"tokio",
"windows-sys 0.61.2",
@@ -3464,7 +3451,7 @@ dependencies = [
"rand 0.9.4",
"rustls",
"rustls-pki-types",
"socket2 0.6.5",
"socket2",
"talpid-tunnel",
"thiserror 2.0.19",
"tokio",
@@ -3891,7 +3878,7 @@ version = "0.50.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5"
dependencies = [
"windows-sys 0.60.2",
"windows-sys 0.61.2",
]
[[package]]
@@ -4744,9 +4731,9 @@ dependencies = [
[[package]]
name = "proc-macro2"
version = "1.0.103"
version = "1.0.107"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8"
checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9"
dependencies = [
"unicode-ident",
]
@@ -4851,7 +4838,7 @@ dependencies = [
"quinn-udp",
"rustc-hash",
"rustls",
"socket2 0.5.10",
"socket2",
"thiserror 2.0.19",
"tokio",
"tracing",
@@ -4888,16 +4875,16 @@ dependencies = [
"cfg_aliases",
"libc",
"once_cell",
"socket2 0.5.10",
"socket2",
"tracing",
"windows-sys 0.60.2",
]
[[package]]
name = "quote"
version = "1.0.40"
version = "1.0.47"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001"
dependencies = [
"proc-macro2",
]
@@ -5196,7 +5183,7 @@ dependencies = [
"errno 0.3.14",
"libc",
"linux-raw-sys 0.12.1",
"windows-sys 0.60.2",
"windows-sys 0.61.2",
]
[[package]]
@@ -5332,7 +5319,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b55fb86dfd3a2f5f76ea78310a88f96c4ea21a3031f8d212443d56123fd0521"
dependencies = [
"libc",
"windows-sys 0.60.2",
"windows-sys 0.61.2",
]
[[package]]
@@ -5512,7 +5499,7 @@ dependencies = [
"serde_json",
"serde_urlencoded",
"shadowsocks-crypto",
"socket2 0.6.5",
"socket2",
"spin",
"thiserror 2.0.19",
"tokio",
@@ -5563,7 +5550,7 @@ version = "1.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b"
dependencies = [
"errno 0.2.8",
"errno 0.3.14",
"libc",
]
@@ -5642,16 +5629,6 @@ dependencies = [
"managed",
]
[[package]]
name = "socket2"
version = "0.5.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678"
dependencies = [
"libc",
"windows-sys 0.52.0",
]
[[package]]
name = "socket2"
version = "0.6.5"
@@ -5659,7 +5636,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3d1e2c7f27f8d4cb10542a02c49005dbd6e93095799d6f3be745fae9f8fedd4"
dependencies = [
"libc",
"windows-sys 0.60.2",
"windows-sys 0.61.2",
]
[[package]]
@@ -5736,7 +5713,7 @@ dependencies = [
"parking_lot",
"pnet_packet 0.34.0",
"rand 0.9.4",
"socket2 0.6.5",
"socket2",
"thiserror 1.0.69",
"tokio",
"tracing",
@@ -5868,7 +5845,7 @@ dependencies = [
"rand 0.9.4",
"serde",
"serde_json",
"socket2 0.6.5",
"socket2",
"talpid-cgroup",
"talpid-dbus",
"talpid-dns",
@@ -5960,7 +5937,7 @@ dependencies = [
"libc",
"log",
"nix 0.31.3",
"socket2 0.6.5",
"socket2",
"talpid-types",
"thiserror 2.0.19",
]
@@ -6075,7 +6052,7 @@ name = "talpid-windows"
version = "0.0.0"
dependencies = [
"futures",
"socket2 0.6.5",
"socket2",
"talpid-types",
"thiserror 2.0.19",
"tokio",
@@ -6106,7 +6083,7 @@ dependencies = [
"proptest",
"rand 0.9.4",
"rtnetlink",
"socket2 0.6.5",
"socket2",
"surge-ping",
"talpid-dbus",
"talpid-net",
@@ -6135,7 +6112,7 @@ dependencies = [
"getrandom 0.4.2",
"once_cell",
"rustix 1.1.4",
"windows-sys 0.60.2",
"windows-sys 0.61.2",
]
[[package]]
@@ -6340,7 +6317,7 @@ dependencies = [
"parking_lot",
"pin-project-lite",
"signal-hook-registry",
"socket2 0.6.5",
"socket2",
"tokio-macros",
"windows-sys 0.61.2",
]
@@ -6402,7 +6379,7 @@ dependencies = [
"log",
"once_cell",
"pin-project",
"socket2 0.6.5",
"socket2",
"tokio",
"windows-sys 0.60.2",
]
@@ -6546,7 +6523,7 @@ dependencies = [
"hyper-util",
"percent-encoding",
"pin-project",
"socket2 0.6.5",
"socket2",
"sync_wrapper",
"tokio",
"tokio-stream",
@@ -6879,7 +6856,7 @@ checksum = "f2f6fb2847f6742cd76af783a2a2c49e9375d0a111c7bef6f71cd9e738c72d6e"
dependencies = [
"memoffset 0.9.1",
"tempfile",
"windows-sys 0.60.2",
"windows-sys 0.61.2",
]
[[package]]
@@ -7336,7 +7313,7 @@ version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
dependencies = [
"windows-sys 0.60.2",
"windows-sys 0.61.2",
]
[[package]]
+1 -1
View File
@@ -372,7 +372,7 @@ log_header "Preparing for packaging Mullvad VPN $PRODUCT_VERSION"
if [[ "$(uname -s)" == "Darwin" || "$(uname -s)" == "Linux" ]]; then
mkdir -p "build/shell-completions"
for sh in bash zsh fish; do
for sh in bash zsh fish nushell; do
log_info "Generating shell completion script for $sh..."
cargo run --bin mullvad "${CARGO_ARGS[@]}" -- shell-completions "$sh" \
"build/shell-completions/"
@@ -104,6 +104,7 @@ function newConfig() {
{ from: distAssets('uninstall_macos.sh'), to: './uninstall.sh' },
{ from: buildAssets('shell-completions/_mullvad'), to: '.' },
{ from: buildAssets('shell-completions/mullvad.fish'), to: '.' },
{ from: buildAssets('shell-completions/mullvad.nu'), to: '.' },
],
},
@@ -214,6 +215,8 @@ function newConfig() {
buildAssets('shell-completions/_mullvad') + '=/usr/local/share/zsh/site-functions/_mullvad',
buildAssets('shell-completions/mullvad.fish') +
'=/usr/share/fish/vendor_completions.d/mullvad.fish',
buildAssets('shell-completions/mullvad.nu') +
'=/usr/share/nushell/vendor/autoload/mullvad.nu',
],
afterInstall: distAssets('linux/after-install.sh'),
afterRemove: distAssets('linux/after-remove.sh'),
@@ -257,6 +260,8 @@ function newConfig() {
buildAssets('shell-completions/_mullvad') + '=/usr/share/zsh/site-functions/_mullvad',
buildAssets('shell-completions/mullvad.fish') +
'=/usr/share/fish/vendor_completions.d/mullvad.fish',
buildAssets('shell-completions/mullvad.nu') +
'=/usr/share/nushell/vendor/autoload/mullvad.nu',
],
afterInstall: distAssets('linux/after-install.sh'),
afterRemove: distAssets('linux/after-remove.sh'),
+4
View File
@@ -79,6 +79,7 @@ EOM
)
ZSH_COMPLETIONS_DIR="/usr/local/share/zsh/site-functions/"
NUSHELL_COMPLETIONS_DIR="/usr/local/share/nushell/vendor/autoload/"
if [[ -d "/opt/homebrew/share/fish/vendor_completions.d/" ]]; then
FISH_COMPLETIONS_DIR="/opt/homebrew/share/fish/vendor_completions.d/"
@@ -106,6 +107,9 @@ ln -sf "$INSTALL_DIR/Mullvad VPN.app/Contents/Resources/mullvad-problem-report"
mkdir -p "$ZSH_COMPLETIONS_DIR"
ln -sf "$INSTALL_DIR/Mullvad VPN.app/Contents/Resources/_mullvad" "$ZSH_COMPLETIONS_DIR/_mullvad"
mkdir -p "$NUSHELL_COMPLETIONS_DIR"
ln -sf "$INSTALL_DIR/Mullvad VPN.app/Contents/Resources/mullvad.nu" "$NUSHELL_COMPLETIONS_DIR/mullvad.nu"
if [[ -d "$FISH_COMPLETIONS_DIR" ]]; then
ln -sf "$INSTALL_DIR/Mullvad VPN.app/Contents/Resources/mullvad.fish" "$FISH_COMPLETIONS_DIR/mullvad.fish"
fi
+3
View File
@@ -48,6 +48,9 @@ echo "Removing fish shell completion symlink ..."
sudo rm -f "/opt/homebrew/share/fish/vendor_completions.d/mullvad.fish"
sudo rm -f "/usr/local/share/fish/vendor_completions.d/mullvad.fish"
echo "Removing nushell completion symlink ..."
sudo rm -f "/usr/local/share/nushell/vendor/autoload/mullvad.nu"
echo "Removing CLI symlinks from /usr/local/bin/ ..."
sudo rm -f /usr/local/bin/mullvad /usr/local/bin/mullvad-problem-report
+1
View File
@@ -35,6 +35,7 @@ tokio = { workspace = true, features = ["fs", "macros", "rt-multi-thread"] }
[target.'cfg(all(unix, not(target_os = "android")))'.dependencies]
clap_complete = { version = "4.4.8" }
clap_complete_nushell = "4.6.2"
nix = { workspace = true, features = ["signal"] }
[target."cfg(windows)".build-dependencies]
+52 -4
View File
@@ -1,5 +1,7 @@
use anyhow::Result;
use clap::Parser;
#[cfg(all(unix, not(target_os = "android")))]
use clap::ValueEnum;
mod cmds;
mod format;
@@ -9,6 +11,53 @@ use crate::cmds::reset::SettingsKey;
pub const BIN_NAME: &str = env!("CARGO_BIN_NAME");
/// Shell with auto-generated completion script available.
///
/// NOTE: this enum as a copy of [`clap_complete::Shell`],
/// with Nushell added.
#[cfg(all(unix, not(target_os = "android")))]
#[derive(Clone, ValueEnum, Debug)]
enum CompletionShell {
/// Bourne Again `SHell` (bash)
Bash,
/// Elvish shell
Elvish,
/// Friendly Interactive `SHell` (fish)
Fish,
/// `PowerShell`
#[value(name = "powershell")]
PowerShell,
/// Z `SHell` (zsh)
Zsh,
/// Nushell
Nushell,
}
#[cfg(all(unix, not(target_os = "android")))]
impl CompletionShell {
fn generate_to(self, dir: &std::path::Path) -> std::io::Result<std::path::PathBuf> {
use clap::CommandFactory;
use clap_complete::Shell;
let mut command = Cli::command();
match self {
Self::Bash => clap_complete::generate_to(Shell::Bash, &mut command, BIN_NAME, dir),
Self::Elvish => clap_complete::generate_to(Shell::Elvish, &mut command, BIN_NAME, dir),
Self::Fish => clap_complete::generate_to(Shell::Fish, &mut command, BIN_NAME, dir),
Self::Nushell => clap_complete::generate_to(
clap_complete_nushell::Nushell,
&mut command,
BIN_NAME,
dir,
),
Self::PowerShell => {
clap_complete::generate_to(Shell::PowerShell, &mut command, BIN_NAME, dir)
}
Self::Zsh => clap_complete::generate_to(Shell::Zsh, &mut command, BIN_NAME, dir),
}
}
}
#[derive(Debug, Parser)]
#[command(version = mullvad_version::VERSION, about, long_about = None)]
#[command(propagate_version = true)]
@@ -116,7 +165,7 @@ enum Cli {
#[command(hide = true)]
ShellCompletions {
/// The shell to generate the script for
shell: clap_complete::Shell,
shell: CompletionShell,
/// Output directory where the shell completions are written
#[arg(default_value = "./")]
@@ -200,11 +249,10 @@ async fn main() -> Result<()> {
#[cfg(all(unix, not(target_os = "android")))]
Cli::ShellCompletions { shell, dir } => {
use anyhow::Context;
use clap::CommandFactory;
// FIXME: The shell completions include hidden commands (including "shell-completions")
println!("Generating shell completions to {}", dir.display());
clap_complete::generate_to(shell, &mut Cli::command(), BIN_NAME, dir)
shell
.generate_to(&dir)
.context("Failed to generate shell completions")?;
Ok(())
}
+2
View File
@@ -37,6 +37,7 @@ assets = [
{ source = "../build/shell-completions/mullvad.bash", dest = "usr/share/bash-completion/completions/mullvad", mode = "644" },
{ source = "../build/shell-completions/_mullvad", dest = "usr/local/share/zsh/site-functions/_mullvad", mode = "644" },
{ source = "../build/shell-completions/mullvad.fish", dest = "usr/share/fish/vendor_completions.d/mullvad.fish", mode = "644" },
{ source = "../build/shell-completions/mullvad.nu", dest = "usr/share/nushell/vendor/autoload/mullvad.nu", mode = "644" },
{ source = "../CHANGELOG.md", dest = "opt/Mullvad VPN/resources/", mode = "644" },
]
@@ -62,6 +63,7 @@ assets = [
{ source = "../build/shell-completions/mullvad.bash", dest = "/usr/share/bash-completion/completions/mullvad", mode = "644" },
{ source = "../build/shell-completions/_mullvad", dest = "/usr/share/zsh/site-functions/_mullvad", mode = "644" },
{ source = "../build/shell-completions/mullvad.fish", dest = "/usr/share/fish/vendor_completions.d/mullvad.fish", mode = "644" },
{ source = "../build/shell-completions/mullvad.nu", dest = "/usr/share/nushell/vendor/autoload/mullvad.nu", mode = "644" },
{ source = "../CHANGELOG.md", dest = "/opt/Mullvad VPN/resources/", mode = "644" },
]
+2
View File
@@ -77,6 +77,7 @@ pub fn find_traces() -> Result<Vec<AppTrace>, Error> {
Path::new(r"/usr/share/bash-completion/completions/mullvad"),
Path::new(r"/usr/local/share/zsh/site-functions/_mullvad"),
Path::new(r"/usr/share/fish/vendor_completions.d/mullvad.fish"),
Path::new(r"/usr/share/nushell/vendor/autoload/mullvad.nu"),
];
Ok(existing_paths(&traces))
@@ -106,6 +107,7 @@ pub fn find_traces() -> Result<Vec<AppTrace>, Error> {
Path::new(r"/usr/local/share/zsh/site-functions/_mullvad"),
Path::new(r"/opt/homebrew/share/fish/vendor_completions.d/mullvad.fish"),
Path::new(r"/usr/local/share/fish/vendor_completions.d/mullvad.fish"),
Path::new(r"/usr/local/share/nushell/vendor/autoload/mullvad.nu"),
];
Ok(existing_paths(&traces))