summaryrefslogtreecommitdiff
path: root/src/eval
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2022-04-24 14:39:53 +0200
committerLaurenz <laurmaedje@gmail.com>2022-04-24 14:53:43 +0200
commit50e4002a2a65c27f46895103c59cb775ca60d16d (patch)
treedbd43c16ae8456536c89d64d2cfff293bb6b1148 /src/eval
parent04fb8b288aa7c80607da79db7d085a4820b95a9d (diff)
Split `show` into `realize` and `finalize`
Diffstat (limited to 'src/eval')
-rw-r--r--src/eval/content.rs51
-rw-r--r--src/eval/show.rs32
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 {