use std::path::PathBuf; use std::str::FromStr; use clap::{Parser, ValueEnum}; use serde::Deserialize; #[derive(Parser, Debug)] #[command(name = "mov-renamarr", version, about = "Rename movie files into Radarr-compatible naming")] pub struct Cli { #[arg(long, value_name = "DIR")] pub input: PathBuf, #[arg(long, value_name = "DIR")] pub output: Option, #[arg(long, value_name = "PATH")] pub config: Option, #[arg(long, value_enum)] pub provider: Option, #[arg(long = "api-key-omdb")] pub api_key_omdb: Option, #[arg(long = "api-key-tmdb")] pub api_key_tmdb: Option, #[arg(long, value_name = "PATH")] pub cache: Option, #[arg(long)] pub refresh_cache: bool, #[arg(long)] pub dry_run: bool, #[arg(long = "move", conflicts_with = "rename_in_place")] pub move_files: bool, #[arg(long = "rename-in-place", conflicts_with = "move_files")] pub rename_in_place: bool, #[arg(long)] pub interactive: bool, #[arg( long, value_name = "PATH", num_args = 0..=1, default_missing_value = "__DEFAULT__" )] pub report: Option, #[arg(long, value_enum)] pub report_format: Option, #[arg(long)] pub sidecar_notes: bool, #[arg(long)] pub sidecars: bool, #[arg(long)] pub overwrite: bool, #[arg(long)] pub suffix: bool, #[arg(long)] pub min_score: Option, #[arg(long)] pub include_id: bool, #[arg(long, value_name = "LIST")] pub quality_tags: Option, #[arg(long, value_enum)] pub color: Option, #[arg(long, value_enum)] pub llm_mode: Option, #[arg(long, value_name = "URL")] pub llm_endpoint: Option, #[arg(long, value_name = "NAME")] pub llm_model: Option, #[arg(long, value_name = "SECONDS")] pub llm_timeout: Option, #[arg(long, value_name = "N")] pub llm_max_tokens: Option, #[arg(long, value_parser = parse_jobs_arg)] pub jobs: Option, #[arg(long, value_parser = parse_jobs_arg)] pub net_jobs: Option, #[arg(long, alias = "offline")] pub no_lookup: bool, #[arg(long)] pub verbose: bool, } #[derive(Clone, Debug, ValueEnum, Eq, PartialEq, Deserialize)] #[serde(rename_all = "lowercase")] pub enum ProviderChoice { Auto, Omdb, Tmdb, Both, } #[derive(Clone, Debug, ValueEnum, Eq, PartialEq, Deserialize)] #[serde(rename_all = "lowercase")] pub enum ReportFormat { Text, Json, Csv, } #[derive(Clone, Debug, ValueEnum, Eq, PartialEq, Deserialize)] #[serde(rename_all = "lowercase")] pub enum ColorMode { Auto, Always, Never, } #[derive(Clone, Debug, ValueEnum, Eq, PartialEq, Deserialize)] #[serde(rename_all = "lowercase")] pub enum LlmMode { Off, Parse, Assist, } #[derive(Clone, Debug, Eq, PartialEq)] pub enum JobsArg { Auto, Fixed(usize), } fn parse_jobs_arg(value: &str) -> Result { if value.eq_ignore_ascii_case("auto") { return Ok(JobsArg::Auto); } let parsed = usize::from_str(value).map_err(|_| "jobs must be an integer or 'auto'".to_string())?; if parsed == 0 { return Err("jobs must be >= 1".to_string()); } Ok(JobsArg::Fixed(parsed)) }