Polish a few things (#67)

* Improve some match statements using macros

* Use `thiserror` instead of manually impl'ing Error
This commit is contained in:
T0mstone 2021-04-10 16:27:44 +02:00 committed by Keavon Chambers
parent a56f50c60c
commit 21ffb3571e
7 changed files with 145 additions and 75 deletions

21
Cargo.lock generated
View File

@ -60,6 +60,7 @@ dependencies = [
"graphite-document-core", "graphite-document-core",
"graphite-proc-macros", "graphite-proc-macros",
"log", "log",
"thiserror",
] ]
[[package]] [[package]]
@ -155,6 +156,26 @@ dependencies = [
"unicode-xid", "unicode-xid",
] ]
[[package]]
name = "thiserror"
version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e0f4a65597094d4483ddaed134f409b2cb7c1beccf25201a9f73c719254fa98e"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7765189610d8241a44529806d6fd1f2e0a08734313a35d5b3a556f92b381f3c0"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "unicode-xid" name = "unicode-xid"
version = "0.2.1" version = "0.2.1"

View File

@ -24,41 +24,54 @@ impl Color {
} }
} }
macro_rules! match_string_to_enum {
(match ($e:expr) {$($var:ident),* $(,)?}) => {
match $e {
$(
stringify!($var) => Some($var),
)*
_ => None
}
};
}
pub fn translate_tool(name: &str) -> Option<ToolType> { pub fn translate_tool(name: &str) -> Option<ToolType> {
match name { use ToolType::*;
"Select" => Some(ToolType::Select),
"Crop" => Some(ToolType::Crop), match_string_to_enum!(match (name) {
"Navigate" => Some(ToolType::Navigate), Select,
"Sample" => Some(ToolType::Sample), Crop,
"Text" => Some(ToolType::Text), Navigate,
"Fill" => Some(ToolType::Fill), Sample,
"Gradient" => Some(ToolType::Gradient), Text,
"Brush" => Some(ToolType::Brush), Fill,
"Heal" => Some(ToolType::Heal), Gradient,
"Clone" => Some(ToolType::Clone), Brush,
"Patch" => Some(ToolType::Patch), Heal,
"BlurSharpen" => Some(ToolType::BlurSharpen), Clone,
"Relight" => Some(ToolType::Relight), Patch,
"Path" => Some(ToolType::Path), BlurSharpen,
"Pen" => Some(ToolType::Pen), Relight,
"Freehand" => Some(ToolType::Freehand), Path,
"Spline" => Some(ToolType::Spline), Pen,
"Line" => Some(ToolType::Line), Freehand,
"Rectangle" => Some(ToolType::Rectangle), Spline,
"Ellipse" => Some(ToolType::Ellipse), Line,
"Shape" => Some(ToolType::Shape), Rectangle,
_ => None, Ellipse,
} Shape
})
} }
pub fn translate_append_mode(name: &str) -> Option<SelectAppendMode> { pub fn translate_append_mode(name: &str) -> Option<SelectAppendMode> {
match name { use SelectAppendMode::*;
"New" => Some(SelectAppendMode::New),
"Add" => Some(SelectAppendMode::Add), match_string_to_enum!(match (name) {
"Subtract" => Some(SelectAppendMode::Subtract), New,
"Intersect" => Some(SelectAppendMode::Intersect), Add,
_ => None, Subtract,
} Intersect
})
} }
pub fn translate_key(name: &str) -> events::Key { pub fn translate_key(name: &str) -> events::Key {

View File

@ -11,6 +11,7 @@ license = "Apache-2.0"
[dependencies] [dependencies]
log = "0.4" log = "0.4"
bitflags = "1.2.1" bitflags = "1.2.1"
thiserror = "1.0.24"
[dependencies.document-core] [dependencies.document-core]
path = "../document" path = "../document"

View File

@ -31,10 +31,14 @@ pub enum Response {
impl fmt::Display for Response { impl fmt::Display for Response {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
match self { use Response::*;
Response::UpdateCanvas { document: _ } => write!(formatter, "UpdateCanvas"),
Response::SetActiveTool { tool_name: _ } => write!(formatter, "SetActiveTool"), let name = match_variant_name!(match (self) {
} UpdateCanvas,
SetActiveTool
});
formatter.write_str(name)
} }
} }

View File

@ -1,32 +1,22 @@
use crate::events::Event; use crate::events::Event;
use crate::Color; use crate::Color;
use std::error::Error; use thiserror::Error;
use std::fmt::{self, Display};
/// The error type used by the Graphite editor. /// The error type used by the Graphite editor.
#[derive(Clone, Debug)] #[derive(Clone, Debug, Error)]
pub enum EditorError { pub enum EditorError {
#[error("Failed to execute operation: {0}")]
InvalidOperation(String), InvalidOperation(String),
#[error("Failed to dispatch event: {0}")]
InvalidEvent(String), InvalidEvent(String),
#[error("{0}")]
Misc(String), Misc(String),
#[error("Tried to construct an invalid color {0:?}")]
Color(String), Color(String),
#[error("The requested tool does not exist")]
UnknownTool, UnknownTool,
} }
impl Display for EditorError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
EditorError::InvalidOperation(e) => write!(f, "Failed to execute operation: {}", e),
EditorError::InvalidEvent(e) => write!(f, "Failed to dispatch event: {}", e),
EditorError::Misc(e) => write!(f, "{}", e),
EditorError::Color(c) => write!(f, "Tried to construct an invalid color {:?}", c),
EditorError::UnknownTool => write!(f, "The requested tool does not exist"),
}
}
}
impl Error for EditorError {}
macro_rules! derive_from { macro_rules! derive_from {
($type:ty, $kind:ident) => { ($type:ty, $kind:ident) => {
impl From<$type> for EditorError { impl From<$type> for EditorError {

View File

@ -47,3 +47,40 @@ macro_rules! gen_tools_hash_map {
hash_map hash_map
}}; }};
} }
/// Creates a string representation of an enum value that exactly matches the given name of each enum variant
///
/// # Example
///
/// ```ignore
/// enum E {
/// A(u8),
/// B
/// }
///
/// // this line is important
/// use E::*;
///
/// let a = E::A(7);
/// let s = match_variant_name!(match (a) { A, B });
/// ```
///
/// expands to
///
/// ```ignore
/// // ...
///
/// let s = match a {
/// A { .. } => "A",
/// B { .. } => "B"
/// };
/// ```
macro_rules! match_variant_name {
(match ($e:expr) { $($v:ident),* $(,)? }) => {
match $e {
$(
$v { .. } => stringify!(v)
),*
}
};
}

View File

@ -124,29 +124,33 @@ pub enum ToolType {
impl fmt::Display for ToolType { impl fmt::Display for ToolType {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
match self { use ToolType::*;
ToolType::Select => write!(formatter, "Select"),
ToolType::Crop => write!(formatter, "Crop"), let name = match_variant_name!(match (self) {
ToolType::Navigate => write!(formatter, "Navigate"), Select,
ToolType::Sample => write!(formatter, "Sample"), Crop,
ToolType::Text => write!(formatter, "Text"), Navigate,
ToolType::Fill => write!(formatter, "Fill"), Sample,
ToolType::Gradient => write!(formatter, "Gradient"), Text,
ToolType::Brush => write!(formatter, "Brush"), Fill,
ToolType::Heal => write!(formatter, "Heal"), Gradient,
ToolType::Clone => write!(formatter, "Clone"), Brush,
ToolType::Patch => write!(formatter, "Patch"), Heal,
ToolType::BlurSharpen => write!(formatter, "BlurSharpen"), Clone,
ToolType::Relight => write!(formatter, "Relight"), Patch,
ToolType::Path => write!(formatter, "Path"), BlurSharpen,
ToolType::Pen => write!(formatter, "Pen"), Relight,
ToolType::Freehand => write!(formatter, "Freehand"), Path,
ToolType::Spline => write!(formatter, "Spline"), Pen,
ToolType::Line => write!(formatter, "Line"), Freehand,
ToolType::Rectangle => write!(formatter, "Rectangle"), Spline,
ToolType::Ellipse => write!(formatter, "Ellipse"), Line,
ToolType::Shape => write!(formatter, "Shape"), Rectangle,
} Ellipse,
Shape
});
formatter.write_str(name)
} }
} }