119625d8cSopenharmony_ciuse std::ffi::OsStr;
219625d8cSopenharmony_ciuse std::ffi::OsString;
319625d8cSopenharmony_ciuse std::path::PathBuf;
419625d8cSopenharmony_ci
519625d8cSopenharmony_ciuse clap::{Args, Parser, Subcommand, ValueEnum};
619625d8cSopenharmony_ci
719625d8cSopenharmony_ci/// A fictional versioning CLI
819625d8cSopenharmony_ci#[derive(Debug, Parser)] // requires `derive` feature
919625d8cSopenharmony_ci#[command(name = "git")]
1019625d8cSopenharmony_ci#[command(about = "A fictional versioning CLI", long_about = None)]
1119625d8cSopenharmony_cistruct Cli {
1219625d8cSopenharmony_ci    #[command(subcommand)]
1319625d8cSopenharmony_ci    command: Commands,
1419625d8cSopenharmony_ci}
1519625d8cSopenharmony_ci
1619625d8cSopenharmony_ci#[derive(Debug, Subcommand)]
1719625d8cSopenharmony_cienum Commands {
1819625d8cSopenharmony_ci    /// Clones repos
1919625d8cSopenharmony_ci    #[command(arg_required_else_help = true)]
2019625d8cSopenharmony_ci    Clone {
2119625d8cSopenharmony_ci        /// The remote to clone
2219625d8cSopenharmony_ci        remote: String,
2319625d8cSopenharmony_ci    },
2419625d8cSopenharmony_ci    /// Compare two commits
2519625d8cSopenharmony_ci    Diff {
2619625d8cSopenharmony_ci        #[arg(value_name = "COMMIT")]
2719625d8cSopenharmony_ci        base: Option<OsString>,
2819625d8cSopenharmony_ci        #[arg(value_name = "COMMIT")]
2919625d8cSopenharmony_ci        head: Option<OsString>,
3019625d8cSopenharmony_ci        #[arg(last = true)]
3119625d8cSopenharmony_ci        path: Option<OsString>,
3219625d8cSopenharmony_ci        #[arg(
3319625d8cSopenharmony_ci            long,
3419625d8cSopenharmony_ci            require_equals = true,
3519625d8cSopenharmony_ci            value_name = "WHEN",
3619625d8cSopenharmony_ci            num_args = 0..=1,
3719625d8cSopenharmony_ci            default_value_t = ColorWhen::Auto,
3819625d8cSopenharmony_ci            default_missing_value = "always",
3919625d8cSopenharmony_ci            value_enum
4019625d8cSopenharmony_ci        )]
4119625d8cSopenharmony_ci        color: ColorWhen,
4219625d8cSopenharmony_ci    },
4319625d8cSopenharmony_ci    /// pushes things
4419625d8cSopenharmony_ci    #[command(arg_required_else_help = true)]
4519625d8cSopenharmony_ci    Push {
4619625d8cSopenharmony_ci        /// The remote to target
4719625d8cSopenharmony_ci        remote: String,
4819625d8cSopenharmony_ci    },
4919625d8cSopenharmony_ci    /// adds things
5019625d8cSopenharmony_ci    #[command(arg_required_else_help = true)]
5119625d8cSopenharmony_ci    Add {
5219625d8cSopenharmony_ci        /// Stuff to add
5319625d8cSopenharmony_ci        #[arg(required = true)]
5419625d8cSopenharmony_ci        path: Vec<PathBuf>,
5519625d8cSopenharmony_ci    },
5619625d8cSopenharmony_ci    Stash(StashArgs),
5719625d8cSopenharmony_ci    #[command(external_subcommand)]
5819625d8cSopenharmony_ci    External(Vec<OsString>),
5919625d8cSopenharmony_ci}
6019625d8cSopenharmony_ci
6119625d8cSopenharmony_ci#[derive(ValueEnum, Copy, Clone, Debug, PartialEq, Eq)]
6219625d8cSopenharmony_cienum ColorWhen {
6319625d8cSopenharmony_ci    Always,
6419625d8cSopenharmony_ci    Auto,
6519625d8cSopenharmony_ci    Never,
6619625d8cSopenharmony_ci}
6719625d8cSopenharmony_ci
6819625d8cSopenharmony_ciimpl std::fmt::Display for ColorWhen {
6919625d8cSopenharmony_ci    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
7019625d8cSopenharmony_ci        self.to_possible_value()
7119625d8cSopenharmony_ci            .expect("no values are skipped")
7219625d8cSopenharmony_ci            .get_name()
7319625d8cSopenharmony_ci            .fmt(f)
7419625d8cSopenharmony_ci    }
7519625d8cSopenharmony_ci}
7619625d8cSopenharmony_ci
7719625d8cSopenharmony_ci#[derive(Debug, Args)]
7819625d8cSopenharmony_ci#[command(args_conflicts_with_subcommands = true)]
7919625d8cSopenharmony_cistruct StashArgs {
8019625d8cSopenharmony_ci    #[command(subcommand)]
8119625d8cSopenharmony_ci    command: Option<StashCommands>,
8219625d8cSopenharmony_ci
8319625d8cSopenharmony_ci    #[command(flatten)]
8419625d8cSopenharmony_ci    push: StashPushArgs,
8519625d8cSopenharmony_ci}
8619625d8cSopenharmony_ci
8719625d8cSopenharmony_ci#[derive(Debug, Subcommand)]
8819625d8cSopenharmony_cienum StashCommands {
8919625d8cSopenharmony_ci    Push(StashPushArgs),
9019625d8cSopenharmony_ci    Pop { stash: Option<String> },
9119625d8cSopenharmony_ci    Apply { stash: Option<String> },
9219625d8cSopenharmony_ci}
9319625d8cSopenharmony_ci
9419625d8cSopenharmony_ci#[derive(Debug, Args)]
9519625d8cSopenharmony_cistruct StashPushArgs {
9619625d8cSopenharmony_ci    #[arg(short, long)]
9719625d8cSopenharmony_ci    message: Option<String>,
9819625d8cSopenharmony_ci}
9919625d8cSopenharmony_ci
10019625d8cSopenharmony_cifn main() {
10119625d8cSopenharmony_ci    let args = Cli::parse();
10219625d8cSopenharmony_ci
10319625d8cSopenharmony_ci    match args.command {
10419625d8cSopenharmony_ci        Commands::Clone { remote } => {
10519625d8cSopenharmony_ci            println!("Cloning {remote}");
10619625d8cSopenharmony_ci        }
10719625d8cSopenharmony_ci        Commands::Diff {
10819625d8cSopenharmony_ci            mut base,
10919625d8cSopenharmony_ci            mut head,
11019625d8cSopenharmony_ci            mut path,
11119625d8cSopenharmony_ci            color,
11219625d8cSopenharmony_ci        } => {
11319625d8cSopenharmony_ci            if path.is_none() {
11419625d8cSopenharmony_ci                path = head;
11519625d8cSopenharmony_ci                head = None;
11619625d8cSopenharmony_ci                if path.is_none() {
11719625d8cSopenharmony_ci                    path = base;
11819625d8cSopenharmony_ci                    base = None;
11919625d8cSopenharmony_ci                }
12019625d8cSopenharmony_ci            }
12119625d8cSopenharmony_ci            let base = base
12219625d8cSopenharmony_ci                .as_deref()
12319625d8cSopenharmony_ci                .map(|s| s.to_str().unwrap())
12419625d8cSopenharmony_ci                .unwrap_or("stage");
12519625d8cSopenharmony_ci            let head = head
12619625d8cSopenharmony_ci                .as_deref()
12719625d8cSopenharmony_ci                .map(|s| s.to_str().unwrap())
12819625d8cSopenharmony_ci                .unwrap_or("worktree");
12919625d8cSopenharmony_ci            let path = path.as_deref().unwrap_or_else(|| OsStr::new(""));
13019625d8cSopenharmony_ci            println!(
13119625d8cSopenharmony_ci                "Diffing {}..{} {} (color={})",
13219625d8cSopenharmony_ci                base,
13319625d8cSopenharmony_ci                head,
13419625d8cSopenharmony_ci                path.to_string_lossy(),
13519625d8cSopenharmony_ci                color
13619625d8cSopenharmony_ci            );
13719625d8cSopenharmony_ci        }
13819625d8cSopenharmony_ci        Commands::Push { remote } => {
13919625d8cSopenharmony_ci            println!("Pushing to {remote}");
14019625d8cSopenharmony_ci        }
14119625d8cSopenharmony_ci        Commands::Add { path } => {
14219625d8cSopenharmony_ci            println!("Adding {path:?}");
14319625d8cSopenharmony_ci        }
14419625d8cSopenharmony_ci        Commands::Stash(stash) => {
14519625d8cSopenharmony_ci            let stash_cmd = stash.command.unwrap_or(StashCommands::Push(stash.push));
14619625d8cSopenharmony_ci            match stash_cmd {
14719625d8cSopenharmony_ci                StashCommands::Push(push) => {
14819625d8cSopenharmony_ci                    println!("Pushing {push:?}");
14919625d8cSopenharmony_ci                }
15019625d8cSopenharmony_ci                StashCommands::Pop { stash } => {
15119625d8cSopenharmony_ci                    println!("Popping {stash:?}");
15219625d8cSopenharmony_ci                }
15319625d8cSopenharmony_ci                StashCommands::Apply { stash } => {
15419625d8cSopenharmony_ci                    println!("Applying {stash:?}");
15519625d8cSopenharmony_ci                }
15619625d8cSopenharmony_ci            }
15719625d8cSopenharmony_ci        }
15819625d8cSopenharmony_ci        Commands::External(args) => {
15919625d8cSopenharmony_ci            println!("Calling out to {:?} with {:?}", &args[0], &args[1..]);
16019625d8cSopenharmony_ci        }
16119625d8cSopenharmony_ci    }
16219625d8cSopenharmony_ci
16319625d8cSopenharmony_ci    // Continued program logic goes here...
16419625d8cSopenharmony_ci}
165