use std::io::Write; use std::str; use std::fs::File; use std::fs::OpenOptions; use std::io::{prelude::*, BufReader}; pub fn write_to_history(command: &str) -> Result<(), std::io::Error> { //Write a command to history let filepath = dirs::home_dir().unwrap().join(".history.sqish"); let mut file = OpenOptions::new() .write(true) .append(true) .create(true) .open(&filepath)?; let number = match get_history_number() { Ok(n) => n + 1, Err(_) => 1 }; let command = command.replace('\n', "\\n"); writeln!(file, "{} {}", number, command.trim())?; return Ok(()) } pub fn get_history_number() -> Result { //Get the latest number found in history file let filepath = dirs::home_dir().unwrap().join(".history.sqish"); let file = File::open(filepath)?; let reader = BufReader::new(file).lines(); let myline = String::from(reader.last().unwrap_or(Ok(String::from("1")))?); let number = myline.split(' ').next().expect("???").parse().unwrap(); return Ok(number); } pub fn get_curr_history_number() -> i32 { //Returns CURRENT history number, AKA the one for the command we are typing let mynumber = match get_history_number() { Ok(n) => n + 1, Err(_) => 1, }; return mynumber; } pub fn get_history() -> Result { let filepath = dirs::home_dir().unwrap().join(".history.sqish"); let file = File::open(filepath)?; let contents = BufReader::new(file).lines(); let mut res = String::new(); for line in contents { let myline = format!("\r\n{}", line.unwrap()); res.push_str(&myline); } res.push_str("\r\n"); return Ok(res); } pub fn get_hist_from_number(number: &i32) -> Option { //Returns a command from its number in hist file let filepath = dirs::home_dir().unwrap().join(".history.sqish"); if filepath.exists() == false { return None; } let file = File::open(filepath) .expect("Error opening history file..."); if file.metadata().unwrap().len() < 1 { return None; } let reader = BufReader::new(file).lines(); for line in reader { let current_line = line .expect("Empty history file ? Please rm it"); let mut s = current_line.split_whitespace(); let n: i32 = s.next() .expect("Error reading a line in hist file") .parse() .unwrap(); //let c = s.next().expect("No command!"); if &n == number { let remainder: String = s.map(|c| c.to_string()).collect::>().join(" "); return Some(String::from(remainder)); } } return None; } pub fn treat_history_callback(line: &str) -> Option { let mystring = String::from(line); let temp = mystring.split_whitespace().collect::>(); let mystring = temp.first().unwrap_or(&line); let mut chars = mystring.chars(); let args = &temp[1..]; //Skip the ! chars.next(); let mynbr: i32 = chars.as_str().parse().unwrap(); match get_hist_from_number(&mynbr) { Some(h) => return Some(format!("{} {}", h, args.join(" "))), None => return None, } } pub fn get_prev_arg() -> Option { let nbr = get_history_number(); match nbr { Ok(r) => { let prev_cmd = get_hist_from_number(&r).unwrap_or(String::new()); let last_arg = prev_cmd.split_whitespace().last().unwrap(); return Some(String::from(last_arg)); }, Err(_) => { return None }, }; }