use clap::{Parser, Subcommand, ValueHint};
use crate::{cmds, constants, model, path};
#[derive(Clone, Debug, Default, Parser)]
#[command(name = constants::GARDEN)]
#[command(author, version, about, long_about = None)]
pub struct MainOptions {
#[arg(
long,
require_equals = true,
num_args = 0..=1,
default_value_t = model::ColorMode::Auto,
default_missing_value = "true",
value_name = "WHEN",
value_parser = model::ColorMode::parse_from_str,
)]
pub color: model::ColorMode,
#[arg(long, short, value_hint = ValueHint::FilePath)]
pub config: Option<std::path::PathBuf>,
#[arg(long, short = 'C', value_hint = ValueHint::DirPath)]
pub chdir: Option<std::path::PathBuf>,
#[arg(long, short, action = clap::ArgAction::Append)]
pub debug: Vec<String>,
#[arg(long, short = 'D')]
pub define: Vec<String>,
#[arg(long, short, value_hint = ValueHint::DirPath)]
pub root: Option<std::path::PathBuf>,
#[arg(short, long)]
pub quiet: bool,
#[arg(short, long, action = clap::ArgAction::Count)]
pub verbose: u8,
#[command(subcommand)]
pub command: Command,
}
impl MainOptions {
pub fn new() -> Self {
Self::default()
}
}
pub fn debug_level(debug: &[String], name: &str) -> u8 {
debug.iter().filter(|&x| x == name).count() as u8
}
pub trait GardenOptions {
fn get_chdir(&self) -> &Option<std::path::PathBuf>;
fn get_color_mut(&mut self) -> &mut model::ColorMode;
fn get_config(&self) -> &Option<std::path::PathBuf>;
fn set_config(&mut self, path: std::path::PathBuf);
fn get_debug(&self) -> &[String];
fn get_root(&self) -> &Option<std::path::PathBuf>;
fn set_root(&mut self, path: std::path::PathBuf);
fn update(&mut self) {
self.get_color_mut().update();
if let Some(ref config) = self.get_config() {
if config.exists() {
self.set_config(path::abspath(config));
}
}
if let Some(ref root) = self.get_root() {
self.set_root(path::abspath(root));
}
if let Some(ref chdir) = self.get_chdir() {
if let Err(err) = std::env::set_current_dir(chdir) {
error!("could not chdir to {:?}: {}", chdir, err);
}
}
}
fn debug_level(&self, name: &str) -> u8 {
debug_level(self.get_debug(), name)
}
}
impl GardenOptions for MainOptions {
fn get_color_mut(&mut self) -> &mut model::ColorMode {
&mut self.color
}
fn get_config(&self) -> &Option<std::path::PathBuf> {
&self.config
}
fn set_config(&mut self, path: std::path::PathBuf) {
self.config = Some(path);
}
fn get_chdir(&self) -> &Option<std::path::PathBuf> {
&self.chdir
}
fn get_debug(&self) -> &[String] {
&self.debug
}
fn get_root(&self) -> &Option<std::path::PathBuf> {
&self.root
}
fn set_root(&mut self, root: std::path::PathBuf) {
self.root = Some(root);
}
}
#[derive(Default, Clone, Debug, Parser)]
pub struct Arguments {
#[arg(allow_hyphen_values = true)]
pub args: Vec<String>,
}
#[derive(Clone, Debug, Subcommand)]
pub enum Command {
Cmd(cmds::cmd::CmdOptions),
Completion(cmds::completion::CompletionOptions),
#[command(external_subcommand)]
Custom(Vec<String>),
Eval(cmds::eval::EvalOptions),
Exec(cmds::exec::ExecOptions),
Grow(cmds::grow::GrowOptions),
Gui(Arguments),
Init(cmds::init::InitOptions),
#[command(name = "ls")]
List(cmds::list::ListOptions),
Plant(cmds::plant::PlantOptions),
Prune(cmds::prune::PruneOptions),
#[command(alias = "sh")]
Shell(cmds::shell::ShellOptions),
}
impl std::default::Default for Command {
fn default() -> Self {
Command::Custom(vec![])
}
}
pub fn verbose_string(verbose: u8) -> String {
let mut verbose_str = "-".to_string();
verbose_str.reserve((verbose + 1) as usize);
for _ in 0..verbose {
verbose_str.push('v');
}
verbose_str
}