diff --git a/src/lib.rs b/src/lib.rs index 5ebc40a..c69bfb0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -236,6 +236,12 @@ pub mod shell { let mut current_pos: usize = 0; let mut max_pos: usize = 0; + //Used to keep the result of the last autocomplete + //Next time we press tab we get a different result so that we can + //rotate between files in the dir for example + //Resetted by pressing enter + let mut prev_autocomplete = String::new(); + //Initialize write!(stdout, "\r\n SquiShell (sqish)--- \r\n{}", prompt); stdout.flush(); @@ -244,7 +250,13 @@ pub mod shell { match c.unwrap() { Key::Char('\t') => { - let (res, list) = autocomplete(&mycommand); + //Do NOT search on an empty command + if *&mycommand.len() == 0 { + continue; + } + //Search + let (res, list) = autocomplete(&mycommand, &prev_autocomplete); + *&mut prev_autocomplete = String::from(res.as_str()); write!(stdout, "\r\n{}\r\n", list); mycommand.clear(); mycommand.push_str(&res); @@ -255,6 +267,7 @@ pub mod shell { } Key::Char('\n') => { + *&mut prev_autocomplete = String::new(); current_number = get_curr_history_number(); prompt = build_prompt(¤t_number); current_pos = 0; diff --git a/src/shell/autocomplete.rs b/src/shell/autocomplete.rs index 39a36e0..636181f 100644 --- a/src/shell/autocomplete.rs +++ b/src/shell/autocomplete.rs @@ -1,10 +1,78 @@ use which::which_re; use regex::Regex; use std::path::PathBuf; +use std::{env, fs}; -pub fn autocomplete(input: &String) -> (String, String) { - let faketab = format!(" --This is a fake output for autocomplete from {input}-- "); +pub fn autocomplete(input: &String, prev_match: &String) -> (String, String) { + if !input.contains(' ') && !input.contains("./") { + return autocomplete_cmd(input); + } else { + return autocomplete_file(input, prev_match).unwrap(); + } +} + +///Look for a file using the string after the last space in the input, +///in the current folder. +fn autocomplete_file(input: &String, prev_match: &String) -> std::io::Result<(String, String)> { + + //Keep the last part of the cmd... + let input_searchee = input + .split(' ') + .collect::>() + .last() + .copied(); + + //And also the beginning ! + let mut input_buff = input + .split(' ') + .collect::>(); + _ = input_buff.pop(); + let mut input_origin = format!("{} ", input_buff.join(" ")); + + match input_searchee { + Some(s) => { + //Search happens 'round here + let current_dir = env::current_dir()?; + let mut all_res = String::new(); + let mut nbr_found: u16 = 0; + let mut last_found = String::new(); + + for file in fs::read_dir(current_dir)? { + let filepath = file.unwrap().path(); + let filename = filepath + .iter() + .last() + .unwrap() + .to_str() + .unwrap(); + let re = format!("^{}.*$", s); + let regex = Regex::new(&re).unwrap(); + if regex.is_match(filename) { + *&mut nbr_found += 1; + let matchline = format!("\r\n* {}", filename); + &mut all_res.push_str(&matchline); + //No need to find things we already found + if *prev_match != filename { + *&mut last_found = format!("{}{}", &input_origin, filename); + } + } + } + //Found one or zero, use what has been found directly + if nbr_found < 2 { + return Ok((last_found, String::new())); + //Otherwise, just display a list + } else { + return Ok((String::from(input), all_res)); + } + }, + None => { + return Ok((String::from(""), String::from(""))); + }, + }; +} + +fn autocomplete_cmd(input: &String) -> (String, String) { let found_bins = find_bin(input); if found_bins.len() == 1 { let aaa = found_bins.clone();