Adds shell completion generation.

This commit is contained in:
2026-08-23 23:52:59 -07:00
parent 5b29784c07
commit 8a7a201daa
4 changed files with 68 additions and 8 deletions

View File

@@ -6,6 +6,7 @@ edition = "2024"
[dependencies]
nextcloud_client = { path = "../nextcloud_client" }
clap = { version = "4.5", features = ["derive", "cargo"] }
clap_complete = "4.5"
tokio = { version = "1", features = ["full"] }
reqwest = { version = "0.12", default-features = false, features = ["json", "default-tls"] }
open = "5.3"

View File

@@ -1,4 +1,5 @@
use clap::{Args, Parser, Subcommand};
use clap::{Args, CommandFactory, Parser, Subcommand};
use clap_complete::{generate, Shell};
use indicatif::{ProgressBar, ProgressDrawTarget, ProgressStyle};
use serde::Serialize;
use std::fs;
@@ -39,6 +40,13 @@ enum Commands {
/// Quick alias to list all configured accounts
Accounts(AccountListArgs),
/// Generate shell completion scripts for bash, zsh, fish, powershell, or elvish
Completions {
/// Target shell to generate completions for
#[arg(value_enum)]
shell: Shell,
},
}
#[derive(Args, Debug, PartialEq)]
@@ -207,6 +215,10 @@ async fn main() {
handle_account_set_default(&account)
}
Commands::Account(AccountCommands::Delete { account }) => handle_account_delete(&account),
Commands::Completions { shell } => {
handle_completions(shell);
Ok(())
}
};
if let Err(err) = result {
@@ -215,6 +227,12 @@ async fn main() {
}
}
/// Generate shell completion scripts for supported shells.
fn handle_completions(shell: Shell) {
let mut cmd = Cli::command();
generate(shell, &mut cmd, "nut", &mut io::stdout());
}
/// Handle interactive or non-interactive login flows.
async fn handle_login(args: LoginArgs) -> Result<()> {
let server_url = ClientConfig::normalize_url(&args.server_url)?;
@@ -822,4 +840,35 @@ mod tests {
_ => panic!("Expected Accounts list command"),
}
}
#[test]
fn test_cli_completions_parsing() {
let shells = [
("bash", Shell::Bash),
("zsh", Shell::Zsh),
("fish", Shell::Fish),
("powershell", Shell::PowerShell),
("elvish", Shell::Elvish),
];
for (name, expected_shell) in shells {
let parsed = Cli::try_parse_from(&["nut", "completions", name]).unwrap();
match parsed.command {
Commands::Completions { shell } => {
assert_eq!(shell, expected_shell);
}
_ => panic!("Expected Completions command for shell {name}"),
}
let mut buf = Vec::new();
let mut cmd = Cli::command();
generate(expected_shell, &mut cmd, "nut", &mut buf);
assert!(!buf.is_empty(), "Generated completion for {name} should not be empty");
let output_str = String::from_utf8(buf).expect("Completions should be valid UTF-8");
assert!(
output_str.contains("nut"),
"Completion output should contain 'nut'"
);
}
}
}