use std::env; use std::error::Error; use std::process::exit; use std::io::{stdout, stdin, Write}; use std::num::Wrapping; use colored::*; use gclone::{Result, Cache}; fn flush_stdout() { stdout().flush().ok(); } fn main() -> Result<()> { let request = match env::args().nth(1) { Some(arg) => arg, None => { eprintln!("{} {}", "error:".bold().red(), "cdg expects an argument".bold()); exit(1); }, }; main_with_cache(&request, true) } fn main_with_cache(request: &str, regen: bool) -> Result<()> { let (cache, regen) = match Cache::read() { Ok(c) => (c, regen), Err(_) => (Cache::generate(), false), }; let matches = cache.find(&request); match matches.len() { 0 => { if regen { eprintln!("{} {}", "warning:".bold().yellow(), "directory not found, regenerating cache...".bold()); let cache = Cache::generate(); match cache.write() { Ok(_) => (), Err(e) => { eprintln!("{} {} {}", "warning:".bold().yellow(), "couldn't write cache:".bold(), e.description()); }, } return main_with_cache(request, false); } else { eprintln!("{} {}", "error:".bold().red(), "no such directory".bold()); exit(1); } }, 1 => { println!("{}", matches[0]); }, len => { eprintln!("{}", "info: multiple entries found, please select one".bold()); for (i, j) in matches.iter().enumerate() { eprintln!("{} {}", &format!("[{}]", i + 1).bold().blue(), &format!("{}", j).yellow()); } eprint!("{}", "Enter your choice: ".bold()); flush_stdout(); let mut string = String::new(); match stdin().read_line(&mut string) { Ok(_) => (), Err(e) => { eprintln!("{} {} {}", "error:".bold().red(), "couldn't read line:".bold(), e.description()); exit(1); }, }; // Pop the trailing \n of the string string.pop(); // Use wrapping to move 0 to std::usize::MAX which is ok. let value = (Wrapping(match string.parse::() { Ok(v) => v, Err(e) => { eprintln!("{} {} {}", "error:".bold().red(), "couldn't parse integer:".bold(), e.description()); exit(1); } }) - Wrapping(1)).0; if value >= len { eprintln!("{} {}", "error:".bold().red(), "integer wasn't in the right range".bold()); exit(1); } println!("{}", matches[value]); }, } Ok(()) }