image_optimizer/cli/
cli_args.rs

1use clap::Parser;
2use std::path::PathBuf;
3
4/// Command-line interface configuration for the image optimizer tool.
5///
6/// This struct defines all available command-line arguments and flags for the image optimization
7/// tool. It uses the `clap` crate for parsing and validation of command-line arguments.
8///
9/// ## Examples
10///
11/// ```rust
12/// use image_optimizer::cli::Cli;
13/// use clap::Parser;
14///
15/// // Parse CLI arguments
16/// let cli = Cli::parse();
17/// ```
18#[derive(Parser)]
19#[command(name = "image-optimizer")]
20#[command(about = "CLI tool for optimizing images (JPEG, PNG, WebP)")]
21#[command(long_about = None)]
22#[command(version = env!("CARGO_PKG_VERSION"))]
23#[allow(clippy::struct_excessive_bools)]
24pub struct Cli {
25    /// Input directory or file to process
26    #[arg(short, long)]
27    pub input: Option<PathBuf>,
28
29    /// Output directory (if not specified, optimizes in place)
30    #[arg(short, long)]
31    pub output: Option<PathBuf>,
32
33    /// Create backup files (.bak)
34    #[arg(long)]
35    pub backup: bool,
36
37    /// Use lossless compression
38    #[arg(long)]
39    pub lossless: bool,
40
41    /// JPEG quality (1-100), ignored if lossless is set
42    #[arg(short, long, default_value = "85")]
43    pub quality: u8,
44
45    /// Recursively scan subdirectories
46    #[arg(short, long)]
47    pub recursive: bool,
48
49    /// Maximum size for the longer edge (resizes if larger)
50    #[arg(long)]
51    pub max_size: Option<u32>,
52
53    /// Update to the latest version
54    #[arg(long)]
55    pub update: bool,
56}
57
58#[cfg(test)]
59mod tests {
60    use super::*;
61    use clap::CommandFactory;
62
63    #[test]
64    fn test_cli_defaults() {
65        let cli = Cli::parse_from(&["image-optimizer"]);
66        assert_eq!(cli.input, None);
67        assert_eq!(cli.output, None);
68        assert!(!cli.backup);
69        assert!(!cli.lossless);
70        assert_eq!(cli.quality, 85);
71        assert!(!cli.recursive);
72        assert_eq!(cli.max_size, None);
73        assert!(!cli.update);
74    }
75
76    #[test]
77    fn test_cli_with_input() {
78        let cli = Cli::parse_from(&["image-optimizer", "-i", "/path/to/images"]);
79        assert_eq!(cli.input, Some(PathBuf::from("/path/to/images")));
80    }
81
82    #[test]
83    fn test_cli_with_all_flags() {
84        let cli = Cli::parse_from(&[
85            "image-optimizer",
86            "-i",
87            "/input",
88            "-o",
89            "/output",
90            "--backup",
91            "--lossless",
92            "-q",
93            "90",
94            "--recursive",
95            "--max-size",
96            "1024",
97            "--update",
98        ]);
99
100        assert_eq!(cli.input, Some(PathBuf::from("/input")));
101        assert_eq!(cli.output, Some(PathBuf::from("/output")));
102        assert!(cli.backup);
103        assert!(cli.lossless);
104        assert_eq!(cli.quality, 90);
105        assert!(cli.recursive);
106        assert_eq!(cli.max_size, Some(1024));
107        assert!(cli.update);
108    }
109
110    #[test]
111    fn test_cli_quality_bounds() {
112        let cli = Cli::parse_from(&["image-optimizer", "-q", "1"]);
113        assert_eq!(cli.quality, 1);
114
115        let cli = Cli::parse_from(&["image-optimizer", "-q", "100"]);
116        assert_eq!(cli.quality, 100);
117    }
118
119    #[test]
120    fn test_cli_help_generation() {
121        let mut cmd = Cli::command();
122        let help = cmd.render_help();
123        assert!(help.to_string().contains("CLI tool for optimizing images"));
124    }
125}