use clap::{Parser, ValueEnum};
use clap_complete::Shell;
use serde::{Deserialize, Serialize};
use std::path::PathBuf;
use crate::config::Config;
#[derive(Parser, Clone, Debug)]
#[command(
name = "rskiller",
about = "Find and clean Rust project build artifacts and caches"
)]
pub struct Cli {
#[arg(short, long)]
pub directory: Option<PathBuf>,
#[arg(short = 'f', long)]
pub full: bool,
#[arg(short, long)]
pub target: Option<String>,
#[arg(short, long, value_enum)]
pub sort: Option<SortBy>,
#[arg(long)]
pub gb: bool,
#[arg(short = 'E', long)]
pub exclude: Option<String>,
#[arg(short = 'x', long)]
pub exclude_hidden: bool,
#[arg(short = 'e', long)]
pub hide_errors: bool,
#[arg(short = 'D', long)]
pub delete_all: bool,
#[arg(long)]
pub dry_run: bool,
#[arg(short, long)]
pub list_only: bool,
#[arg(long)]
pub include_cargo_cache: bool,
#[arg(short = 'c', long, value_enum)]
pub color: Option<Color>,
#[arg(long)]
pub no_check_update: bool,
#[arg(long)]
pub config: Option<PathBuf>,
#[arg(long)]
pub print_config: bool,
#[arg(long)]
pub init_config: bool,
#[arg(long, value_enum, default_value = "toml")]
pub format: ConfigFormat,
#[arg(long)]
pub global: bool,
#[arg(long)]
pub validate_config: Option<PathBuf>,
#[clap(long)]
pub config_info: bool,
#[clap(long, value_enum)]
pub completion: Option<Shell>,
}
#[derive(ValueEnum, Clone, Debug, Serialize, Deserialize, PartialEq)]
pub enum SortBy {
Size,
Path,
LastMod,
}
#[derive(ValueEnum, Clone, Debug, Serialize, Deserialize, PartialEq)]
pub enum Color {
Blue,
Cyan,
Magenta,
White,
Red,
Yellow,
}
#[derive(ValueEnum, Clone, Debug)]
pub enum ConfigFormat {
Toml,
Json,
}
impl From<ConfigFormat> for crate::config::ConfigFormat {
fn from(format: ConfigFormat) -> Self {
match format {
ConfigFormat::Toml => crate::config::ConfigFormat::Toml,
ConfigFormat::Json => crate::config::ConfigFormat::Json,
}
}
}
impl Cli {
pub fn from_config_and_args(config: Config) -> Self {
let mut cli = Self::parse();
if cli.directory.is_none() {
cli.directory = config.search.directory;
}
if !cli.full && config.search.full.unwrap_or(false) {
cli.full = true;
}
if cli.target.is_none() {
cli.target = config.search.target;
}
if cli.sort.is_none() {
cli.sort = config.output.sort;
}
if !cli.gb && config.output.gb.unwrap_or(false) {
cli.gb = true;
}
if cli.exclude.is_none() && config.search.exclude.is_some() {
cli.exclude = config.search.exclude.map(|dirs| dirs.join(","));
}
if !cli.exclude_hidden && config.search.exclude_hidden.unwrap_or(false) {
cli.exclude_hidden = true;
}
if !cli.hide_errors && config.output.hide_errors.unwrap_or(false) {
cli.hide_errors = true;
}
if !cli.delete_all && config.behavior.delete_all.unwrap_or(false) {
cli.delete_all = true;
}
if !cli.dry_run && config.behavior.dry_run.unwrap_or(false) {
cli.dry_run = true;
}
if !cli.list_only && config.behavior.list_only.unwrap_or(false) {
cli.list_only = true;
}
if !cli.include_cargo_cache && config.search.include_cargo_cache.unwrap_or(false) {
cli.include_cargo_cache = true;
}
if cli.color.is_none() {
cli.color = config.output.color;
}
if !cli.no_check_update && config.behavior.no_check_update.unwrap_or(false) {
cli.no_check_update = true;
}
cli
}
pub fn get_search_directory(&self) -> PathBuf {
if self.full {
dirs::home_dir().unwrap_or_else(|| PathBuf::from("/"))
} else {
self.directory.clone().unwrap_or_else(|| {
dirs::home_dir().unwrap_or_else(|| PathBuf::from("."))
})
}
}
pub fn get_excluded_dirs(&self) -> Vec<String> {
self.exclude
.as_ref()
.map(|s| {
s.split(',')
.map(|dir| dir.trim().to_string())
.collect()
})
.unwrap_or_default()
}
pub fn get_target_name(&self) -> String {
self.target.clone().unwrap_or_else(|| "target".to_string())
}
pub fn get_sort_by(&self) -> SortBy {
self.sort.clone().unwrap_or(SortBy::Size)
}
pub fn get_color(&self) -> Color {
self.color.clone().unwrap_or(Color::Blue)
}
}