From f47bf23f6aac16dbd67dfd2718ca3fec2dbf6656 Mon Sep 17 00:00:00 2001 From: iff Date: Sat, 7 Dec 2024 17:14:47 +0100 Subject: [PATCH] refactor: reuse executable list --- src/modes.rs | 2 +- src/replaces.rs | 6 +++--- src/rules.rs | 1 + src/runtime_rules.rs | 10 +++++++--- src/shell.rs | 18 ++++++++++++++++++ src/suggestions.rs | 27 ++------------------------- src/system.rs | 13 +++---------- 7 files changed, 35 insertions(+), 42 deletions(-) diff --git a/src/modes.rs b/src/modes.rs index d5cbc3d..3268ae9 100644 --- a/src/modes.rs +++ b/src/modes.rs @@ -86,7 +86,7 @@ pub fn cnf(data: &mut Data) { suggestion(data); } } else { - let package_manager = match system::get_package_manager(&shell) { + let package_manager = match system::get_package_manager(data) { Some(package_manager) => package_manager, None => { return; diff --git a/src/replaces.rs b/src/replaces.rs index 0b81820..2a8cc99 100644 --- a/src/replaces.rs +++ b/src/replaces.rs @@ -94,7 +94,7 @@ pub fn command(suggest: &mut String, split_command: &[String]) { } } -pub fn typo(suggest: &mut String, split_command: &[String], shell: &str) { +pub fn typo(suggest: &mut String, split_command: &[String], executables: &[String], shell: &str) { while suggest.contains("{{typo") { let (placeholder, args) = eval_placeholder(suggest, "{{typo", "}}"); @@ -160,9 +160,9 @@ pub fn typo(suggest: &mut String, split_command: &[String], shell: &str) { let function = match_list.join(","); let (_, args) = eval_placeholder(&function, "{{shell", "}}"); let function = &function[args.to_owned()].trim_matches(|c| c == '(' || c == ')'); - suggest_typo(&split_command[index], eval_shell_command(shell, function)) + suggest_typo(&split_command[index], eval_shell_command(shell, function), executables) } else { - suggest_typo(&split_command[index], match_list) + suggest_typo(&split_command[index], match_list, executables) }; suggest.replace_range(placeholder, &command); diff --git a/src/rules.rs b/src/rules.rs index 680d608..3474832 100644 --- a/src/rules.rs +++ b/src/rules.rs @@ -6,5 +6,6 @@ pub fn match_pattern(executable: &str, data: &mut Data) { let error_msg = &data.error.clone(); let shell = &data.shell.clone(); let last_command = &data.command.clone(); + let executables = &data.get_executables().clone(); parse_rules!("rules"); } diff --git a/src/runtime_rules.rs b/src/runtime_rules.rs index f3a07e7..4c926f3 100644 --- a/src/runtime_rules.rs +++ b/src/runtime_rules.rs @@ -25,6 +25,7 @@ pub fn runtime_match(executable: &str, data: &mut Data) { let shell = &data.shell.clone(); let last_command = &data.command.clone(); let error_msg = &data.error.clone(); + let executables = &data.get_executables().clone(); let mut pure_suggest; @@ -66,6 +67,7 @@ pub fn runtime_match(executable: &str, data: &mut Data) { last_command, error_msg, split_command, + data, ) == reverse { continue 'suggest; @@ -84,6 +86,7 @@ pub fn runtime_match(executable: &str, data: &mut Data) { &pure_suggest, last_command, error_msg, + executables, shell, )); } @@ -99,9 +102,10 @@ fn eval_condition( last_command: &str, error_msg: &str, split_command: &[String], + data: &mut Data ) -> bool { match condition { - "executable" => check_executable(shell, arg), + "executable" => data.has_executable(arg), "err_contains" => error_msg.contains(arg), "cmd_contains" => last_command.contains(arg), "min_length" => split_command.len() >= arg.parse::().unwrap(), @@ -112,7 +116,7 @@ fn eval_condition( } } -fn eval_suggest(suggest: &str, last_command: &str, error_msg: &str, shell: &str) -> String { +fn eval_suggest(suggest: &str, last_command: &str, error_msg: &str, executables: &[String], shell: &str) -> String { let mut suggest = suggest.to_owned(); if suggest.contains("{{command}}") { suggest = suggest.replace("{{command}}", "{last_command}"); @@ -128,7 +132,7 @@ fn eval_suggest(suggest: &str, last_command: &str, error_msg: &str, shell: &str) replaces::err(&mut suggest, error_msg); replaces::command(&mut suggest, &split_command); replaces::shell(&mut suggest, shell); - replaces::typo(&mut suggest, &split_command, shell); + replaces::typo(&mut suggest, &split_command, executables, shell); for (tag, value) in opt_list { suggest = suggest.replace(&tag, &value); diff --git a/src/shell.rs b/src/shell.rs index a018880..dc1d74d 100644 --- a/src/shell.rs +++ b/src/shell.rs @@ -7,6 +7,8 @@ use std::time::Duration; use regex_lite::Regex; +use crate::files::get_path_files; + pub const PRIVILEGE_LIST: [&str; 2] = ["sudo", "doas"]; pub enum Mode { @@ -23,6 +25,7 @@ pub struct Data { pub alias: Option>, pub privilege: Option, pub error: String, + pub executables: Vec, pub mode: Mode, } @@ -49,6 +52,7 @@ impl Data { split: vec![], privilege: None, error: "".to_string(), + executables: vec![], mode, }; @@ -119,6 +123,20 @@ impl Data { self.candidates.push(candidate.to_string()); } } + + pub fn get_executables(&mut self) -> &Vec { + if self.executables.is_empty() { + self.executables = get_path_files(); + } + &self.executables + } + + pub fn has_executable(&mut self, executable: &str) -> bool { + if self.executables.is_empty() { + self.executables = get_path_files(); + } + self.executables.contains(&executable.to_string()) + } } pub fn split_command(command: &str) -> Vec { diff --git a/src/suggestions.rs b/src/suggestions.rs index 159eb1c..4b88f48 100644 --- a/src/suggestions.rs +++ b/src/suggestions.rs @@ -124,25 +124,6 @@ pub fn select_candidate(data: &mut Data) { data.candidates.clear(); } -pub fn check_executable(shell: &str, executable: &str) -> bool { - match shell { - "nu" => std::process::Command::new(shell) - .arg("-c") - .arg(format!("if (which {} | is-empty) {{ exit 1 }}", executable)) - .output() - .expect("failed to execute process") - .status - .success(), - _ => std::process::Command::new(shell) - .arg("-c") - .arg(format!("command -v {}", executable)) - .output() - .expect("failed to execute process") - .status - .success(), - } -} - pub fn opt_regex(regex: &str, command: &mut String) -> String { let regex = Regex::new(regex).unwrap(); @@ -212,18 +193,14 @@ pub fn split_command(command: &str) -> Vec { split_command } -pub fn suggest_typo(typos: &[String], candidates: Vec) -> String { - let mut path_files = Vec::new(); +pub fn suggest_typo(typos: &[String], candidates: Vec, executables: &[String]) -> String { let mut suggestions = Vec::new(); for typo in typos { let typo = typo.as_str(); if candidates.len() == 1 { match candidates[0].as_str() { "path" => { - if path_files.is_empty() { - path_files = get_path_files(); - }; - if let Some(suggest) = find_similar(typo, &path_files, Some(2)) { + if let Some(suggest) = find_similar(typo, executables, Some(2)) { suggestions.push(suggest); } else { suggestions.push(typo.to_string()); diff --git a/src/system.rs b/src/system.rs index f469de1..95010ff 100644 --- a/src/system.rs +++ b/src/system.rs @@ -1,20 +1,13 @@ use std::io::stderr; use std::process::Command; use std::process::Stdio; +use crate::shell::Data; -pub fn get_package_manager(shell: &str) -> Option { +pub fn get_package_manager(data: &mut Data) -> Option { let package_managers = vec!["pacman"]; for package_manager in package_managers { - let success = Command::new(shell) - .arg("-c") - .arg(format!("command -v {}", package_manager)) - .output() - .expect("failed to execute process") - .status - .success(); - - if success { + if data.has_executable(package_manager) { return Some(package_manager.to_string()); } }