diff options
| author | Laurenz <laurmaedje@gmail.com> | 2022-04-24 14:39:53 +0200 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2022-04-24 14:53:43 +0200 |
| commit | 50e4002a2a65c27f46895103c59cb775ca60d16d (patch) | |
| tree | dbd43c16ae8456536c89d64d2cfff293bb6b1148 /src/eval | |
| parent | 04fb8b288aa7c80607da79db7d085a4820b95a9d (diff) | |
Split `show` into `realize` and `finalize`
Diffstat (limited to 'src/eval')
| -rw-r--r-- | src/eval/content.rs | 51 | ||||
| -rw-r--r-- | src/eval/show.rs | 32 |
2 files changed, 61 insertions, 22 deletions
diff --git a/src/eval/content.rs b/src/eval/content.rs index 098bfbfc..2465f0e3 100644 --- a/src/eval/content.rs +++ b/src/eval/content.rs @@ -104,6 +104,23 @@ impl Content { Self::Show(node.pack()) } + /// Create a new sequence nodes from multiples nodes. + pub fn sequence(seq: Vec<Self>) -> Self { + if seq.len() == 1 { + seq.into_iter().next().unwrap() + } else { + Self::Sequence(Arc::new(seq)) + } + } + + /// Repeat this content `n` times. + pub fn repeat(&self, n: i64) -> StrResult<Self> { + let count = usize::try_from(n) + .map_err(|_| format!("cannot repeat this content {} times", n))?; + + Ok(Self::sequence(vec![self.clone(); count])) + } + /// Style this content with a single style property. pub fn styled<'k, K: Key<'k>>(mut self, key: K, value: K::Value) -> Self { if let Self::Styled(styled) = &mut self { @@ -137,21 +154,24 @@ impl Content { Self::show(DecoNode::<UNDERLINE>(self)) } - /// Create a new sequence nodes from multiples nodes. - pub fn sequence(seq: Vec<Self>) -> Self { - if seq.len() == 1 { - seq.into_iter().next().unwrap() - } else { - Self::Sequence(Arc::new(seq)) + /// Return a node that is spaced apart at top and bottom. + pub fn spaced(self, above: Length, below: Length) -> Self { + if above.is_zero() && below.is_zero() { + return self; } - } - /// Repeat this content `n` times. - pub fn repeat(&self, n: i64) -> StrResult<Self> { - let count = usize::try_from(n) - .map_err(|_| format!("cannot repeat this content {} times", n))?; + let mut seq = vec![]; + if !above.is_zero() { + seq.push(Content::Vertical(above.into())); + } - Ok(Self::sequence(vec![self.clone(); count])) + seq.push(self); + + if !below.is_zero() { + seq.push(Content::Vertical(below.into())); + } + + Self::sequence(seq) } /// Layout this content into a collection of pages. @@ -454,8 +474,11 @@ impl<'a> Builder<'a> { } Content::Show(node) => { let id = node.id(); - let realized = styles.realize(ctx, node)?; - let content = node.show(ctx, styles, realized)?; + let realized = match styles.realize(ctx, node)? { + Some(content) => content, + None => node.realize(ctx, styles)?, + }; + let content = node.finalize(ctx, styles, realized)?; let stored = self.tpa.alloc(content); self.process(ctx, stored, styles.unscoped(id))?; } diff --git a/src/eval/show.rs b/src/eval/show.rs index f8d98d52..c374c2df 100644 --- a/src/eval/show.rs +++ b/src/eval/show.rs @@ -13,14 +13,26 @@ pub trait Show: 'static { /// Encode this node into a dictionary. fn encode(&self) -> Dict; - /// Show this node in the given styles and optionally given the realization - /// of a show rule. - fn show( + /// The base recipe for this node that is executed if there is no + /// user-defined show rule. + fn realize(&self, ctx: &mut Context, styles: StyleChain) -> TypResult<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 + /// - Attaching things like semantics to a heading + /// + /// Defaults to just the realized content. + #[allow(unused_variables)] + fn finalize( &self, ctx: &mut Context, styles: StyleChain, - realized: Option<Content>, - ) -> TypResult<Content>; + realized: Content, + ) -> TypResult<Content> { + Ok(realized) + } /// Convert to a packed show node. fn pack(self) -> ShowNode @@ -55,13 +67,17 @@ impl Show for ShowNode { self.0.encode() } - fn show( + fn realize(&self, ctx: &mut Context, styles: StyleChain) -> TypResult<Content> { + self.0.realize(ctx, styles) + } + + fn finalize( &self, ctx: &mut Context, styles: StyleChain, - realized: Option<Content>, + realized: Content, ) -> TypResult<Content> { - self.0.show(ctx, styles, realized) + self.0.finalize(ctx, styles, realized) } fn pack(self) -> ShowNode { |
