summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2020-01-05 11:18:13 +0100
committerLaurenz <laurmaedje@gmail.com>2020-01-05 11:18:13 +0100
commitbd384a2a633e21cd7deff7ed2a29a9c03a63a20e (patch)
tree12246c7c9142efe5fc2b2feb14fe4f286e3e177f /src
parent7b84f3b553de672e5374e142467f63b10009aeca (diff)
Re-enable *, _ and `.
Diffstat (limited to 'src')
-rw-r--r--src/func/mod.rs2
-rw-r--r--src/layout/tree.rs18
-rw-r--r--src/library/align.rs7
-rw-r--r--src/library/boxed.rs5
-rw-r--r--src/library/direction.rs5
-rw-r--r--src/library/mod.rs400
-rw-r--r--src/style.rs4
-rw-r--r--src/syntax/mod.rs8
-rw-r--r--src/syntax/parsing.rs2
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.