diff options
| author | Laurenz <laurmaedje@gmail.com> | 2020-01-05 11:18:13 +0100 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2020-01-05 11:18:13 +0100 |
| commit | bd384a2a633e21cd7deff7ed2a29a9c03a63a20e (patch) | |
| tree | 12246c7c9142efe5fc2b2feb14fe4f286e3e177f /src | |
| parent | 7b84f3b553de672e5374e142467f63b10009aeca (diff) | |
Re-enable *, _ and `.
Diffstat (limited to 'src')
| -rw-r--r-- | src/func/mod.rs | 2 | ||||
| -rw-r--r-- | src/layout/tree.rs | 18 | ||||
| -rw-r--r-- | src/library/align.rs | 7 | ||||
| -rw-r--r-- | src/library/boxed.rs | 5 | ||||
| -rw-r--r-- | src/library/direction.rs | 5 | ||||
| -rw-r--r-- | src/library/mod.rs | 400 | ||||
| -rw-r--r-- | src/style.rs | 4 | ||||
| -rw-r--r-- | src/syntax/mod.rs | 8 | ||||
| -rw-r--r-- | src/syntax/parsing.rs | 2 |
9 files changed, 240 insertions, 211 deletions
diff --git a/src/func/mod.rs b/src/func/mod.rs index 208e1977..427e5b6f 100644 --- a/src/func/mod.rs +++ b/src/func/mod.rs @@ -101,7 +101,7 @@ pub enum Command<'a> { Add(Layout), AddMultiple(MultiLayout), - AddSpacing(Size, SpacingKind, GenericAxis), + SpacingFunc(Size, SpacingKind, GenericAxis), FinishLine, FinishSpace, diff --git a/src/layout/tree.rs b/src/layout/tree.rs index e77fd528..4ed3d82a 100644 --- a/src/layout/tree.rs +++ b/src/layout/tree.rs @@ -44,9 +44,19 @@ impl<'a, 'p> TreeLayouter<'a, 'p> { Node::Space => self.layout_space(), Node::Newline => self.layout_paragraph()?, - Node::ToggleItalics => {}, - Node::ToggleBold => {}, - Node::ToggleMonospace => {}, + Node::ToggleItalics => self.style.text.variant.style.toggle(), + Node::ToggleBolder => { + self.style.text.variant.weight.0 += 300 * + if self.style.text.bolder { -1 } else { 1 }; + self.style.text.bolder = !self.style.text.bolder; + } + Node::ToggleMonospace => { + let list = &mut self.style.text.fallback.list; + match list.get(0).map(|s| s.as_str()) { + Some("monospace") => { list.remove(0); }, + _ => list.insert(0, "monospace".to_string()), + } + } Node::Func(func) => self.layout_func(func)?, } @@ -98,7 +108,7 @@ impl<'a, 'p> TreeLayouter<'a, 'p> { Add(layout) => self.layouter.add(layout)?, AddMultiple(layouts) => self.layouter.add_multiple(layouts)?, - AddSpacing(space, kind, axis) => match axis { + SpacingFunc(space, kind, axis) => match axis { Primary => self.layouter.add_primary_spacing(space, kind), Secondary => self.layouter.add_secondary_spacing(space, kind)?, } diff --git a/src/library/align.rs b/src/library/align.rs index 524ada61..03d905cd 100644 --- a/src/library/align.rs +++ b/src/library/align.rs @@ -1,16 +1,17 @@ use crate::func::prelude::*; use super::maps::{PosAxisMap, AlignmentKey}; + function! { /// `align`: Aligns content along the layouting axes. #[derive(Debug, PartialEq)] - pub struct Align { + pub struct AlignFunc { body: Option<SyntaxTree>, map: PosAxisMap<AlignmentKey>, } parse(args, body, ctx) { - Align { + AlignFunc { body: parse!(optional: body, ctx), map: PosAxisMap::new(&mut args)?, } @@ -28,7 +29,7 @@ function! { match &self.body { Some(body) => vec![AddMultiple(layout(&body, ctx)?)], - None => vec![Command::SetAlignment(ctx.alignment)], + None => vec![SetAlignment(ctx.alignment)], } } } diff --git a/src/library/boxed.rs b/src/library/boxed.rs index 7333c50f..a4d059cb 100644 --- a/src/library/boxed.rs +++ b/src/library/boxed.rs @@ -3,17 +3,18 @@ use smallvec::smallvec; use crate::func::prelude::*; use super::maps::ExtentMap; + function! { /// `box`: Layouts content into a box. #[derive(Debug, PartialEq)] - pub struct Boxed { + pub struct BoxFunc { body: SyntaxTree, map: ExtentMap<PSize>, debug: Option<bool>, } parse(args, body, ctx) { - Boxed { + BoxFunc { body: parse!(optional: body, ctx).unwrap_or(SyntaxTree::new()), map: ExtentMap::new(&mut args, false)?, debug: args.get_key_opt::<bool>("debug")?, diff --git a/src/library/direction.rs b/src/library/direction.rs index 7bb11c99..a0992075 100644 --- a/src/library/direction.rs +++ b/src/library/direction.rs @@ -1,16 +1,17 @@ use crate::func::prelude::*; use super::maps::PosAxisMap; + function! { /// `direction`: Sets the directions of the layouting axes. #[derive(Debug, PartialEq)] - pub struct DirectionChange { + pub struct DirectionFunc { body: Option<SyntaxTree>, map: PosAxisMap<Direction>, } parse(args, body, ctx) { - DirectionChange { + DirectionFunc { body: parse!(optional: body, ctx), map: PosAxisMap::new(&mut args)?, } diff --git a/src/library/mod.rs b/src/library/mod.rs index d4519867..ac1ac338 100644 --- a/src/library/mod.rs +++ b/src/library/mod.rs @@ -12,73 +12,168 @@ pub_use_mod!(align); pub_use_mod!(boxed); pub_use_mod!(direction); + /// Create a scope with all standard functions. pub fn std() -> Scope { let mut std = Scope::new(); - std.add::<Align>("align"); - std.add::<Boxed>("box"); - std.add::<DirectionChange>("direction"); - - std.add::<LineBreak>("n"); - std.add::<LineBreak>("line.break"); - std.add::<ParBreak>("par.break"); - std.add::<PageBreak>("page.break"); + // Font setup + std.add::<FontFamilyFunc>("font.family"); + std.add::<FontStyleFunc>("font.style"); + std.add::<FontWeightFunc>("font.weight"); + std.add::<FontSizeFunc>("font.size"); + + // Layout + std.add::<AlignFunc>("align"); + std.add::<DirectionFunc>("direction"); + std.add_with_metadata::<ContentSpacingFunc>("par.spacing", ContentKind::Paragraph); + std.add_with_metadata::<ContentSpacingFunc>("word.spacing", ContentKind::Word); + std.add_with_metadata::<ContentSpacingFunc>("line.spacing", ContentKind::Line); + std.add::<BoxFunc>("box"); + + // Spacing + std.add::<LineBreakFunc>("n"); + std.add::<LineBreakFunc>("line.break"); + std.add::<ParBreakFunc>("par.break"); + std.add::<PageBreakFunc>("page.break"); + std.add_with_metadata::<SpacingFunc>("spacing", None); + std.add_with_metadata::<SpacingFunc>("h", Some(Horizontal)); + std.add_with_metadata::<SpacingFunc>("v", Some(Vertical)); + + // Page setup + std.add::<PageSizeFunc>("page.size"); + std.add::<PageMarginsFunc>("page.margins"); - std.add_with_metadata::<ContentSpacing>("word.spacing", ContentKind::Word); - std.add_with_metadata::<ContentSpacing>("line.spacing", ContentKind::Line); - std.add_with_metadata::<ContentSpacing>("par.spacing", ContentKind::Paragraph); + std +} - std.add::<PageSize>("page.size"); - std.add::<PageMargins>("page.margins"); +// -------------------------------------------------------------------------- // +// Font setup - std.add_with_metadata::<Spacing>("spacing", None); - std.add_with_metadata::<Spacing>("h", Some(Horizontal)); - std.add_with_metadata::<Spacing>("v", Some(Vertical)); +function! { + /// `font.family`: Set the font family. + #[derive(Debug, PartialEq)] + pub struct FontFamilyFunc { + body: Option<SyntaxTree>, + family: String, + } - std.add_with_metadata::<FontFamily>("font.family", None); - std.add_with_metadata::<FontFamily>("mono", Some("monospace".to_string())); - std.add::<SetFontStyle>("font.style"); - std.add::<SetFontWeight>("font.weight"); - std.add::<FontSize>("font.size"); + parse(args, body, ctx, meta) { + FontFamilyFunc { + body: parse!(optional: body, ctx), + family: args.get_pos::<String>()?, + } + } - std + layout(self, ctx) { + let mut style = ctx.style.text.clone(); + style.fallback.list = vec![self.family.clone()]; + styled(&self.body, &ctx, style) + } } function! { - /// `line.break`, `n`: Ends the current line. - #[derive(Debug, Default, PartialEq)] - pub struct LineBreak; + /// `font.style`: Set the font style (normal / italic). + #[derive(Debug, PartialEq)] + pub struct FontStyleFunc { + body: Option<SyntaxTree>, + style: FontStyle, + } - parse(default) - layout() { vec![FinishLine] } + parse(args, body, ctx) { + FontStyleFunc { + body: parse!(optional: body, ctx), + style: { + let s = args.get_pos::<String>()?; + match FontStyle::from_str(&s) { + Some(style) => style, + None => error!("invalid font style: `{}`", s), + } + } + } + } + + layout(self, ctx) { + let mut style = ctx.style.text.clone(); + style.variant.style = self.style; + styled(&self.body, &ctx, style) + } } function! { - /// `par.break`: Ends the current paragraph. - /// - /// self has the same effect as two subsequent newlines. - #[derive(Debug, Default, PartialEq)] - pub struct ParBreak; + /// `font.weight`: Set text with a given weight. + #[derive(Debug, PartialEq)] + pub struct FontWeightFunc { + body: Option<SyntaxTree>, + weight: FontWeight, + } - parse(default) - layout() { vec![BreakParagraph] } + parse(args, body, ctx, meta) { + FontWeightFunc { + body: parse!(optional: body, ctx), + weight: match args.get_pos::<Expression>()? { + Expression::Num(weight) => { + let weight = weight.round() as i16; + FontWeight( + if weight < 100 { 100 } + else if weight <= 900 { weight } + else { 900 } + ) + } + Expression::Ident(Ident(s)) => { + match FontWeight::from_str(&s) { + Some(weight) => weight, + None => error!("invalid font weight: `{}`", s), + } + } + _ => error!("expected identifier or number"), + }, + } + } + + layout(self, ctx) { + let mut style = ctx.style.text.clone(); + style.variant.style.toggle(); + styled(&self.body, &ctx, style) + } } function! { - /// `page.break`: Ends the current page. - #[derive(Debug, Default, PartialEq)] - pub struct PageBreak; + /// `font.size`: Sets the font size. + #[derive(Debug, PartialEq)] + pub struct FontSizeFunc { + body: Option<SyntaxTree>, + size: ScaleSize, + } - parse(default) - layout() { vec![BreakPage] } + parse(args, body, ctx) { + FontSizeFunc { + body: parse!(optional: body, ctx), + size: args.get_pos::<ScaleSize>()?, + } + } + + layout(self, ctx) { + let mut style = ctx.style.text.clone(); + match self.size { + ScaleSize::Absolute(size) => { + style.base_font_size = size; + style.font_scale = 1.0; + } + ScaleSize::Scaled(scale) => style.font_scale = scale, + } + styled(&self.body, &ctx, style) + } } +// -------------------------------------------------------------------------- // +// Layout + function! { /// `word.spacing`, `line.spacing`, `par.spacing`: The spacing between /// words, lines or paragraphs as a multiple of the font size. #[derive(Debug, PartialEq)] - pub struct ContentSpacing { + pub struct ContentSpacingFunc { body: Option<SyntaxTree>, content: ContentKind, spacing: f32, @@ -87,7 +182,7 @@ function! { type Meta = ContentKind; parse(args, body, ctx, meta) { - ContentSpacing { + ContentSpacingFunc { body: parse!(optional: body, ctx), content: meta, spacing: args.get_pos::<f64>()? as f32, @@ -113,77 +208,42 @@ pub enum ContentKind { Paragraph, } -function! { - /// `page.size`: Set the size of pages. - #[derive(Debug, PartialEq)] - pub enum PageSize { - Paper(Paper, bool), - Custom(ExtentMap<PSize>), - } +// -------------------------------------------------------------------------- // +// Spacing - parse(args, body) { - parse!(forbidden: body); - - if let Some(name) = args.get_pos_opt::<Ident>()? { - let landscape = args.get_key_opt::<bool>("landscape")? - .unwrap_or(false); - PageSize::Paper(Paper::from_name(name.as_str())?, landscape) - } else { - PageSize::Custom(ExtentMap::new(&mut args, true)?) - } - } - - layout(self, ctx) { - let mut style = ctx.style.page; - - match self { - PageSize::Paper(paper, landscape) => { - style.class = paper.class; - style.dimensions = paper.dimensions; - if *landscape { - style.dimensions.swap(); - } - } +function! { + /// `line.break`, `n`: Ends the current line. + #[derive(Debug, Default, PartialEq)] + pub struct LineBreakFunc; - PageSize::Custom(map) => { - style.class = PaperClass::Custom; + parse(default) + layout() { vec![FinishLine] } +} - let map = map.dedup(ctx.axes)?; - let dims = &mut style.dimensions; - map.with(Horizontal, |&psize| dims.x = psize.scaled(dims.x)); - map.with(Vertical, |&psize| dims.y = psize.scaled(dims.y)); - } - } +function! { + /// `par.break`: Ends the current paragraph. + /// + /// self has the same effect as two subsequent newlines. + #[derive(Debug, Default, PartialEq)] + pub struct ParBreakFunc; - vec![SetPageStyle(style)] - } + parse(default) + layout() { vec![BreakParagraph] } } function! { - /// `page.margins`: Sets the page margins. - #[derive(Debug, PartialEq)] - pub struct PageMargins { - map: PaddingMap, - } - - parse(args, body) { - parse!(forbidden: body); - PageMargins { - map: PaddingMap::new(&mut args)?, - } - } + /// `page.break`: Ends the current page. + #[derive(Debug, Default, PartialEq)] + pub struct PageBreakFunc; - layout(self, ctx) { - let mut style = ctx.style.page; - self.map.apply(ctx.axes, &mut style.margins)?; - vec![SetPageStyle(style)] - } + parse(default) + layout() { vec![BreakPage] } } function! { /// `spacing`, `h`, `v`: Adds spacing along an axis. #[derive(Debug, PartialEq)] - pub struct Spacing { + pub struct SpacingFunc { axis: AxisKey, spacing: FSize, } @@ -194,7 +254,7 @@ function! { parse!(forbidden: body); if let Some(axis) = meta { - Spacing { + SpacingFunc { axis: AxisKey::Specific(axis), spacing: FSize::from_expr(args.get_pos::<Spanned<Expression>>()?)?, } @@ -203,7 +263,7 @@ function! { .map_err(|_| error!(@unexpected_argument))?; let spacing = FSize::from_expr(arg.v.value)?; - Spacing { axis, spacing } + SpacingFunc { axis, spacing } } else { error!("expected axis and spacing") } @@ -212,131 +272,83 @@ function! { layout(self, ctx) { let axis = self.axis.to_generic(ctx.axes); let spacing = self.spacing.scaled(ctx.style.text.font_size()); - vec![AddSpacing(spacing, SpacingKind::Hard, axis)] + vec![SpacingFunc(spacing, SpacingKind::Hard, axis)] } } +// -------------------------------------------------------------------------- // +// Page setup + function! { - /// `font.weight`, `bold`: Set text with a given weight. + /// `page.size`: Set the size of pages. #[derive(Debug, PartialEq)] - pub struct SetFontWeight { - body: Option<SyntaxTree>, - weight: FontWeight, + pub enum PageSizeFunc { + Paper(Paper, bool), + Custom(ExtentMap<PSize>), } - parse(args, body, ctx, meta) { - SetFontWeight { - body: parse!(optional: body, ctx), - weight: match args.get_pos::<Expression>()? { - Expression::Num(weight) => FontWeight(if weight < 0.0 { - 0 - } else if weight < 1000.0 { - weight.round() as u16 - } else { - 1000 - }), - Expression::Ident(Ident(s)) => { - match FontWeight::from_str(&s) { - Some(weight) => weight, - None => error!("invalid font weight: `{}`", s), - } - } - _ => error!("expected identifier or number"), - }, + parse(args, body) { + parse!(forbidden: body); + + if let Some(name) = args.get_pos_opt::<Ident>()? { + let flip = args.get_key_opt::<bool>("flip")? + .unwrap_or(false); + PageSizeFunc::Paper(Paper::from_name(name.as_str())?, flip) + } else { + PageSizeFunc::Custom(ExtentMap::new(&mut args, true)?) } } layout(self, ctx) { - let mut style = ctx.style.text.clone(); - style.variant.style.toggle(); - styled(&self.body, &ctx, style) - } -} - -function! { - /// `font.style`: Set the font style (normal / italic). - #[derive(Debug, PartialEq)] - pub struct SetFontStyle { - body: Option<SyntaxTree>, - style: FontStyle, - } + let mut style = ctx.style.page; - parse(args, body, ctx) { - SetFontStyle { - body: parse!(optional: body, ctx), - style: { - let s = args.get_pos::<String>()?; - match FontStyle::from_str(&s) { - Some(style) => style, - None => error!("invalid font style: `{}`", s), + match self { + PageSizeFunc::Paper(paper, flip) => { + style.class = paper.class; + style.dimensions = paper.dimensions; + if *flip { + style.dimensions.swap(); } } - } - } - - layout(self, ctx) { - let mut style = ctx.style.text.clone(); - style.variant.style = self.style; - styled(&self.body, &ctx, style) - } -} -function! { - /// `font.family`: Set the font family. - #[derive(Debug, PartialEq)] - pub struct FontFamily { - body: Option<SyntaxTree>, - family: String, - } - - type Meta = Option<String>; + PageSizeFunc::Custom(map) => { + style.class = PaperClass::Custom; - parse(args, body, ctx, meta) { - FontFamily { - body: parse!(optional: body, ctx), - family: if let Some(family) = meta { - family - } else { - args.get_pos::<String>()? - }, + let map = map.dedup(ctx.axes)?; + let dims = &mut style.dimensions; + map.with(Horizontal, |&psize| dims.x = psize.scaled(dims.x)); + map.with(Vertical, |&psize| dims.y = psize.scaled(dims.y)); + } } - } - layout(self, ctx) { - let mut style = ctx.style.text.clone(); - style.fallback.list = vec![self.family.clone()]; - styled(&self.body, &ctx, style) + vec![SetPageStyle(style)] } } function! { - /// `font.size`: Sets the font size. + /// `page.margins`: Sets the page margins. #[derive(Debug, PartialEq)] - pub struct FontSize { - body: Option<SyntaxTree>, - size: ScaleSize, + pub struct PageMarginsFunc { + map: PaddingMap, } - parse(args, body, ctx) { - FontSize { - body: parse!(optional: body, ctx), - size: args.get_pos::<ScaleSize>()?, + parse(args, body) { + parse!(forbidden: body); + PageMarginsFunc { + map: PaddingMap::new(&mut args)?, } } layout(self, ctx) { - let mut style = ctx.style.text.clone(); - match self.size { - ScaleSize::Absolute(size) => { - style.base_font_size = size; - style.font_scale = 1.0; - } - ScaleSize::Scaled(scale) => style.font_scale = scale, - } - styled(&self.body, &ctx, style) + let mut style = ctx.style.page; + self.map.apply(ctx.axes, &mut style.margins)?; + vec![SetPageStyle(style)] } } +// -------------------------------------------------------------------------- // +// Helpers + /// Layout the body with the style or update the style if there is no body. fn styled<'a>( body: &'a Option<SyntaxTree>, diff --git a/src/style.rs b/src/style.rs index ffa10d51..cbe4bf01 100644 --- a/src/style.rs +++ b/src/style.rs @@ -20,6 +20,9 @@ pub struct TextStyle { pub fallback: FontFallbackTree, /// The selected font variant. pub variant: FontVariant, + /// Whether the bolder toggle is active or inactive. This determines + /// whether the next `*` adds or removes font weight. + pub bolder: bool, /// The base font size. pub base_font_size: Size, /// The font scale to apply on the base font size. @@ -80,6 +83,7 @@ impl Default for TextStyle { style: FontStyle::Normal, weight: FontWeight(400), }, + bolder: false, base_font_size: Size::pt(11.0), font_scale: 1.0, word_spacing_scale: 0.25, diff --git a/src/syntax/mod.rs b/src/syntax/mod.rs index bf395c2b..193810c0 100644 --- a/src/syntax/mod.rs +++ b/src/syntax/mod.rs @@ -72,11 +72,11 @@ pub enum Node { Space, /// A line feed. Newline, - /// Indicates that italics were enabled / disabled. + /// Indicates that italics were toggled. ToggleItalics, - /// Indicates that boldface was enabled / disabled. - ToggleBold, - /// Indicates that monospace was enabled / disabled. + /// Indicates that bolder text was toggled. + ToggleBolder, + /// Indicates that monospace was toggled. ToggleMonospace, /// Literal text. Text(String), diff --git a/src/syntax/parsing.rs b/src/syntax/parsing.rs index dcba1d0f..6eed2235 100644 --- a/src/syntax/parsing.rs +++ b/src/syntax/parsing.rs @@ -73,7 +73,7 @@ impl<'s> Parser<'s> { // Modifiers. Underscore => self.append_consumed(Node::ToggleItalics, token.span), - Star => self.append_consumed(Node::ToggleBold, token.span), + Star => self.append_consumed(Node::ToggleBolder, token.span), Backtick => self.append_consumed(Node::ToggleMonospace, token.span), // Normal text. |
