refactor: reuse executable list

This commit is contained in:
iff 2024-12-07 17:14:47 +01:00
parent 0ab8f269a1
commit f47bf23f6a
7 changed files with 35 additions and 42 deletions

View file

@ -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;

View file

@ -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);

View file

@ -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");
}

View file

@ -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::<usize>().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);

View file

@ -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<HashMap<String, String>>,
pub privilege: Option<String>,
pub error: String,
pub executables: Vec<String>,
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<String> {
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<String> {

View file

@ -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<String> {
split_command
}
pub fn suggest_typo(typos: &[String], candidates: Vec<String>) -> String {
let mut path_files = Vec::new();
pub fn suggest_typo(typos: &[String], candidates: Vec<String>, 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());

View file

@ -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<String> {
pub fn get_package_manager(data: &mut Data) -> Option<String> {
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());
}
}