use crate::consts::{TOOL_NAME, TOOL_VERSION};
use clap::builder::styling::{AnsiColor, Effects, Styles};
use clap::{Args, Parser, Subcommand, ValueEnum};
use clap_complete_command::Shell;
use std::path::PathBuf;
macro_rules! env_var {
($name:literal) => {
concat!("KEYCLI_", $name)
};
}
const STYLES: Styles = Styles::styled()
.header(AnsiColor::Green.on_default().effects(Effects::BOLD))
.usage(AnsiColor::Green.on_default().effects(Effects::BOLD))
.literal(AnsiColor::Cyan.on_default().effects(Effects::BOLD))
.placeholder(AnsiColor::Cyan.on_default());
#[derive(Parser)]
#[command(
name = TOOL_NAME,
version = TOOL_VERSION,
about = "A env manager which stores your secrets in your OS keyring",
long_about = None,
styles = STYLES,
after_help = "Examples:
# Create a .keycli.conf from a keycli.tpl and populate your keyring
keycli init
# Create a .keycli.conf from scratch and populate your keyring
keycli init -a my_app -s PASS -s PASS2 -s PASS3:another_app
# Run a shell with declared env vars
keycli shell
# Load env vars
eval $(keycli load) # Or keycli-load if you installed the alias
# Unload env vars
eval $(keycli unload) # Or keycli-unload if you installed the alias
# Save vars without .keycli.conf file
keycli save -a custom_app -s ZOZO -s ZAZA
# Load vars without .keycli.conf file
keycli load -a custom_app -s ZOZO -s ZAZA
# Install completions and aliases
keycli alias zsh >> ~/.zshrc
keycli completion zsh > ~/.zfunc/_keycli
keycli completion zsh keycli-load > ~/.zfunc/_keycli-load
keycli completion zsh keycli-unload > ~/.zfunc/_keycli-unload
",
)]
pub struct Cli {
#[command(flatten)]
pub global: GlobalArgs,
#[command(subcommand)]
pub command: Commands,
}
#[derive(Args)]
pub struct GlobalArgs {
#[arg(short, long, global = true, env = env_var!("VERBOSE"))]
pub verbose: bool,
}
#[derive(Args)]
pub struct CommonOptions {
#[arg(short, long, env = env_var!("EXTRA_SECRETS"), conflicts_with = "secrets")]
pub extra_secrets: Vec<String>,
#[arg(short, long, env = env_var!("SECRETS"), conflicts_with_all = ["extra_secrets", "config"])]
pub secrets: Vec<String>,
#[arg(short, long, env = env_var!("APP_NAME"))]
pub app_name: Option<String>,
}
#[derive(Args)]
pub struct AllCommonOptions {
#[command(flatten)]
pub common: CommonOptions,
#[arg(short, long, env = env_var!("CONFIG"), conflicts_with = "secrets")]
pub config: Option<PathBuf>,
#[arg(short = 't', long = "no-check-template", env = env_var!("CHECK_TEMPLATE"), default_value = "true", action = clap::ArgAction::SetFalse)]
pub check_tpl: bool,
}
#[derive(Args)]
pub struct SaveArgs {
#[arg(short, long = "no-interactive", env = env_var!("INTERACTIVE"), default_value = "true", action = clap::ArgAction::SetFalse)]
pub interactive: bool,
#[arg(short, long, env = env_var!("FORCE"), default_value = "false", action = clap::ArgAction::SetTrue)]
pub force: bool,
}
#[derive(Args)]
pub struct LoadArgs {
#[arg(short, long = "no-overwrite", env = env_var!("OVERWRITE"), default_value = "true", action = clap::ArgAction::SetFalse)]
pub overwrite: bool,
}
#[derive(ValueEnum, Clone)]
pub enum AliasCommand {
#[value(name = "keycli-load")]
Load,
#[value(name = "keycli-unload")]
Unload,
}
#[derive(ValueEnum, Clone)]
pub enum OutputFormat {
#[value(name = "shell-script")]
ShellScript,
#[value(name = "json")]
Json,
}
#[derive(Subcommand)]
pub enum Commands {
Load {
#[command(flatten)]
all_common: AllCommonOptions,
#[command(flatten)]
load: LoadArgs,
#[arg(short = 'f', long = "output-format", env = env_var!("OUTPUT_FORMAT"), default_value = "shell-script")]
output_format: OutputFormat,
},
Unload {
#[command(flatten)]
all_common: AllCommonOptions,
},
List {
#[command(flatten)]
all_common: AllCommonOptions,
},
Save {
#[command(flatten)]
all_common: AllCommonOptions,
#[command(flatten)]
save: SaveArgs,
},
Clear {
#[command(flatten)]
all_common: AllCommonOptions,
#[arg(short, long = "no-interactive", env = env_var!("INTERACTIVE"), default_value = "true", action = clap::ArgAction::SetFalse)]
interactive: bool,
},
Exec {
#[command(flatten)]
all_common: AllCommonOptions,
#[command(flatten)]
load: LoadArgs,
binary: String,
#[arg(trailing_var_arg = true)]
args: Vec<String>,
},
Shell {
#[command(flatten)]
all_common: AllCommonOptions,
#[command(flatten)]
load: LoadArgs,
},
Init {
#[command(flatten)]
common: CommonOptions,
#[command(flatten)]
save: SaveArgs,
#[arg(short, long, env = env_var!("CONFIG"), default_value = ".keycli.conf")]
config: PathBuf,
#[arg(short, long, env = env_var!("TEMPLATE"), default_value = "keycli.tpl")]
template: PathBuf,
},
Alias {
shell: Shell,
},
Completion {
shell: Shell,
#[arg(value_enum)]
alias: Option<AliasCommand>,
},
}