diff options
| author | Laurenz <laurmaedje@gmail.com> | 2021-06-09 00:37:13 +0200 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2021-06-09 00:37:13 +0200 |
| commit | 5afb42ad89abb518a01a09051f0f9b6f75bd383e (patch) | |
| tree | b12368a287f22de711df8d759c20ee742ed5b4c2 /src/exec | |
| parent | d69dfa84ec957ac4037f60a3335416a9f73b97c8 (diff) | |
Lists with indent-based parsing
- Unordered lists with indent-based parsing and basic layout using stacks
- Headings are now also indent based
- Removes syntax functions since they will be superseded by select & transform
Diffstat (limited to 'src/exec')
| -rw-r--r-- | src/exec/context.rs | 20 | ||||
| -rw-r--r-- | src/exec/mod.rs | 91 | ||||
| -rw-r--r-- | src/exec/state.rs | 2 |
3 files changed, 95 insertions, 18 deletions
diff --git a/src/exec/context.rs b/src/exec/context.rs index 016b092a..63008260 100644 --- a/src/exec/context.rs +++ b/src/exec/context.rs @@ -1,13 +1,13 @@ use std::mem; -use super::{Exec, FontFamily, State}; +use super::{Exec, ExecWithMap, FontFamily, State}; use crate::diag::{Diag, DiagSet, Pass}; -use crate::eval::TemplateValue; +use crate::eval::{ExprMap, TemplateValue}; use crate::geom::{Align, Dir, Gen, GenAxis, Length, Linear, Sides, Size}; use crate::layout::{ AnyNode, PadNode, PageRun, ParChild, ParNode, StackChild, StackNode, Tree, }; -use crate::syntax::Span; +use crate::syntax::{self, Span}; /// The context for execution. pub struct ExecContext { @@ -48,12 +48,22 @@ impl ExecContext { } /// Execute a template and return the result as a stack node. - pub fn exec_template(&mut self, template: &TemplateValue) -> StackNode { + pub fn exec_template_stack(&mut self, template: &TemplateValue) -> StackNode { + self.exec_stack(|ctx| template.exec(ctx)) + } + + /// Execute a tree with a map and return the result as a stack node. + pub fn exec_tree_stack(&mut self, tree: &syntax::Tree, map: &ExprMap) -> StackNode { + self.exec_stack(|ctx| tree.exec_with_map(ctx, map)) + } + + /// Execute something and return the result as a stack node. + pub fn exec_stack(&mut self, f: impl FnOnce(&mut Self)) -> StackNode { let snapshot = self.state.clone(); let page = self.page.take(); let stack = mem::replace(&mut self.stack, StackBuilder::new(&self.state)); - template.exec(self); + f(self); self.state = snapshot; self.page = page; diff --git a/src/exec/mod.rs b/src/exec/mod.rs index 35e6b55c..a13d8c5e 100644 --- a/src/exec/mod.rs +++ b/src/exec/mod.rs @@ -9,10 +9,11 @@ pub use state::*; use std::rc::Rc; use crate::diag::Pass; -use crate::eval::{NodeMap, TemplateFunc, TemplateNode, TemplateValue, Value}; -use crate::layout; +use crate::eval::{ExprMap, TemplateFunc, TemplateNode, TemplateValue, Value}; +use crate::geom::{Dir, Gen}; +use crate::layout::{self, FixedNode, StackChild, StackNode}; use crate::pretty::pretty; -use crate::syntax::*; +use crate::syntax; /// Execute a template to produce a layout tree. pub fn exec(template: &TemplateValue, state: State) -> Pass<layout::Tree> { @@ -33,30 +34,96 @@ pub trait Exec { fn exec(&self, ctx: &mut ExecContext); } -/// Execute a node with a node map that applies to it. +/// Execute a node with an expression map that applies to it. pub trait ExecWithMap { /// Execute the node. - fn exec_with_map(&self, ctx: &mut ExecContext, map: &NodeMap); + fn exec_with_map(&self, ctx: &mut ExecContext, map: &ExprMap); } -impl ExecWithMap for Tree { - fn exec_with_map(&self, ctx: &mut ExecContext, map: &NodeMap) { +impl ExecWithMap for syntax::Tree { + fn exec_with_map(&self, ctx: &mut ExecContext, map: &ExprMap) { for node in self { node.exec_with_map(ctx, map); } } } -impl ExecWithMap for Node { - fn exec_with_map(&self, ctx: &mut ExecContext, map: &NodeMap) { +impl ExecWithMap for syntax::Node { + fn exec_with_map(&self, ctx: &mut ExecContext, map: &ExprMap) { match self { - Node::Text(text) => ctx.push_text(text), - Node::Space => ctx.push_word_space(), - _ => map[&(self as *const _)].exec(ctx), + Self::Text(text) => ctx.push_text(text), + Self::Space => ctx.push_word_space(), + Self::Linebreak(_) => ctx.linebreak(), + Self::Parbreak(_) => ctx.parbreak(), + Self::Strong(_) => ctx.state.font.strong ^= true, + Self::Emph(_) => ctx.state.font.emph ^= true, + Self::Raw(raw) => raw.exec(ctx), + Self::Heading(heading) => heading.exec_with_map(ctx, map), + Self::List(list) => list.exec_with_map(ctx, map), + Self::Expr(expr) => map[&(expr as *const _)].exec(ctx), } } } +impl Exec for syntax::RawNode { + fn exec(&self, ctx: &mut ExecContext) { + if self.block { + ctx.parbreak(); + } + + let snapshot = ctx.state.clone(); + ctx.set_monospace(); + ctx.push_text(&self.text); + ctx.state = snapshot; + + if self.block { + ctx.parbreak(); + } + } +} + +impl ExecWithMap for syntax::HeadingNode { + fn exec_with_map(&self, ctx: &mut ExecContext, map: &ExprMap) { + let snapshot = ctx.state.clone(); + + let upscale = 1.6 - 0.1 * self.level as f64; + ctx.state.font.scale *= upscale; + ctx.state.font.strong = true; + + self.body.exec_with_map(ctx, map); + + ctx.state = snapshot; + ctx.parbreak(); + } +} + +impl ExecWithMap for syntax::ListNode { + fn exec_with_map(&self, ctx: &mut ExecContext, map: &ExprMap) { + ctx.parbreak(); + + let bullet = ctx.exec_stack(|ctx| ctx.push_text("•")); + let body = ctx.exec_tree_stack(&self.body, map); + + let stack = StackNode { + dirs: Gen::new(Dir::TTB, ctx.state.lang.dir), + aspect: None, + children: vec![ + StackChild::Any(bullet.into(), Gen::default()), + StackChild::Spacing(ctx.state.font.resolve_size() / 2.0), + StackChild::Any(body.into(), Gen::default()), + ], + }; + + ctx.push(FixedNode { + width: None, + height: None, + child: stack.into(), + }); + + ctx.parbreak(); + } +} + impl Exec for Value { fn exec(&self, ctx: &mut ExecContext) { match self { diff --git a/src/exec/state.rs b/src/exec/state.rs index 9a8971cc..aeeeaed5 100644 --- a/src/exec/state.rs +++ b/src/exec/state.rs @@ -7,7 +7,7 @@ use crate::geom::*; use crate::layout::Fill; use crate::paper::{Paper, PaperClass, PAPER_A4}; -/// The evaluation state. +/// The execution state. #[derive(Debug, Clone, PartialEq)] pub struct State { /// The current language-related settings. |
