aboutsummaryrefslogtreecommitdiff
path: root/src/cli/cmd/mod.rs
diff options
context:
space:
mode:
authorArne Dußin2021-01-06 22:56:37 +0100
committerArne Dußin2021-01-06 22:56:37 +0100
commitfa1afb6be3ba2d521eb0791edc0bb8e631a85327 (patch)
treee0a365444784efaaeb1eea6373b34559b6d57fbc /src/cli/cmd/mod.rs
parent1c81d7c70fe891e6ded49d49d6a09f04ce74dd6e (diff)
parent30b23db9e86fdf72a4e7de72213df274ce19123e (diff)
downloadgraf_karto-fa1afb6be3ba2d521eb0791edc0bb8e631a85327.tar.gz
graf_karto-fa1afb6be3ba2d521eb0791edc0bb8e631a85327.zip
Merge branch 'master' into snapping
Diffstat (limited to 'src/cli/cmd/mod.rs')
-rw-r--r--src/cli/cmd/mod.rs59
1 files changed, 59 insertions, 0 deletions
diff --git a/src/cli/cmd/mod.rs b/src/cli/cmd/mod.rs
new file mode 100644
index 0000000..42e865a
--- /dev/null
+++ b/src/cli/cmd/mod.rs
@@ -0,0 +1,59 @@
+//! The commands that can be performed in the CLI
+
+pub mod edit;
+pub mod read;
+pub mod save;
+
+pub use edit::*;
+pub use read::*;
+pub use save::*;
+
+use crate::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(Save::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>;
+}