1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
|
//! The commands that can be performed in the CLI
pub mod edit;
pub mod read;
pub mod write;
pub use edit::*;
pub use read::*;
pub use write::*;
use crate::client::Editor;
use std::ops::RangeInclusive;
/// Errors that can occur when parsing a command. This is for syntax checking, the
/// semantics are checked when trying to execute the command.
#[allow(missing_docs)]
#[derive(thiserror::Error, Debug)]
pub enum CmdParseError {
#[error("no command specified")]
StringEmpty,
#[error("the command {0} is unknown")]
NoSuchCmd(String),
#[error("wrong number of arguments. Expected in range {1:?}, but received {0}")]
WrongNumberOfArgs(usize, RangeInclusive<usize>),
#[error("{0} cannot be converted into a {1}, which is required")]
InvalidArgType(String, &'static str),
}
/// Attempts to parse a command from the given string. If it is unsuccessful, it returns a
/// [CmdParseError].
pub fn parse_command(string: &str) -> Result<Box<dyn Command>, CmdParseError> {
if string.is_empty() {
return Err(CmdParseError::StringEmpty);
}
let parts: Vec<&str> = string.split_whitespace().collect();
match parts[0] {
"w" => Ok(Box::new(Write::from_args(&parts[1..])?)),
"e" => Ok(Box::new(Edit::from_args(&parts[1..])?)),
"r" => Ok(Box::new(Read::from_args(&parts[1..])?)),
other => Err(CmdParseError::NoSuchCmd(other.to_owned())),
}
}
/// Indicates that this entity (command) can be created from arguments. Make sure to check what is
/// expected, to pass the arguments to the correct command.
pub trait FromArgs: Sized {
/// Creates a new instance from the arguments provided. If for whatever reason the syntax of the
/// given arguments is correct an [ArgParseError] is returned.
fn from_args(args: &[&str]) -> Result<Self, CmdParseError>;
}
/// A common trait for all commands.
pub trait Command {
/// Process this command on the provided context. Returns either a string with the output of the
/// command when everything went right with it, or an error string explaining what went wrong,
/// which can be displayed to the user.
fn process(&self, editor: &mut Editor) -> Result<String, String>;
}
|