use std::{fmt::Display, io::stdout, path::PathBuf};
use clap::{Parser, Subcommand, builder::PossibleValue};
use tip_files::Tips;
#[derive(Parser, Clone, Debug)]
struct Args {
tip: Option<String>,
#[command(subcommand)]
cmd: Option<Command>,
}
#[derive(Subcommand, Clone, Debug)]
enum Command {
#[clap(visible_alias("l"))]
List {
#[clap(short, default_value_t = FilterState::Open)]
filter_state: FilterState,
},
#[clap(visible_alias("v"))]
View { tip: String },
#[clap(visible_alias("n"))]
New { title: String },
#[clap(visible_alias("r"))]
Remove { tip: String },
#[clap(visible_alias("o"))]
Open { tip: String },
#[clap(visible_alias("c"))]
Close { tip: String },
}
#[derive(Clone, Debug, Default)]
enum FilterState {
#[default]
Open,
Closed,
All,
}
impl FilterState {
fn str(&self) -> &'static str {
match self {
FilterState::Open => "open",
FilterState::Closed => "closed",
FilterState::All => "all",
}
}
fn filter(&self) -> &'static [&'static str] {
match self {
FilterState::Open => &["open"],
FilterState::Closed => &["closed"],
FilterState::All => &["open", "closed"],
}
}
}
impl Display for FilterState {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(self.str())
}
}
impl clap::ValueEnum for FilterState {
fn value_variants<'a>() -> &'a [Self] {
&[FilterState::Open, FilterState::Closed, FilterState::All]
}
fn to_possible_value(&self) -> Option<clap::builder::PossibleValue> {
Some(PossibleValue::new(self.str()))
}
}
fn main() {
let mut args = Args::parse();
let root = PathBuf::from("tip");
if args.cmd.is_none() {
if let Some(tip) = args.tip {
args.cmd = Some(Command::View { tip })
};
args.cmd = Some(Command::List {
filter_state: Default::default(),
});
}
let mut out = stdout();
let mut tips = Tips::new(root, &mut out);
match args.cmd.unwrap_or(Command::List {
filter_state: Default::default(),
}) {
Command::List { filter_state } => tips.list(filter_state.filter()),
Command::View { tip } => tips.details(tip.as_str()),
Command::New { title } => tips.create(title.as_str()),
Command::Remove { tip } => tips.delete(tip.as_str()),
Command::Open { tip } => tips.open(tip.as_str()),
Command::Close { tip } => tips.close(tip.as_str()),
}
}