use core::fmt;
use clap::{Parser, Subcommand};
use colored::Colorize;
use url::Url;
#[derive(Parser, Debug)]
#[command(name = "Coma")]
#[command(author = "Noah")]
#[command(version)]
#[command(help_template = "
{name} - {about}
Author: {author}
Version: {version}
{usage-heading} {usage}
{all-args} {tab}")]
pub struct Cli {
#[command(subcommand)]
pub cmd: Display,
#[arg(short, long, value_delimiter = ',', default_value = "all")]
pub content: Vec<Content>,
#[arg(short, long)]
pub url: String,
#[arg(short, long, default_value_t = 0, allow_negative_numbers = true)]
pub depth: i32,
#[arg(short, long, default_value = "")]
pub bound: String,
#[arg(short, long, default_value_t = 5)]
pub thread: u32,
#[arg(short, long, default_value_t = 0)]
pub external: i32,
}
#[derive(Subcommand, Debug, Clone, PartialEq, Eq, Hash)]
pub enum Display {
Print {
#[arg()]
format: Format,
},
Save {
#[arg()]
format: Format,
#[arg(short, long, default_value = "output")]
name: String,
},
Graph,
}
#[derive(clap::ValueEnum, Debug, Clone, Copy, PartialEq, serde::Serialize)]
pub enum Content {
Texts,
Comments,
Links,
Images,
Inputs,
All,
}
#[derive(clap::ValueEnum, Debug, Clone, PartialEq, Eq, Hash)]
pub enum Format {
Json,
Raw,
}
pub enum ArgsError {
InvalidUrl(String),
}
impl ArgsError {
fn print(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ArgsError::InvalidUrl(url) => write!(f, "{}: {}", "Invalid URL".red(), url),
}
}
}
impl fmt::Display for ArgsError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.print(f)
}
}
impl fmt::Debug for ArgsError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.print(f)
}
}
impl std::error::Error for ArgsError {}
pub fn args() -> Result<Cli, ArgsError> {
let args = Cli::parse();
match Url::parse(&args.url) {
Ok(v) => {
v.domain().ok_or(ArgsError::InvalidUrl(v.to_string()))?;
Ok(args)
}
Err(e) => Err(ArgsError::InvalidUrl(e.to_string())),
}
}