Autocomplete works for files

This commit is contained in:
Justine Pelletreau 2023-02-02 16:51:52 +01:00
parent f7e6063778
commit 4e27fe3106
2 changed files with 84 additions and 3 deletions

View File

@ -236,6 +236,12 @@ pub mod shell {
let mut current_pos: usize = 0; let mut current_pos: usize = 0;
let mut max_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 //Initialize
write!(stdout, "\r\n SquiShell (sqish)--- \r\n{}", prompt); write!(stdout, "\r\n SquiShell (sqish)--- \r\n{}", prompt);
stdout.flush(); stdout.flush();
@ -244,7 +250,13 @@ pub mod shell {
match c.unwrap() { match c.unwrap() {
Key::Char('\t') => { 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); write!(stdout, "\r\n{}\r\n", list);
mycommand.clear(); mycommand.clear();
mycommand.push_str(&res); mycommand.push_str(&res);
@ -255,6 +267,7 @@ pub mod shell {
} }
Key::Char('\n') => { Key::Char('\n') => {
*&mut prev_autocomplete = String::new();
current_number = get_curr_history_number(); current_number = get_curr_history_number();
prompt = build_prompt(&current_number); prompt = build_prompt(&current_number);
current_pos = 0; current_pos = 0;

View File

@ -1,10 +1,78 @@
use which::which_re; use which::which_re;
use regex::Regex; use regex::Regex;
use std::path::PathBuf; 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::<Vec<&str>>()
.last()
.copied();
//And also the beginning !
let mut input_buff = input
.split(' ')
.collect::<Vec<&str>>();
_ = 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); let found_bins = find_bin(input);
if found_bins.len() == 1 { if found_bins.len() == 1 {
let aaa = found_bins.clone(); let aaa = found_bins.clone();