Skip to main content

git_pincer/
cli.rs

1//! CLI definition and subcommand dispatch.
2
3use std::path::PathBuf;
4
5use anyhow::Result;
6use clap::{Parser, Subcommand};
7
8use crate::commands;
9
10/// Program command line
11#[derive(Debug, Parser)]
12#[command(
13    version,
14    about,
15    long_about = None
16)]
17pub struct Cli {
18    /// The specific subcommand to be executed
19    #[command(subcommand)]
20    pub command: Option<Commands>,
21    /// The Git repository path (default is current directory)
22    #[arg(short = 'C', long = "repo", global = true, value_name = "PATH")]
23    pub repo: Option<PathBuf>,
24    /// Echo executed git command
25    #[arg(short, long, global = true)]
26    pub verbose: bool,
27    /// theme
28    #[arg(long, global = true, value_enum, default_value = "auto")]
29    pub theme: ThemeArg,
30    /// UI language
31    #[arg(long, global = true, value_enum, default_value = "auto")]
32    pub lang: LangArg,
33}
34
35/// 界面语言选择。
36#[derive(Debug, Clone, Copy, PartialEq, Eq, clap::ValueEnum)]
37pub enum LangArg {
38    /// 按系统 locale 自动选择(zh 前缀用中文,其余英文)
39    Auto,
40    /// 中文
41    Zh,
42    /// 英文
43    En,
44}
45
46/// 界面主题选择。
47#[derive(Debug, Clone, Copy, PartialEq, Eq, clap::ValueEnum)]
48pub enum ThemeArg {
49    /// 按终端环境自动选择(读 COLORFGBG,检测不到用深色)
50    Auto,
51    /// 深色(Tokyo Night)
52    Dark,
53    /// 浅色(Maple Light,适配浅色终端背景)
54    Light,
55}
56
57/// 支持的子命令。
58#[derive(Debug, Subcommand)]
59pub enum Commands {
60    /// Run `git merge` and take over conflicts if any
61    Merge(commands::run::MergeArgs),
62    /// Run `git rebase`, looping through every conflicted round
63    Rebase(commands::run::RebaseArgs),
64    /// Run `git pull` (all arguments are passed through)
65    Pull(commands::run::PullArgs),
66    /// Run `git cherry-pick` (all arguments are passed through)
67    CherryPick(commands::run::CherryPickArgs),
68    /// Run `git revert` (all arguments are passed through)
69    Revert(commands::run::RevertArgs),
70    /// Resolve a single conflict-marked file, no git required
71    File(commands::file::FileArgs),
72    /// Abort the operation in progress (merge / rebase / cherry-pick / revert / am)
73    Abort,
74}
75
76impl Cli {
77    /// Distribute and execute the selected subcommands.
78    pub fn run(self) -> Result<()> {
79        crate::i18n::init(match self.lang {
80            LangArg::Zh => crate::i18n::Lang::Zh,
81            LangArg::En => crate::i18n::Lang::En,
82            LangArg::Auto => crate::i18n::detect(),
83        });
84        let verbose = self.verbose;
85        let dir = self.repo.unwrap_or_else(|| PathBuf::from("."));
86        let light = match self.theme {
87            ThemeArg::Light => true,
88            ThemeArg::Dark => false,
89            ThemeArg::Auto => crate::ui::detect_light(),
90        };
91        match self.command {
92            None => commands::menu::run(verbose, &dir, light),
93            Some(Commands::Merge(args)) => commands::run::merge(args, verbose, &dir, light),
94            Some(Commands::Rebase(args)) => commands::run::rebase(args, verbose, &dir, light),
95            Some(Commands::Pull(args)) => commands::run::pull(args, verbose, &dir, light),
96            Some(Commands::CherryPick(args)) => {
97                commands::run::cherry_pick(args, verbose, &dir, light)
98            }
99            Some(Commands::Revert(args)) => commands::run::revert(args, verbose, &dir, light),
100            Some(Commands::File(args)) => commands::file::run(args, light),
101            Some(Commands::Abort) => commands::abort::run(verbose, &dir),
102        }
103    }
104}