feat: multi-directory typo suggestion

This commit is contained in:
iff 2023-08-07 17:12:38 +02:00
parent 77b0793076
commit b9943fb777
2 changed files with 29 additions and 15 deletions

View file

@ -1,3 +1,5 @@
use crate::suggestions::find_similar;
pub fn get_path_files() -> Vec<String> { pub fn get_path_files() -> Vec<String> {
let path = std::env::var("PATH").unwrap(); let path = std::env::var("PATH").unwrap();
let path = path.split(':').collect::<Vec<&str>>(); let path = path.split(':').collect::<Vec<&str>>();
@ -16,26 +18,40 @@ pub fn get_path_files() -> Vec<String> {
all_executable all_executable
} }
pub fn get_directory_files(input: &str) -> Vec<String> { pub fn get_best_match_file(input: &str) -> Option<String> {
let mut input = input.trim_matches(|c| c == '\'' || c == '"').to_owned(); let mut input = input.trim_matches(|c| c == '\'' || c == '"').to_owned();
let files = loop { let mut exit_dirs = Vec::new();
let mut files = loop {
match std::fs::read_dir(&input) { match std::fs::read_dir(&input) {
Ok(files) => break files, Ok(files) => break files,
Err(_) => { Err(_) => {
if let Some((dirs, _)) = input.rsplit_once('/') { if let Some((dirs, exit_dir)) = input.rsplit_once('/') {
exit_dirs.push(exit_dir.to_owned());
input = dirs.to_owned(); input = dirs.to_owned();
} else { } else {
exit_dirs.push(input.to_owned());
input = ".".to_owned();
break std::fs::read_dir("./").unwrap(); break std::fs::read_dir("./").unwrap();
} }
} }
} }
}; };
let mut all_files = vec![]; while let Some(exit_dir) = exit_dirs.pop() {
for file in files { let dir_files = files.filter_map(|file| {
let file = file.unwrap(); let file = file.unwrap();
let file_name = file.path().to_str().unwrap().to_owned(); let file_name = file.file_name().into_string().unwrap();
all_files.push(file_name); Some(file_name)
}).collect::<Vec<String>>();
let best_match = find_similar(&exit_dir, dir_files);
input = format!("{}/{}", input, best_match.unwrap());
files = match std::fs::read_dir(&input) {
Ok(files) => files,
Err(_) => return Some(input),
};
} }
all_files
Some(input)
} }

View file

@ -2,7 +2,7 @@ use regex_lite::Regex;
use rule_parser::parse_rules; use rule_parser::parse_rules;
use crate::files::{get_directory_files, get_path_files}; use crate::files::{get_best_match_file, get_path_files};
use crate::shell::{command_output, PRIVILEGE_LIST}; use crate::shell::{command_output, PRIVILEGE_LIST};
pub fn suggest_command(shell: &str, last_command: &str) -> Option<String> { pub fn suggest_command(shell: &str, last_command: &str) -> Option<String> {
@ -105,8 +105,7 @@ fn suggest_typo(typo: &str, candidates: Vec<String>) -> String {
} }
} }
"file" => { "file" => {
let files = get_directory_files(typo); if let Some(suggest) = get_best_match_file(typo) {
if let Some(suggest) = find_similar(typo, files) {
suggestion = suggest; suggestion = suggest;
} }
} }
@ -115,7 +114,6 @@ fn suggest_typo(typo: &str, candidates: Vec<String>) -> String {
} else if let Some(suggest) = find_similar(typo, candidates) { } else if let Some(suggest) = find_similar(typo, candidates) {
suggestion = suggest; suggestion = suggest;
} }
suggestion suggestion
} }
@ -158,8 +156,8 @@ fn compare_string(a: &str, b: &str) -> usize {
matrix[a.chars().count()][b.chars().count()] matrix[a.chars().count()][b.chars().count()]
} }
pub fn confirm_suggestion(shell: &str, command: &str) { pub fn confirm_suggestion(shell: &str, command: &str, highlighted: &str) {
println!{"{}\n", command} println!{"{}\n", highlighted}
println!("Press enter to execute the suggestion. Or press Ctrl+C to exit."); println!("Press enter to execute the suggestion. Or press Ctrl+C to exit.");
std::io::stdin().read_line(&mut String::new()).unwrap(); std::io::stdin().read_line(&mut String::new()).unwrap();