add command usage hint after syntax error

This commit is contained in:
user622628252416
2024-08-19 18:33:06 +02:00
parent 943f8fcd4c
commit 40b2fdc45f
3 changed files with 50 additions and 2 deletions

View File

@@ -19,7 +19,7 @@ pub(crate) struct CommandDispatcher<'a> {
}
impl <'a> CommandDispatcher<'a> {
pub(crate) fn dispatch(&'a self, src: &mut CommandSender, cmd: &str) -> Result<(), &str> {
pub(crate) fn dispatch(&'a self, src: &mut CommandSender, cmd: &str) -> Result<(), String> {
let mut parts = cmd.split_ascii_whitespace();
let key = parts.next().ok_or("Empty Command")?;
@@ -31,9 +31,11 @@ impl <'a> CommandDispatcher<'a> {
match Self::try_path(src, path, tree, raw_args.clone()) {
Err(InvalidConsumptionError(s)) => {
println!("Error while parsing command \"{cmd}\": {s:?} was consumed, but couldn't be parsed");
return Err("Internal Error (See logs for details)".into())
},
Err(InvalidRequirementError) => {
println!("Error while parsing command \"{cmd}\": a requirement that was expected was not met.");
return Err("Internal Error (See logs for details)".into())
},
Ok(fitting_path) => {
if fitting_path { return Ok(()) }
@@ -41,7 +43,7 @@ impl <'a> CommandDispatcher<'a> {
}
}
Err("Invalid Syntax: ")
Err(format!("Invalid Syntax. Usage:{}", tree.paths_formatted(key)))
}
fn try_path(src: &mut CommandSender, path: Vec<usize>, tree: &CommandTree, mut raw_args: RawArgs) -> Result<bool, InvalidTreeError> {

View File

@@ -4,6 +4,8 @@ use pumpkin_text::TextComponent;
use crate::client::Client;
use crate::commands::dispatcher::CommandDispatcher;
use crate::server::Server;
mod cmd_gamemode;
mod cmd_pumpkin;
mod cmd_stop;
@@ -11,6 +13,7 @@ mod tree;
mod tree_builder;
mod dispatcher;
mod arg_player;
mod cmd_teleport;
pub enum CommandSender<'a> {
Rcon(&'a mut Vec<String>),

View File

@@ -50,6 +50,49 @@ impl <'a> CommandTree<'a> {
todo,
}
}
pub(crate) fn paths_formatted(&'a self, name: &str) -> String {
let paths: Vec<Vec<&NodeType>> = self.iter_paths()
.map(|path| path.iter().map(|&i| &self.nodes[i].node_type).collect())
.collect();
let len = paths.iter()
.map(|path| path.iter()
.map(|node| match node {
NodeType::ExecuteLeaf { .. } => 0,
NodeType::Literal { string } => string.len() + 1,
NodeType::Argument { name, .. } => name.len() + 3,
NodeType::Require { .. } => 0,
})
.sum::<usize>() + name.len() + 2
)
.sum::<usize>();
let mut s = String::with_capacity(len);
for path in paths {
s.push('\n');
s.push('/');
s.push_str(name);
for node in path {
match node {
NodeType::Literal { string } => {
s.push(' ');
s.push_str(string);
}
NodeType::Argument { name, .. } => {
s.push(' ');
s.push('<');
s.push_str(name);
s.push('>');
}
_ => {}
}
}
}
s
}
}
struct TraverseAllPathsIter<'a> {