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::Cache; fn flush_stdout() { stdout().flush().ok(); } fn main() { let cache = Cache::read(); let request = match env::args().nth(1) { Some(arg) => arg, None => { eprintln!("{} {}", "error:".bold().red(), "cdg expects an argument".bold()); exit(1); }, }; let matches = cache.find(&request); match matches.len() { 0 => { eprintln!("{} {}", "error:".bold().red(), "no such directory".bold()); exit(1); }, 1 => { println!("{}", matches[0]); }, len => { eprintln!("{} {}", "info:".bold(), "multiple entries found, please select one"); for (i, j) in matches.iter().enumerate() { eprintln!("[{}] {}", i + 1, j); } eprint!("Enter your choice: "); 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]); }, } }