diff --git a/src/porcelain/main.rs b/src/porcelain/main.rs index aeb89458d83..a622571485e 100644 --- a/src/porcelain/main.rs +++ b/src/porcelain/main.rs @@ -3,8 +3,8 @@ use std::sync::{ Arc, }; -use anyhow::Result; -use clap::Parser; +use anyhow::{anyhow, Result}; +use clap::{CommandFactory, Parser}; use gitoxide::shared::pretty::prepare_and_run; use gitoxide_core as core; @@ -169,6 +169,21 @@ pub fn main() -> Result<()> { ) } }, + Subcommands::Completions { shell, out_dir } => { + let mut app = Args::command(); + + let shell = shell + .or_else(clap_complete::Shell::from_env) + .ok_or_else(|| anyhow!("The shell could not be derived from the environment"))?; + + let bin_name = app.get_name().to_owned(); + if let Some(out_dir) = out_dir { + clap_complete::generate_to(shell, &mut app, bin_name, &out_dir)?; + } else { + clap_complete::generate(shell, &mut app, bin_name, &mut std::io::stdout()); + } + Ok(()) + } }?; Ok(()) } diff --git a/src/porcelain/options.rs b/src/porcelain/options.rs index 263779dec11..708ffdd1417 100644 --- a/src/porcelain/options.rs +++ b/src/porcelain/options.rs @@ -1,7 +1,8 @@ +use clap_complete::Shell; use std::path::PathBuf; #[derive(Debug, clap::Parser)] -#[clap(about = "The rusty git", version = option_env!("GIX_VERSION"))] +#[clap(name = "ein", about = "The rusty git", version = option_env!("GIX_VERSION"))] #[clap(subcommand_required = true)] pub struct Args { /// Do not display verbose messages and progress information @@ -39,6 +40,15 @@ pub enum Subcommands { /// A selection of useful tools #[clap(subcommand)] Tool(ToolCommands), + /// Generate shell completions to stdout or a directory. + #[clap(visible_alias = "generate-completions", visible_alias = "shell-completions")] + Completions { + /// The shell to generate completions for. Otherwise it's derived from the environment. + #[clap(long, short)] + shell: Option, + /// The output directory in case multiple files are generated. If not provided, will write to stdout. + out_dir: Option, + }, #[cfg(debug_assertions)] Panic, }