#![allow(clippy::needless_return)] mod app; pub mod config; pub mod error; pub mod input; pub mod state; use std::{ fs::read_to_string, io::{IsTerminal, Read, stdin}, path::Path, }; use anyhow::Result; use app::App; use clap::{Args, Parser}; use rand::Rng; use crate::config::{Quote, get_quoter}; #[derive(Parser)] struct Cli { /// Turns all text into lowercase (NOOB mode) #[arg(short, long)] lower: bool, #[command(flatten)] quote_size: QuoteSize, quote: Option, } #[derive(Args)] #[group(required = false, multiple = false)] struct QuoteSize { #[arg(short, long)] short: bool, #[arg(short, long)] medium: bool, #[arg(short, long)] long: bool, #[arg(short, long)] huge: bool, } fn generate_quotes(path: &Path) -> Result> { let mut ris = Vec::new(); if path.is_file() { ris.push(read_to_string(path)?); } else { for f in path.read_dir()? { if f.is_err() { continue; } let v = f.unwrap().path(); if v.is_file() { ris.push(read_to_string(v)?); } } } return Ok(ris); } #[tokio::main] async fn main() -> Result<()> { let args = Cli::parse(); let mut quote = if !stdin().is_terminal() { let mut b = Vec::new(); stdin().read_to_end(&mut b).unwrap(); Quote { text: String::from_utf8(b)?, source: None, } } else if let Some(q) = &args.quote { let path = Path::new(q); let mut quotes = generate_quotes(path).unwrap(); let mut rng = rand::rand_core::UnwrapErr(rand::rngs::SysRng); let chosen = rng.next_u64() as usize; Quote { text: quotes.remove(chosen), source: None, } } else { println!("Loading available quotes..."); let mut quoter = get_quoter()?; if args.quote_size.short { quoter.get_short()?; } if args.quote_size.medium { quoter.get_medium()?; } if args.quote_size.long { quoter.get_long()?; } if args.quote_size.huge { quoter.get_huge()?; } quoter.get_random()? }; if args.lower { quote.text = quote.text.to_lowercase(); } // TODO Add more options to choose quotes let mut app = App::new("e); app.start().await?; return Ok(()); }