auto_commit/cli/
mod.rs

1use clap::Parser;
2use clap_verbosity_flag::{InfoLevel, Verbosity};
3
4#[derive(Parser, Debug)]
5#[command(version)]
6#[command(name = "Auto Commit")]
7#[command(author = "Miguel Piedrafita <soy@miguelpiedrafita.com>")]
8#[command(about = "Automagically generate commit messages.", long_about = None)]
9pub struct Cli {
10    #[clap(flatten)]
11    pub verbose: Verbosity<InfoLevel>,
12
13    #[arg(
14        long = "dry-run",
15        help = "Output the generated message, but don't create a commit."
16    )]
17    pub dry_run: bool,
18
19    #[arg(
20        short,
21        long,
22        help = "Edit the generated commit message before committing."
23    )]
24    pub review: bool,
25
26    #[arg(short, long, help = "Don't ask for confirmation before committing.")]
27    pub force: bool,
28
29    #[arg(
30        long,
31        help = "Custom message format with placeholders like {title}, {description}, {prefix}, {emoji}, {scope}"
32    )]
33    pub format: Option<String>,
34}
35
36impl Cli {
37    pub fn parse_args() -> Self {
38        Self::parse()
39    }
40}
41
42#[cfg(test)]
43mod tests {
44    use super::*;
45
46    #[test]
47    fn test_parse_dry_run() {
48        let args = vec!["auto-commit", "--dry-run"];
49        let cli = Cli::parse_from(args);
50        assert!(cli.dry_run);
51        assert!(!cli.review);
52        assert!(!cli.force);
53        assert!(cli.format.is_none());
54    }
55
56    #[test]
57    fn test_parse_review() {
58        let args = vec!["auto-commit", "--review"];
59        let cli = Cli::parse_from(args);
60        assert!(!cli.dry_run);
61        assert!(cli.review);
62        assert!(!cli.force);
63    }
64
65    #[test]
66    fn test_parse_force() {
67        let args = vec!["auto-commit", "--force"];
68        let cli = Cli::parse_from(args);
69        assert!(!cli.dry_run);
70        assert!(!cli.review);
71        assert!(cli.force);
72    }
73
74    #[test]
75    fn test_parse_format() {
76        let args = vec!["auto-commit", "--format", "{prefix}: {title}"];
77        let cli = Cli::parse_from(args);
78        assert_eq!(cli.format, Some("{prefix}: {title}".to_string()));
79    }
80
81    #[test]
82    fn test_parse_multiple_options() {
83        let args = vec!["auto-commit", "--dry-run", "--force", "--format", "custom: {title}"];
84        let cli = Cli::parse_from(args);
85        assert!(cli.dry_run);
86        assert!(cli.force);
87        assert_eq!(cli.format, Some("custom: {title}".to_string()));
88    }
89
90    #[test]
91    fn test_parse_short_options() {
92        let args = vec!["auto-commit", "-r", "-f"];
93        let cli = Cli::parse_from(args);
94        assert!(cli.review);
95        assert!(cli.force);
96    }
97
98    #[test]
99    fn test_verbosity_levels() {
100        // Default verbosity
101        let args = vec!["auto-commit"];
102        let cli = Cli::parse_from(args);
103        assert_eq!(cli.verbose.log_level(), Some(log::Level::Info));
104
105        // Quiet mode
106        let args = vec!["auto-commit", "-q"];
107        let cli = Cli::parse_from(args);
108        assert_eq!(cli.verbose.log_level(), Some(log::Level::Warn));
109
110        // Very quiet mode
111        let args = vec!["auto-commit", "-qq"];
112        let cli = Cli::parse_from(args);
113        assert_eq!(cli.verbose.log_level(), Some(log::Level::Error));
114
115        // Verbose mode
116        let args = vec!["auto-commit", "-v"];
117        let cli = Cli::parse_from(args);
118        assert_eq!(cli.verbose.log_level(), Some(log::Level::Debug));
119
120        // Very verbose mode
121        let args = vec!["auto-commit", "-vv"];
122        let cli = Cli::parse_from(args);
123        assert_eq!(cli.verbose.log_level(), Some(log::Level::Trace));
124    }
125}