use anyhow::Result;
use clap::{Args, Parser, Subcommand};
use rfc::commands;
use rfc::SearchFilter;
#[derive(Parser)]
#[command(name = "rfc", version)]
#[command(about = "Search, retrieve, and display IETF RFCs and drafts")]
#[command(args_conflicts_with_subcommands = true)]
#[command(arg_required_else_help = true)]
struct Cli {
document: Option<String>,
#[arg(short = 'o', long, value_name = "PROGRAM", conflicts_with = "web")]
open_with: Option<String>,
#[arg(short = 'w', long, requires = "document")]
web: bool,
#[command(subcommand)]
command: Option<Command>,
}
#[derive(Subcommand)]
enum Command {
Fetch {
document: String,
},
Search(SearchArgs),
#[command(subcommand)]
Cache(CacheCmd),
}
#[derive(Args)]
struct SearchArgs {
#[arg(required = true, num_args = 1..)]
query: Vec<String>,
#[command(flatten)]
filter: SearchFilterArgs,
#[arg(short, long, default_value_t = 25)]
limit: usize,
}
#[derive(Args)]
#[group(multiple = false)]
struct SearchFilterArgs {
#[arg(short, long)]
drafts: bool,
#[arg(short, long)]
all: bool,
}
impl From<&SearchFilterArgs> for SearchFilter {
fn from(a: &SearchFilterArgs) -> Self {
if a.drafts {
SearchFilter::DraftsOnly
} else if a.all {
SearchFilter::Both
} else {
SearchFilter::RfcsOnly
}
}
}
#[derive(Subcommand)]
enum CacheCmd {
List {
#[arg(short, long)]
wide: bool,
},
Info,
Remove {
document: String,
},
Clear,
}
#[tokio::main]
async fn main() -> Result<()> {
let cli = Cli::parse();
match cli.command {
Some(Command::Fetch { document }) => commands::fetch::run(&document).await,
Some(Command::Search(args)) => {
let filter = SearchFilter::from(&args.filter);
commands::search::run(commands::search::Args {
query: args.query.join(" "),
filter,
limit: args.limit,
})
.await
}
Some(Command::Cache(c)) => match c {
CacheCmd::List { wide } => commands::cache::list(wide),
CacheCmd::Info => commands::cache::info(),
CacheCmd::Remove { document } => commands::cache::remove(&document),
CacheCmd::Clear => commands::cache::clear(),
},
None => match cli.document {
Some(doc) => commands::view::run(&doc, cli.open_with.as_deref(), cli.web).await,
None => Ok(()),
},
}
}