diff options
| author | Laurenz <laurmaedje@gmail.com> | 2022-11-02 14:48:51 +0100 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2022-11-02 14:48:51 +0100 |
| commit | 56342bd972a13ffe21beaf2b87ab7eb1597704b4 (patch) | |
| tree | 78f9549141e753dde4a938670c54f3fe8695a058 /src/model/recipe.rs | |
| parent | 37ac5d966ebaf97ac79c507028cd5b742b510b89 (diff) | |
Move layout traits into library
Diffstat (limited to 'src/model/recipe.rs')
| -rw-r--r-- | src/model/recipe.rs | 185 |
1 files changed, 0 insertions, 185 deletions
diff --git a/src/model/recipe.rs b/src/model/recipe.rs deleted file mode 100644 index c687f4fb..00000000 --- a/src/model/recipe.rs +++ /dev/null @@ -1,185 +0,0 @@ -use std::fmt::{self, Debug, Formatter}; -use std::hash::Hash; - -use comemo::Tracked; - -use super::{ - Args, Capability, Content, Func, Interruption, Node, NodeId, Regex, StyleChain, - StyleEntry, Value, -}; -use crate::diag::SourceResult; -use crate::library::structure::{DescNode, EnumNode, ListNode}; -use crate::library::text::TextNode; -use crate::syntax::Spanned; -use crate::World; - -/// A show rule recipe. -#[derive(Clone, PartialEq, Hash)] -pub struct Recipe { - /// The patterns to customize. - pub pattern: Pattern, - /// The function that defines the recipe. - pub func: Spanned<Func>, -} - -impl Recipe { - /// Whether the recipe is applicable to the target. - pub fn applicable(&self, target: Target) -> bool { - match (&self.pattern, target) { - (Pattern::Node(id), Target::Node(node)) => *id == node.id(), - (Pattern::Regex(_), Target::Text(_)) => true, - _ => false, - } - } - - /// Try to apply the recipe to the target. - pub fn apply( - &self, - world: Tracked<dyn World>, - sel: Selector, - target: Target, - ) -> SourceResult<Option<Content>> { - let content = match (target, &self.pattern) { - (Target::Node(node), &Pattern::Node(id)) if node.id() == id => { - let node = node.to::<dyn Show>().unwrap().unguard_parts(sel); - self.call(world, || Value::Content(node))? - } - - (Target::Text(text), Pattern::Regex(regex)) => { - let mut result = vec![]; - let mut cursor = 0; - - for mat in regex.find_iter(text) { - let start = mat.start(); - if cursor < start { - result.push(TextNode(text[cursor .. start].into()).pack()); - } - - result.push(self.call(world, || Value::Str(mat.as_str().into()))?); - cursor = mat.end(); - } - - if result.is_empty() { - return Ok(None); - } - - if cursor < text.len() { - result.push(TextNode(text[cursor ..].into()).pack()); - } - - Content::sequence(result) - } - - _ => return Ok(None), - }; - - Ok(Some(content.styled_with_entry(StyleEntry::Guard(sel)))) - } - - /// Call the recipe function, with the argument if desired. - fn call<F>(&self, world: Tracked<dyn World>, arg: F) -> SourceResult<Content> - where - F: FnOnce() -> Value, - { - let args = if self.func.v.argc() == Some(0) { - Args::new(self.func.span, []) - } else { - Args::new(self.func.span, [arg()]) - }; - - Ok(self.func.v.call_detached(world, args)?.display(world)) - } - - /// What kind of structure the property interrupts. - pub fn interruption(&self) -> Option<Interruption> { - if let Pattern::Node(id) = self.pattern { - if id == NodeId::of::<ListNode>() - || id == NodeId::of::<EnumNode>() - || id == NodeId::of::<DescNode>() - { - return Some(Interruption::List); - } - } - - None - } -} - -impl Debug for Recipe { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { - write!( - f, - "Recipe matching {:?} from {:?}", - self.pattern, self.func.span - ) - } -} - -/// A show rule pattern that may match a target. -#[derive(Debug, Clone, PartialEq, Hash)] -pub enum Pattern { - /// Defines the appearence of some node. - Node(NodeId), - /// Defines text to be replaced. - Regex(Regex), -} - -impl Pattern { - /// Define a simple text replacement pattern. - pub fn text(text: &str) -> Self { - Self::Regex(Regex::new(®ex::escape(text)).unwrap()) - } -} - -/// A target for a show rule recipe. -#[derive(Debug, Copy, Clone, PartialEq)] -pub enum Target<'a> { - /// A showable node. - Node(&'a Content), - /// A slice of text. - Text(&'a str), -} - -/// Identifies a show rule recipe. -#[derive(Debug, Copy, Clone, PartialEq, Hash)] -pub enum Selector { - /// The nth recipe from the top of the chain. - Nth(usize), - /// The base recipe for a kind of node. - Base(NodeId), -} - -/// A node that can be realized given some styles. -pub trait Show: 'static + Sync + Send { - /// Unguard nested content against recursive show rules. - fn unguard_parts(&self, sel: Selector) -> Content; - - /// Access a field on this node. - fn field(&self, name: &str) -> Option<Value>; - - /// The base recipe for this node that is executed if there is no - /// user-defined show rule. - fn realize( - &self, - world: Tracked<dyn World>, - styles: StyleChain, - ) -> SourceResult<Content>; - - /// Finalize this node given the realization of a base or user recipe. Use - /// this for effects that should work even in the face of a user-defined - /// show rule, for example: - /// - Application of general settable properties - /// - /// Defaults to just the realized content. - #[allow(unused_variables)] - fn finalize( - &self, - world: Tracked<dyn World>, - styles: StyleChain, - realized: Content, - ) -> SourceResult<Content> { - Ok(realized) - } -} - -impl Capability for dyn Show {} |
