gr/
cli.rs

1pub mod amps;
2pub mod browse;
3pub mod cache;
4pub mod cicd;
5pub mod common;
6pub mod docker;
7pub mod init;
8pub mod merge_request;
9pub mod my;
10pub mod project;
11pub mod release;
12pub mod star;
13pub mod trending;
14pub mod user;
15
16use self::browse::BrowseCommand;
17use self::browse::BrowseOptions;
18use self::cicd::{PipelineCommand, PipelineOptions};
19use self::common::validate_domain_project_repo_path;
20use self::docker::{DockerCommand, DockerOptions};
21use self::init::{InitCommand, InitCommandOptions};
22use self::my::MyCommand;
23use self::my::MyOptions;
24use self::project::{ProjectCommand, ProjectOptions};
25use self::release::{ReleaseCommand, ReleaseOptions};
26use self::trending::TrendingCommand;
27use self::trending::TrendingOptions;
28use amps::AmpsCommand;
29use amps::AmpsOptions;
30use cache::CacheCommand;
31use cache::CacheOptions;
32use clap::ArgAction;
33use merge_request::{MergeRequestCommand, MergeRequestOptions};
34use user::UserCommand;
35use user::UserOptions;
36
37use std::option::Option;
38
39use clap::builder::{styling::AnsiColor, Styles};
40use clap::Parser;
41
42const CLI_STYLE: Styles = Styles::styled()
43    .header(AnsiColor::Red.on_default().bold())
44    .literal(AnsiColor::Blue.on_default().bold())
45    .placeholder(AnsiColor::Green.on_default())
46    .usage(AnsiColor::Red.on_default().bold());
47
48#[derive(Parser)]
49#[command(about = "A Github/Gitlab CLI tool", styles = CLI_STYLE, version)]
50#[clap(next_help_heading = "Global options")]
51struct Args {
52    #[clap(subcommand)]
53    pub command: Command,
54    /// Verbose mode. Enable gitar's logging. -v for INFO, -vv for DEBUG
55    #[clap(long, short, global = true, action = ArgAction::Count)]
56    verbose: u8,
57    /// Bypass local .git/config. Use repo instead. Ex: github.com/jordilin/gitar
58    #[clap(
59        long,
60        global = true,
61        value_name = "DOMAIN/OWNER/PROJECT_NAME",
62        value_parser = validate_domain_project_repo_path
63    )]
64    pub repo: Option<String>,
65    /// Bypass local .git/config. Use domain. Ex. for my subcommands
66    #[clap(long, global = true, value_name = "DOMAIN")]
67    pub domain: Option<String>,
68    /// Full path to the config location. Default is $HOME/.config/gitar
69    #[clap(long, global = true, value_name = "PATH")]
70    pub config: Option<String>,
71}
72
73#[derive(Parser)]
74enum Command {
75    #[clap(name = "mr", about = "Merge request operations")]
76    MergeRequest(MergeRequestCommand),
77    #[clap(name = "br", about = "Open the remote using your browser")]
78    Browse(BrowseCommand),
79    #[clap(name = "pp", about = "CI/CD Pipeline operations")]
80    Pipeline(PipelineCommand),
81    #[clap(name = "pj", about = "Gather project information metadata")]
82    Project(ProjectCommand),
83    #[clap(
84        name = "dk",
85        about = "Handles docker images in Gitlab/Github registries"
86    )]
87    Docker(DockerCommand),
88    #[clap(name = "rl", about = "Release operations")]
89    Release(ReleaseCommand),
90    #[clap(
91        name = "my",
92        about = "Your user information, such as assigned merge requests, etc..."
93    )]
94    My(MyCommand),
95    #[clap(name = "tr", about = "Trending repositories. Github.com only.")]
96    Trending(TrendingCommand),
97    #[clap(name = "us", about = "User operations")]
98    User(UserCommand),
99    /// Interactively execute gitar amplifier commands using gitar. gr-in-gr
100    #[clap(name = "amps")]
101    Amps(AmpsCommand),
102    #[clap(name = "init", about = "Initialize the config file")]
103    Init(InitCommand),
104    #[clap(name = "cache", about = "Local cache operations")]
105    Cache(CacheCommand),
106    #[clap(
107        name = "manual",
108        about = "Open the user manual in the browser",
109        visible_alias = "man"
110    )]
111    Manual,
112}
113
114// Parse cli and return CliOptions
115pub fn parse_cli() -> OptionArgs {
116    let args = Args::parse();
117    let options = match args.command {
118        Command::MergeRequest(sub_matches) => Some(CliOptions::MergeRequest(sub_matches.into())),
119        Command::Browse(sub_matches) => Some(CliOptions::Browse(sub_matches.into())),
120        Command::Pipeline(sub_matches) => Some(CliOptions::Pipeline(sub_matches.into())),
121        Command::Project(sub_matches) => Some(CliOptions::Project(sub_matches.into())),
122        Command::Init(sub_matches) => Some(CliOptions::Init(sub_matches.into())),
123        Command::Docker(sub_matches) => Some(CliOptions::Docker(sub_matches.into())),
124        Command::Release(sub_matches) => Some(CliOptions::Release(sub_matches.into())),
125        Command::My(sub_matches) => Some(CliOptions::My(sub_matches.into())),
126        Command::Trending(sub_matches) => Some(CliOptions::Trending(sub_matches.into())),
127        Command::Cache(sub_matches) => Some(CliOptions::Cache(sub_matches.into())),
128        Command::Manual => Some(CliOptions::Manual),
129        Command::Amps(sub_matches) => Some(CliOptions::Amps(sub_matches.into())),
130        Command::User(sub_matches) => Some(CliOptions::User(sub_matches.into())),
131    };
132    OptionArgs::new(
133        options,
134        CliArgs::new(args.verbose, args.repo, args.domain, args.config),
135    )
136}
137
138pub enum CliOptions {
139    MergeRequest(MergeRequestOptions),
140    Browse(BrowseOptions),
141    Pipeline(PipelineOptions),
142    Project(ProjectOptions),
143    Init(InitCommandOptions),
144    Docker(DockerOptions),
145    Release(ReleaseOptions),
146    My(MyOptions),
147    Trending(TrendingOptions),
148    Cache(CacheOptions),
149    Manual,
150    Amps(AmpsOptions),
151    User(UserOptions),
152}
153
154#[derive(Clone, Default)]
155pub struct CliArgs {
156    pub verbose: u8,
157    pub repo: Option<String>,
158    pub domain: Option<String>,
159    pub config: Option<String>,
160}
161
162impl CliArgs {
163    pub fn new(
164        verbose: u8,
165        repo: Option<String>,
166        domain: Option<String>,
167        config: Option<String>,
168    ) -> Self {
169        CliArgs {
170            verbose,
171            repo,
172            domain,
173            config,
174        }
175    }
176}
177
178pub struct OptionArgs {
179    pub cli_options: Option<CliOptions>,
180    pub cli_args: CliArgs,
181}
182
183impl OptionArgs {
184    pub fn new(cli_options: Option<CliOptions>, cli_args: CliArgs) -> Self {
185        OptionArgs {
186            cli_options,
187            cli_args,
188        }
189    }
190}