use clap::{ArgAction, Command, CommandFactory, Parser, Subcommand, ValueEnum};
use clap_complete::{generate, Generator, Shell};
use gr_bin::formatters::formatter::FormatterType;
use std::io;
use std::process;
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, ValueEnum)]
pub enum StateFilter {
Open,
Closed,
Merged,
Locked,
All,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, ValueEnum)]
pub enum UserFilter {
Me,
All,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, ValueEnum, Default)]
pub enum OutputType {
#[default]
Normal,
Json,
}
impl Into<FormatterType> for OutputType {
fn into(self) -> FormatterType {
match self {
OutputType::Normal => FormatterType::Normal,
OutputType::Json => FormatterType::Json,
}
}
}
#[derive(Debug, Subcommand)]
#[command(after_help = "Examples:
Create pull request on current branch:
$ gr pr create -m 'PR title'
Get information about the current branch PR:
$ gr pr get
Merge the current branch PR:
$ gr pr merge
")]
pub enum PrCommands {
#[command(after_help = "Examples:
Create a pull request with a title:
$ gr pr create -m 'Do things'
Create a pull request with a title and a description:
$ gr pr create -m 'Do things' -d 'Do things and stuff'
Description can be provided from standard input (for example git-cliff):
$ git-cliff --tag PR --strip all | gr pr create -m 'Do things'
Create a pull request to merge into a different branch:
$ gr pr create -m 'Do things' --target staging
Create a pull request and merge it immediately (for fix branches):
$ gr pr create -m 'Fix things' --merge --delete")]
Create {
#[arg(short, long)]
message: String,
#[arg(short, long)]
description: Option<String>,
#[arg(short, long)]
target: Option<String>,
#[arg(short, long = "reviewer")]
reviewers: Option<Vec<String>>,
#[arg(long)]
delete: bool,
#[arg(long)]
open: bool,
#[arg(long)]
merge: bool,
},
#[command(after_help = "Examples:
Get the pull request on the current branch:
$ gr pr get
Get the pull request on another branch:
$ gr pr get -b feature/branch")]
Get {
#[arg(long)]
open: bool,
},
#[command(after_help = "Examples:
Open the pull request on the current branch:
$ gr pr open
Open the pull request on another branch:
$ gr pr open -b feature/branch")]
Open {},
#[command(after_help = "Examples:
List all open pull requests:
$ gr pr list
List all pull requests:
$ gr pr list --state=all
List your open pull requests:
$ gr pr list --user=me")]
List {
#[arg(long, value_enum)]
author: Option<UserFilter>,
#[arg(long, value_enum)]
state: Option<StateFilter>,
},
#[command(after_help = "Examples:
Approve the pull request on the current branch:
$ gr pr approve")]
Approve {},
#[command(after_help = "Examples:
Merge the pull request, and go to the target branch:
$ gr pr merge")]
Merge {
#[arg(long)]
delete: bool,
},
#[command(after_help = "Examples:
Decline the pull request:
$ gr pr decline")]
#[command(alias = "decline")]
Close {},
}
#[derive(Debug, Subcommand)]
pub enum Commands {
#[command(after_help = "Examples:
Login to the current repo's remote:
$ gr login
Login to arbitrary remote:
$ gr login github.com")]
Login {
hostname: Option<String>,
#[arg(long)]
repo: Option<String>,
#[arg(long)]
token: Option<String>,
},
#[command(subcommand)]
Pr(PrCommands),
Completion { shell: Shell },
}
#[derive(Debug, Parser)]
#[command(name = "gr")]
#[command(version = "0.1.5")]
#[command(about = "Interact with remote repositories like you interact with git", long_about = None)]
#[command(after_help = "Examples:
Login to the current repo's remote:
$ gr login
Create pull request on current branch:
$ gr pr create -m 'PR title'
Get information about the current branch PR:
$ gr pr get
Generate bash completion:
$ source <(gr completion bash)")]
pub struct Cli {
#[command(subcommand)]
pub command: Commands,
#[arg(short, long, global = true)]
pub branch: Option<String>,
#[arg(long, global = true)]
pub dir: Option<String>,
#[arg(long, global = true)]
pub auth: Option<String>,
#[arg(long, short, global = true, default_value = "normal")]
pub output: OutputType,
#[arg(long, short, global = true, action = ArgAction::Count)]
pub verbose: u8,
}
fn print_completions<G: Generator>(gen: G, cmd: &mut Command) {
generate(gen, cmd, cmd.get_name().to_string(), &mut io::stdout());
}
impl Cli {
pub fn parse_args() -> Cli {
let cli = Cli::parse();
if let Commands::Completion { shell } = cli.command {
let mut cmd = Cli::command();
print_completions(shell, &mut cmd);
process::exit(0);
}
cli
}
}