diff --git a/Cargo.lock b/Cargo.lock index 08ac3bfc..ff09b72f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,5 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] name = "aho-corasick" version = "0.7.15" @@ -110,6 +112,15 @@ dependencies = [ "syn", ] +[[package]] +name = "clap_generate" +version = "3.0.0-beta.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adf420f8b687b628d2915ccfd43a660c437a170432e3fbcb66944e8717a0d68f" +dependencies = [ + "clap", +] + [[package]] name = "crossbeam-channel" version = "0.4.4" @@ -136,6 +147,7 @@ name = "deploy-rs" version = "0.1.0" dependencies = [ "clap", + "clap_generate", "flexi_logger", "fork", "futures-util", diff --git a/Cargo.toml b/Cargo.toml index 0ded1259..8ae5a230 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,6 +12,7 @@ edition = "2018" [dependencies] clap = "3.0.0-beta.2" +clap_generate = "3.0.0-beta.2" flexi_logger = "0.16" fork = "0.1" futures-util = "0.3.6" diff --git a/src/cli.rs b/src/cli.rs index 33eb5bbd..c2972936 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -6,7 +6,9 @@ use std::collections::HashMap; use std::io::{stdin, stdout, Write}; -use clap::{Clap, ArgMatches, FromArgMatches}; +use clap::{App, ArgEnum, Clap, IntoApp, ValueHint, ArgMatches, FromArgMatches}; +use clap_generate::generators::{Bash, Elvish, Fish, PowerShell, Zsh}; +use clap_generate::{generate, Generator}; use crate as deploy; @@ -18,16 +20,31 @@ use std::process::Stdio; use thiserror::Error; use tokio::process::Command; + +#[derive(ArgEnum, Debug, Clone, PartialEq)] +pub enum GeneratorChoice { + Bash, + Elvish, + Fish, + #[clap(name = "powershell")] + PowerShell, + Zsh, +} + /// Simple Rust rewrite of a simple Nix Flake deployment tool #[derive(Clap, Debug, Clone)] -#[clap(version = "1.0", author = "Serokell ")] +#[clap(name = "deploy", version = "1.0", author = "Serokell ")] pub struct Opts { + /// If provided, outputs the completion file for given shell + #[clap(long = "generate", arg_enum)] + generator: Option, + /// The flake to deploy - #[clap(group = "deploy")] + #[clap(group = "deploy", value_hint = ValueHint::DirPath)] target: Option, /// A list of flakes to deploy alternatively - #[clap(long, group = "deploy")] + #[clap(long, group = "deploy", value_hint = ValueHint::DirPath)] targets: Option>, /// Check signatures when using `nix copy` #[clap(short, long)] @@ -91,6 +108,10 @@ pub struct Opts { rollback_succeeded: Option, } +fn print_completions(app: &mut App) { + generate::(app, app.get_name().to_string(), &mut stdout()); +} + /// Returns if the available Nix installation supports flakes async fn test_flake_support() -> Result { debug!("Checking for flake support"); @@ -619,6 +640,19 @@ pub async fn run(args: Option<&ArgMatches>) -> Result<(), RunError> { deploy::LoggerType::Deploy, )?; + if let Some(generator) = opts.generator { + let mut app = Opts::into_app(); + info!("Generating completion file for {:?}...", generator); + match generator { + GeneratorChoice::Bash => print_completions::(&mut app), + GeneratorChoice::Elvish => print_completions::(&mut app), + GeneratorChoice::Fish => print_completions::(&mut app), + GeneratorChoice::PowerShell => print_completions::(&mut app), + GeneratorChoice::Zsh => print_completions::(&mut app), + }; + return Ok(()) + } + let deploys = opts .clone() .targets