git_revise/
cli.rs

1use clap::{ArgAction, ArgGroup, Parser};
2
3use crate::config;
4
5#[derive(Debug, Parser)]
6#[clap(
7    name = "git-revise",
8    about = "A command line utility for better commit"
9)]
10#[clap(version, author, about)]
11#[clap(group(
12    ArgGroup::new("ai_group")
13        .args(&["generate", "translate"])
14        .multiple(false)
15))]
16#[clap(group(
17    ArgGroup::new("conflict_group")
18        .args(&["message"])
19        .conflicts_with_all(&["generate", "translate", "path", "exclude", "include"])
20))]
21pub struct Cli {
22    /// Generate AI-assisted commit message
23    #[clap(short = 'g', long = "generate", action = ArgAction::SetTrue)]
24    pub generate: bool,
25
26    /// Translate commit message
27    #[clap(short = 't', long = "translate", num_args = 0..=1)]
28    pub translate: Option<String>,
29
30    /// Add files to staged area
31    #[clap(short = 'a', long = "add", num_args = 0.., default_missing_value = ".", value_delimiter = ' ')]
32    pub path: Vec<String>,
33
34    /// Exclude files from being added
35    #[clap(short = 'x', long = "exclude")]
36    pub exclude: Vec<String>,
37
38    /// Include files to be added
39    #[clap(short = 'i', long = "include")]
40    pub include: Vec<String>,
41
42    /// Specify commit message
43    #[clap(short = 'm', long = "message")]
44    pub message: Option<String>,
45    // /// Revise commit message
46    // #[clap(short = 'r', long = "repeat", action = ArgAction::SetTrue)]
47    // pub repeat: bool,
48}
49
50#[derive(Debug)]
51pub struct ReviseCommands {
52    pub ai: Option<AICommand>,
53    pub add: Vec<String>,
54    pub excludes: Vec<String>,
55    pub message: Option<String>,
56}
57
58#[derive(Debug, PartialEq, Clone)]
59pub enum AICommand {
60    Generate,
61    Translate(String),
62}
63
64// #[derive(Debug, Args)]
65// pub struct AddOptions {
66//     #[clap(name = "path", short = 'a', num_args = 0.., default_missing_value
67// = ".", value_delimiter = ' ')]     pub path: Vec<PathBuf>,
68//     #[clap(short = 'n', long = "dry-run")]
69//     pub dry_run: bool,
70//     #[clap(short = 'v', long = "verbose")]
71//     pub verbose: bool,
72//     #[clap(short, long)]
73//     pub update: bool,
74// }
75
76pub fn parse_command() -> ReviseCommands {
77    let cli = Cli::parse();
78    let cfg = config::get_config();
79
80    let mut combined_excludes: Vec<String> = cfg.exclude_files.clone();
81    combined_excludes.extend(cli.exclude.clone());
82
83    for path in &cli.include {
84        combined_excludes.retain(|item| item != path);
85    }
86
87    ReviseCommands {
88        ai: if cli.generate {
89            Some(AICommand::Generate)
90        } else {
91            cli.translate.map(AICommand::Translate)
92        },
93        add: cli.path,
94        excludes: combined_excludes,
95        message: cli.message,
96        // repeat: cli.repeat,
97    }
98}