diff --git a/Cargo.lock b/Cargo.lock index fa8b2533..b9936bac 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -477,6 +477,15 @@ dependencies = [ "strsim", ] +[[package]] +name = "clap_complete" +version = "4.5.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e602857739c5a4291dfa33b5a298aeac9006185229a700e5810a3ef7272d971" +dependencies = [ + "clap", +] + [[package]] name = "clap_derive" version = "4.5.41" @@ -2819,6 +2828,7 @@ dependencies = [ "anyhow", "chrono", "clap", + "clap_complete", "dunce", "human-panic", "itertools", diff --git a/crates/radicle-cli/Cargo.toml b/crates/radicle-cli/Cargo.toml index 99ef3354..58f0f83f 100644 --- a/crates/radicle-cli/Cargo.toml +++ b/crates/radicle-cli/Cargo.toml @@ -17,6 +17,7 @@ path = "src/main.rs" anyhow = "1" chrono = { workspace = true, features = ["clock", "std"] } clap = { version = "4.5.44", features = ["derive"] } +clap_complete = "4.5" dunce = { workspace = true } human-panic.workspace = true itertools.workspace = true diff --git a/crates/radicle-cli/src/main.rs b/crates/radicle-cli/src/main.rs index b407931b..3aa59e47 100644 --- a/crates/radicle-cli/src/main.rs +++ b/crates/radicle-cli/src/main.rs @@ -7,7 +7,7 @@ use std::{io::ErrorKind, process}; use anyhow::anyhow; use clap::builder::styling::AnsiColor; use clap::builder::Styles; -use clap::{Parser, Subcommand}; +use clap::{CommandFactory as _, Parser, Subcommand}; use radicle::version::Version; use radicle_cli::commands::*; @@ -98,6 +98,13 @@ enum Command { json: bool, }, + /// Print static completion information for a given shell + #[command(hide = true)] + Completion { + /// The type of shell to output a static completion script for. + shell: clap_complete::Shell, + }, + #[command(external_subcommand)] External(Vec), } @@ -176,10 +183,23 @@ fn run_command(command: Command, ctx: impl term::Context) -> Result<(), anyhow:: Command::Unseed(args) => unseed::run(args, ctx), Command::Watch(args) => watch::run(args, ctx), Command::Version { json } => write_version(json), + Command::Completion { shell } => { + print_completion(shell, &mut CliArgs::command()); + Ok(()) + } Command::External(args) => ExternalCommand::new(args).run(), } } +fn print_completion(generator: G, cmd: &mut clap::Command) { + clap_complete::generate( + generator, + cmd, + cmd.get_name().to_string(), + &mut io::stdout(), + ); +} + struct ExternalCommand { command: OsString, args: Vec,