summaryrefslogtreecommitdiff
path: root/src/eval
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2022-05-03 16:59:13 +0200
committerLaurenz <laurmaedje@gmail.com>2022-05-04 00:14:31 +0200
commit507c5fc92563560426db0d86c0348880b0493467 (patch)
tree45116b62fb0fffe8e88d6c96ae1fcf11c73f8ee9 /src/eval
parente18a896a93cae987aa30addd40e678bf0064fd31 (diff)
Text replacement show rules
Diffstat (limited to 'src/eval')
-rw-r--r--src/eval/methods.rs16
-rw-r--r--src/eval/str.rs46
-rw-r--r--src/eval/value.rs10
3 files changed, 69 insertions, 3 deletions
diff --git a/src/eval/methods.rs b/src/eval/methods.rs
index b3674dff..363474fb 100644
--- a/src/eval/methods.rs
+++ b/src/eval/methods.rs
@@ -1,8 +1,9 @@
//! Methods on values.
-use super::{Args, StrExt, Value};
+use super::{Args, Regex, StrExt, Value};
use crate::diag::{At, TypResult};
use crate::syntax::Span;
+use crate::util::EcoString;
use crate::Context;
/// Call a method on a value.
@@ -66,6 +67,19 @@ pub fn call(
_ => missing()?,
},
+ Value::Dyn(dynamic) => {
+ if let Some(regex) = dynamic.downcast::<Regex>() {
+ match method {
+ "matches" => {
+ Value::Bool(regex.matches(&args.expect::<EcoString>("text")?))
+ }
+ _ => missing()?,
+ }
+ } else {
+ missing()?
+ }
+ }
+
_ => missing()?,
};
diff --git a/src/eval/str.rs b/src/eval/str.rs
index 3b4349a1..514bf318 100644
--- a/src/eval/str.rs
+++ b/src/eval/str.rs
@@ -1,3 +1,7 @@
+use std::fmt::{self, Debug, Formatter};
+use std::hash::{Hash, Hasher};
+use std::ops::Deref;
+
use super::{Array, Value};
use crate::diag::StrResult;
use crate::util::EcoString;
@@ -35,3 +39,45 @@ impl StrExt for EcoString {
}
}
}
+
+/// A regular expression.
+#[derive(Clone)]
+pub struct Regex(regex::Regex);
+
+impl Regex {
+ /// Create a new regex.
+ pub fn new(re: &str) -> StrResult<Self> {
+ regex::Regex::new(re).map(Self).map_err(|err| err.to_string())
+ }
+
+ /// Whether the regex matches the given `text`.
+ pub fn matches(&self, text: &str) -> bool {
+ self.0.is_match(text)
+ }
+}
+
+impl Deref for Regex {
+ type Target = regex::Regex;
+
+ fn deref(&self) -> &Self::Target {
+ &self.0
+ }
+}
+
+impl Debug for Regex {
+ fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
+ write!(f, "regex({:?})", self.0.as_str())
+ }
+}
+
+impl PartialEq for Regex {
+ fn eq(&self, other: &Self) -> bool {
+ self.0.as_str() == other.0.as_str()
+ }
+}
+
+impl Hash for Regex {
+ fn hash<H: Hasher>(&self, state: &mut H) {
+ self.0.as_str().hash(state);
+ }
+}
diff --git a/src/eval/value.rs b/src/eval/value.rs
index ba30348f..fc54cbce 100644
--- a/src/eval/value.rs
+++ b/src/eval/value.rs
@@ -5,7 +5,7 @@ use std::hash::{Hash, Hasher};
use std::num::NonZeroUsize;
use std::sync::Arc;
-use super::{ops, Args, Array, Dict, Func, RawLength};
+use super::{ops, Args, Array, Dict, Func, RawLength, Regex};
use crate::diag::{with_alternative, StrResult};
use crate::geom::{
Angle, Color, Dir, Em, Fraction, Length, Paint, Ratio, Relative, RgbaColor, Sides,
@@ -641,6 +641,10 @@ dynamic! {
Dir: "direction",
}
+dynamic! {
+ Regex: "regular expression",
+}
+
castable! {
usize,
Expected: "non-negative integer",
@@ -686,8 +690,10 @@ castable! {
castable! {
Pattern,
- Expected: "function",
+ Expected: "function, string or regular expression",
Value::Func(func) => Pattern::Node(func.node()?),
+ Value::Str(text) => Pattern::text(&text),
+ @regex: Regex => Pattern::Regex(regex.clone()),
}
#[cfg(test)]