mod storage; mod utils; use chrono::{DateTime, Utc}; use clap::{Parser, Subcommand}; use regex::Regex; pub use storage::{open_sqlite_storage, Memo, MemoStorage}; use utils::{parse_human_duration, HumanDisplay}; #[derive(Parser)] #[clap(author, version, about, long_about = None)] #[clap(propagate_version = true, disable_colored_help = true)] #[clap(subcommand_required = false)] #[clap(disable_help_subcommand = true)] struct Cli { #[clap(subcommand)] command: Option, #[clap(short, long, help = "location for database file")] db_path: Option, } #[derive(Subcommand)] enum Commands { #[clap(trailing_var_arg = true)] New { #[clap(multiple_values = true)] #[clap(min_values = 1)] #[clap(required = true)] body: Vec, #[clap(short, long, help = "due time relative to now")] due: Option, }, Done { search: String, #[clap(long)] many: bool, }, Del { id: u32, }, } fn main() { let args = Cli::parse(); let home_path = std::env!("HOME").to_string(); let mut db_path: String = home_path + "/.local/share/memo-cli.db"; if let Some(db) = args.db_path { db_path = db; } let storage = open_sqlite_storage(&db_path).unwrap(); match args.command { Some(Commands::New { body, due }) => { let mut due_date: Option> = None; if let Some(d) = due { if d.len() > 0 { due_date = Some(Utc::now() + parse_human_duration(d.as_str()).unwrap()); } } let txt = body.join(" "); storage.add(txt.as_str(), due_date).unwrap(); println!("[+] new memo: {}", txt); } Some(Commands::Done { search, many }) => { let rex = Regex::new(search.as_str()); let mut found = false; let mut to_remove: Option = None; if let Some(re) = rex.ok() { for memo in storage.all().unwrap() { if re.is_match(memo.body.as_str()) { if many { storage.del(memo.id).unwrap(); println!("[-] task #{} done", memo.id); } else if found { println!("[!] would remove multiple tasks"); to_remove = None; break; } else { to_remove = Some(memo); found = true; } } } if let Some(rm) = to_remove { storage.del(rm.id).unwrap(); println!("[-] task #{} done", rm.id); } } else { println!("[!] invalid regex"); } } Some(Commands::Del { id }) => { storage.del(id).unwrap(); println!("[-] task #{} deleted", id); } None => { let all = storage.all().unwrap(); if all.len() < 1 { println!("[ ] nothing to remember"); } for m in all { println!("{}", m.human()); } } } }