polish repl (#17)

* add less daunting panic message on release builds
This commit is contained in:
Chance 2024-12-21 14:35:55 -05:00 committed by BitSyndicate
parent a737369d11
commit f76245835d
WARNING! Although there is a key with this ID in the database it does not verify this commit! This commit is SUSPICIOUS.
GPG key ID: 443E4198D6BBA6DE
17 changed files with 405 additions and 106 deletions

View file

@ -29,7 +29,6 @@ macro_rules! alias {
};
}
fn hamming_distance(a: &str, b: &str) -> Option<usize> {
if a.len() != b.len() {
return None;
@ -71,7 +70,7 @@ fn check_similarity(target: &str) -> Option<String> {
let mut best_match: Option<String> = None;
let mut best_distance = usize::MAX;
for (cmd_name,_) in COMMAND_MANAGER.read().get_commands() {
for (cmd_name, _) in COMMAND_MANAGER.read().get_commands() {
if let Some(hamming_dist) = hamming_distance(target, cmd_name) {
if hamming_dist <= max_hamming_distance && hamming_dist < best_distance {
best_distance = hamming_dist;
@ -92,6 +91,7 @@ fn check_similarity(target: &str) -> Option<String> {
pub struct CommandManager {
pub commands: HashMap<String, Box<dyn Command>>,
pub aliases: HashMap<String, String>,
pub categories: HashMap<String, Category>,
}
impl CommandManager {
@ -99,53 +99,99 @@ impl CommandManager {
CommandManager {
commands: HashMap::new(),
aliases: HashMap::new(),
categories: HashMap::new(),
}
}
pub fn add_category(&mut self, category: Category) {
self.categories.insert(category.name.clone(), category);
}
pub fn get_commands(&self) -> std::collections::hash_map::Iter<'_, String, Box<dyn Command>> {
self.commands.iter()
}
pub fn execute_command(&self,command: &str,args: Option<Vec<String>>) -> Result<(),anyhow::Error> {
pub fn execute_command(
&self,
command: &str,
args: Option<Vec<String>>,
) -> Result<(), anyhow::Error> {
if let Some(command) = self.commands.get(command) {
command.execute(args)?;
Ok(())
} else {
println!("Command '{}' not found.", command);
let corrected_cmd = check_similarity(command);
if corrected_cmd.is_some() {
println!("Command: {} was not found. Did you mean {}?",command.red().bold(),corrected_cmd
.expect("A command was editied during execution, something has gone seriously wrong").green().bold().italic());
return Ok(());
}
Ok(())
Err(anyhow::anyhow!("Command '{}' not found.", command))
}
}
pub fn execute(&self, command: &str,args: Option<Vec<String>>) -> Result<(), anyhow::Error> {
pub fn execute(&self, command: &str, args: Option<Vec<String>>) -> Result<(), anyhow::Error> {
match self.aliases.get(command) {
Some(command) => self.execute(command,args),
Some(command) => self.execute(command, args),
// check to see if we are using an alias or the command just doesnt exist
None => {
self.execute_command(command,args)?;
self.execute_command(command, args)?;
Ok(())
},
}
}
}
pub fn add_command(&mut self, command: Box<dyn Command>) {
self.commands.insert(command.get_name().to_lowercase(), command);
self.commands
.insert(command.get_name().to_lowercase(), command);
}
pub fn add_command_with_category(&mut self, command: Box<dyn Command>, category: Category) {
if self.categories.contains_key(&category.name) {
let mut cmd_name = command.get_name().to_lowercase();
cmd_name.insert_str(0, &format!("{}_", &&category.uid.to_lowercase()));
println!("{}", cmd_name);
self.commands.insert(cmd_name, command);
} else {
panic!("Category {} does not exist", category.name);
}
}
pub fn add_alias(&mut self, alias: &str, command: &str) {
self.aliases.insert(alias.to_string(), command.to_string());
self.aliases.insert(
alias.to_string().to_lowercase(),
command.to_string().to_lowercase(),
);
}
}
#[derive(Debug, Clone)]
pub struct Category {
// eg: Zenyx -> Z
// eg: core -> cr
// eg: exitcmd -> cr_exit
// eg: echo -> z_echo
pub uid: String,
// eg: Zenyx
pub name: String,
// eg: Zenyx internal commands
pub description: String,
}
impl Category {
pub fn new(uid: &str, name: &str, description: &str) -> Self {
Self {
uid: uid.to_string(),
name: name.to_string(),
description: description.to_string(),
}
}
}
pub trait Command: Send + Sync {
fn execute(&self, args: Option<Vec<String>>) -> Result<(),anyhow::Error>;
fn execute(&self, args: Option<Vec<String>>) -> Result<(), anyhow::Error>;
fn undo(&self);
fn redo(&self);
fn get_description(&self) -> String;
fn get_name(&self) -> String;
fn get_help(&self) -> String;
fn get_params(&self) -> String;
}
}