diff options
| author | Laurenz <laurmaedje@gmail.com> | 2022-05-03 16:59:13 +0200 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2022-05-04 00:14:31 +0200 |
| commit | 507c5fc92563560426db0d86c0348880b0493467 (patch) | |
| tree | 45116b62fb0fffe8e88d6c96ae1fcf11c73f8ee9 /src/eval | |
| parent | e18a896a93cae987aa30addd40e678bf0064fd31 (diff) | |
Text replacement show rules
Diffstat (limited to 'src/eval')
| -rw-r--r-- | src/eval/methods.rs | 16 | ||||
| -rw-r--r-- | src/eval/str.rs | 46 | ||||
| -rw-r--r-- | src/eval/value.rs | 10 |
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)] |
