use crate::utils::enums::*;
use clap::builder::styling::{AnsiColor, Effects, Style, Styles};
use clap::{CommandFactory, Parser, Subcommand};
pub const HEADER: Style = AnsiColor::Green.on_default().effects(Effects::BOLD);
pub const USAGE: Style = AnsiColor::Green.on_default().effects(Effects::BOLD);
pub const LITERAL: Style = AnsiColor::Cyan.on_default().effects(Effects::BOLD);
pub const PLACEHOLDER: Style = AnsiColor::Cyan.on_default();
pub const ERROR: Style = AnsiColor::Red.on_default().effects(Effects::BOLD);
pub const VALID: Style = AnsiColor::Cyan.on_default().effects(Effects::BOLD);
pub const INVALID: Style = AnsiColor::Yellow.on_default().effects(Effects::BOLD);
const CARGO_STYLING: Styles = Styles::styled()
.header(HEADER)
.usage(USAGE)
.literal(LITERAL)
.placeholder(PLACEHOLDER)
.error(ERROR)
.valid(VALID)
.invalid(INVALID);
#[derive(Parser, Debug)]
#[command(version, long_about, styles=CARGO_STYLING)]
pub struct Args {
#[arg(
long,
value_name = "DIR",
help = "cache directory for API calls (default: ~/.cache/pokelookup/)"
)]
pub cache_dir: Option<std::path::PathBuf>,
#[command(subcommand)]
pub command: SubArgs,
}
#[derive(Subcommand, Debug)]
pub enum SubArgs {
#[command(name = "list", long_about)]
ListCmd {
#[arg(help = "name of pokemon species")]
pokemon: String,
#[arg(short, long, help = "skip API requests for formatted names")]
fast: bool,
#[arg(value_enum,
short = 'L',
long,
value_name = "LANGUAGE",
default_value_t = LanguageId::En,
hide_possible_values=true,
help = "language ID for API requests for formatted names"
)]
lang: LanguageId,
},
#[command(name = "types", long_about)]
TypeCmd {
#[arg(help = "name of pokemon")]
pokemon: String,
#[arg(short, long, help = "skip API requests for formatted names")]
fast: bool,
#[arg(short, long = "gen", help = "generation to query")]
generation: Option<i64>,
#[arg(value_enum,
short = 'L',
long,
value_name = "LANGUAGE",
default_value_t = LanguageId::En,
hide_possible_values=true,
help = "language ID for API requests for formatted names"
)]
lang: LanguageId,
#[arg(short, help = "recursively check evolution chain")]
recursive: bool,
},
#[command(
name = "abilities",
about = "Look up the abilities of a given pokemon",
long_about
)]
AbilityCmd {
#[arg(help = "name of pokemon")]
pokemon: String,
#[arg(short, long, help = "skip API requests for formatted names")]
fast: bool,
#[arg(value_enum,
short = 'L',
long,
value_name = "LANGUAGE",
default_value_t = LanguageId::En,
hide_possible_values=true,
help = "language ID for API requests for formatted names"
)]
lang: LanguageId,
#[arg(short, help = "recursively check evolution chain")]
recursive: bool,
},
#[command(
name = "moves",
about = "Look up the level-up moveset of a given pokemon",
long_about
)]
MoveCmd {
#[arg(help = "name of pokemon")]
pokemon: String,
#[arg(short, long, help = "skip API requests for formatted names")]
fast: bool,
#[arg(value_enum,
short = 'L',
long,
value_name = "LANGUAGE",
default_value_t = LanguageId::En,
hide_possible_values=true,
help = "language ID for API requests for formatted names"
)]
lang: LanguageId,
#[arg(value_enum, short, long, default_value_t=VersionGroup::ScarletViolet,
hide_possible_values=true, help="version group name")]
vgroup: VersionGroup,
#[arg(short, long, help = "request default moveset at given level")]
level: Option<i64>,
},
#[command(name = "eggs", long_about)]
EggCmd {
#[arg(help = "name of pokemon species")]
pokemon: String,
#[arg(short, long, help = "skip API requests for formatted names")]
fast: bool,
#[arg(value_enum,
short = 'L',
long,
value_name = "LANGUAGE",
default_value_t = LanguageId::En,
hide_possible_values=true,
help = "language ID for API requests for formatted names"
)]
lang: LanguageId,
},
#[command(name = "genders", long_about)]
GenderCmd {
#[arg(help = "name of pokemon species")]
pokemon: String,
#[arg(short, long, help = "skip API requests for formatted names")]
fast: bool,
#[arg(value_enum,
short = 'L',
long,
value_name = "LANGUAGE",
default_value_t = LanguageId::En,
hide_possible_values=true,
help = "language ID for API requests for formatted names"
)]
lang: LanguageId,
},
#[command(name = "encounters", long_about)]
EncounterCmd {
#[arg(value_enum, hide_possible_values = true, help = "name of version")]
version: Version,
#[arg(help = "name of pokemon")]
pokemon: String,
#[arg(short, long, help = "skip API requests for formatted names")]
fast: bool,
#[arg(value_enum,
short = 'L',
long,
value_name = "LANGUAGE",
default_value_t = LanguageId::En,
hide_possible_values=true,
help = "language ID for API requests for formatted names"
)]
lang: LanguageId,
#[arg(short, help = "recursively check evolution chain")]
recursive: bool,
},
#[command(name = "evolutions", long_about)]
EvolutionCmd {
#[arg(help = "name of pokemon species")]
pokemon: String,
#[arg(short, long, help = "skip API requests for formatted names")]
fast: bool,
#[arg(value_enum,
short = 'L',
long,
value_name = "LANGUAGE",
default_value_t = LanguageId::En,
hide_possible_values=true,
help = "language ID for API requests for formatted names"
)]
lang: LanguageId,
#[arg(
short,
long,
help = "hide the names of the pokemon in the evolution chain"
)]
secret: bool,
#[arg(short, long, help = "show all evolution chains, even outdated ones")]
all: bool,
},
#[command(name = "matchups", long_about)]
MatchupCmd {
#[arg(
value_enum,
hide_possible_values = true,
value_name = "TYPE",
help = "name of type"
)]
primary: Type,
#[arg(
value_enum,
hide_possible_values = true,
value_name = "TYPE",
help = "name of optional secondary type"
)]
secondary: Option<Type>,
#[arg(short, long, help = "print output as a list instead of a table")]
list: bool,
#[arg(short, long, help = "skip API requests for formatted names")]
fast: bool,
#[arg(value_enum,
short = 'L',
long,
value_name = "LANGUAGE",
default_value_t = LanguageId::En,
hide_possible_values=true,
help = "language ID for API requests for formatted names"
)]
lang: LanguageId,
},
#[cfg(feature = "web")]
#[command(name = "web", long_about)]
WebCmd {
#[command(flatten)]
endpoint: Endpoints,
#[arg(short = 'A', long, help = "name of area within region")]
area: Option<String>,
#[arg(short, long = "gen", help = "optional name of generation to use")]
generation: Option<i64>,
#[arg(short, long, help = "suppress print statements")]
quiet: bool,
},
}
#[cfg(feature = "web")]
#[derive(Debug, clap::Args)]
#[group(required = true, multiple = false)]
pub struct Endpoints {
#[arg(short, long, help_heading = "Endpoints", conflicts_with_all = ["area"], help = "name of pokemon")]
pub pokemon: Option<String>,
#[arg(short, long, help_heading = "Endpoints", help = "name of region")]
pub region: Option<String>,
#[arg(
short,
long,
help_heading = "Endpoints",
conflicts_with = "area",
help = "name of move"
)]
pub move_: Option<String>,
#[arg(short, long, help_heading = "Endpoints", conflicts_with_all = ["area", "generation"], help = "name of ability")]
pub ability: Option<String>,
#[arg(short, long, help_heading = "Endpoints", conflicts_with_all = ["area", "generation"], help = "name of item")]
pub item: Option<String>,
}
#[cfg(feature = "web")]
impl Endpoints {
pub fn get_mode(&self) -> DexMode {
if let Some(name) = &self.pokemon {
DexMode::Pokedex(name.clone())
} else if let Some(name) = &self.region {
DexMode::Pokearth(name.clone())
} else if let Some(name) = &self.move_ {
DexMode::Attackdex(name.clone())
} else if let Some(name) = &self.ability {
DexMode::Abilitydex(name.clone())
} else if let Some(name) = &self.item {
DexMode::Itemdex(name.clone())
} else {
unreachable!()
}
}
}
#[cfg(feature = "web")]
pub enum DexMode {
Pokedex(String),
Pokearth(String),
Attackdex(String),
Abilitydex(String),
Itemdex(String),
}
pub fn get_appname() -> String {
String::from(Args::command().get_name())
}
pub fn error(kind: clap::error::ErrorKind, message: String) -> clap::Error {
Args::command().error(kind, message)
}