use anyhow::anyhow;
use clap::Parser;
use reqwest::Url;
use std::{error::Error, path::PathBuf, str::FromStr};
#[derive(Debug, Parser)]
pub enum Command {
Post {
#[command(flatten)]
id_options: IdOptions,
#[command(flatten)]
options: CliOptions,
},
Sequence {
#[command(flatten)]
id_options: IdOptions,
#[command(flatten)]
options: CliOptions,
},
All {
#[command(flatten)]
options: CliOptions,
},
}
impl Command {
pub fn options(&self) -> CliOptions {
match self {
Command::Post { options, .. }
| Command::Sequence { options, .. }
| Command::All { options } => options.clone(),
}
}
}
#[derive(Debug, Clone, Parser)]
pub struct IdOptions {
#[clap(long, short = 'u')]
url: Option<String>,
#[clap(long)]
id: Option<String>,
}
#[derive(Debug, Clone)]
pub enum IdOrUrl {
Url { url: String },
Id { id: String },
}
impl From<IdOptions> for IdOrUrl {
fn from(value: IdOptions) -> IdOrUrl {
if let Some(id) = value.id {
IdOrUrl::Id { id }
} else {
IdOrUrl::Url {
url: value
.url
.ok_or(anyhow!("No ID or URL was specified"))
.unwrap(),
}
}
}
}
impl IdOrUrl {
pub fn get_id(self) -> Result<String, Box<dyn Error>> {
Ok(match self {
IdOrUrl::Id { id } => id,
IdOrUrl::Url { url } => {
let url = Url::from_str(&url)?;
url.path_segments()
.ok_or(anyhow!("Failed to parse URL segments"))?
.nth(1)
.ok_or(anyhow!("Failed to find ID in URL"))?
.to_string()
}
})
}
}
#[derive(Debug, Clone, Parser)]
pub struct CliOptions {
#[clap(long, short = 'i')]
pub ignore_cache: bool,
#[clap(long, short = 'd')]
pub delete_cache: bool,
#[clap(long, default_value = "./", short = 'o')]
pub output_dir: PathBuf,
#[clap(long, short = 'c')]
pub cache_dir: Option<PathBuf>,
}
#[derive(Debug, Clone)]
pub struct ParsedCliOptions {
pub ignore_cache: bool,
pub delete_cache: bool,
pub output_dir: PathBuf,
pub cache_dir: PathBuf,
}
impl From<CliOptions> for ParsedCliOptions {
fn from(value: CliOptions) -> Self {
Self {
ignore_cache: value.ignore_cache,
delete_cache: value.delete_cache,
output_dir: value.output_dir,
cache_dir: value.cache_dir.unwrap_or(
dirs::cache_dir()
.unwrap_or(PathBuf::from_str("./cache").unwrap())
.join("lesspub"),
),
}
}
}
pub struct CacheOptions {
pub ignore_cache: bool,
pub cache_dir: PathBuf,
}