131 lines
3.3 KiB
Rust
131 lines
3.3 KiB
Rust
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::<usize>() {
|
|
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(())
|
|
|
|
|
|
}
|
|
|