diff options
| author | Laurenz <laurmaedje@gmail.com> | 2019-11-17 15:16:37 +0100 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2019-11-17 15:16:37 +0100 |
| commit | f6cb4d725ee6e4fd09b92b5af7348d11ac951b10 (patch) | |
| tree | 7cf8bc7b0158a8a453fd9e2a2fe5a857ef036d5e /src/library | |
| parent | 4d0bdc4ca4cb5e8ca1a70b38a0fc0ec37d9e4857 (diff) | |
Update standard library functions 🎁
Diffstat (limited to 'src/library')
| -rw-r--r-- | src/library/axes.rs | 43 | ||||
| -rw-r--r-- | src/library/boxed.rs | 21 | ||||
| -rw-r--r-- | src/library/mod.rs | 19 | ||||
| -rw-r--r-- | src/library/spacing.rs | 81 | ||||
| -rw-r--r-- | src/library/structure.rs | 172 | ||||
| -rw-r--r-- | src/library/style.rs | 14 |
6 files changed, 162 insertions, 188 deletions
diff --git a/src/library/axes.rs b/src/library/axes.rs new file mode 100644 index 00000000..62e0078f --- /dev/null +++ b/src/library/axes.rs @@ -0,0 +1,43 @@ +use crate::func::prelude::*; + +/// 📐 `align`: Aligns content in different ways. +#[derive(Debug, PartialEq)] +pub struct Align { + body: Option<SyntaxTree>, + alignment: Alignment, +} + +function! { + data: Align, + + parse(args, body, ctx) { + let body = parse!(optional: body, ctx); + let arg = args.get_pos::<ArgIdent>()?; + let alignment = match arg.val { + "left" | "origin" => Alignment::Origin, + "center" => Alignment::Center, + "right" | "end" => Alignment::End, + s => err!("invalid alignment specifier: {}", s), + }; + args.done()?; + + Ok(Align { + body, + alignment, + }) + } + + layout(this, ctx) { + let mut new_axes = ctx.axes; + new_axes.primary.alignment = this.alignment; + + Ok(match &this.body { + Some(body) => commands![ + SetAxes(new_axes), + LayoutTree(body), + SetAxes(ctx.axes), + ], + None => commands![Command::SetAxes(new_axes)] + }) + } +} diff --git a/src/library/boxed.rs b/src/library/boxed.rs new file mode 100644 index 00000000..e8debca4 --- /dev/null +++ b/src/library/boxed.rs @@ -0,0 +1,21 @@ +use crate::func::prelude::*; + +/// `box`: Layouts content into a box. +#[derive(Debug, PartialEq)] +pub struct Boxed { + body: SyntaxTree, +} + +function! { + data: Boxed, + + parse(args, body, ctx) { + args.done()?; + let body = parse!(required: body, ctx); + Ok(Boxed { body }) + } + + layout(this, ctx) { + Ok(commands![AddMultiple(layout_tree(&this.body, ctx)?)]) + } +} diff --git a/src/library/mod.rs b/src/library/mod.rs index 74f77204..d795d488 100644 --- a/src/library/mod.rs +++ b/src/library/mod.rs @@ -2,22 +2,23 @@ use crate::func::Scope; -mod structure; -mod style; - -pub use structure::*; -pub use style::*; +pub_use_mod!(boxed); +pub_use_mod!(axes); +pub_use_mod!(spacing); +pub_use_mod!(style); /// 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::<Linebreak>("line.break"); - std.add::<Linebreak>("n"); - std.add::<Pagebreak>("page.break"); + std.add::<Align>("align"); + + std.add::<LineBreak>("n"); + std.add::<LineBreak>("line.break"); + std.add::<ParagraphBreak>("paragraph.break"); + std.add::<PageBreak>("page.break"); std.add::<HorizontalSpace>("h"); std.add::<VerticalSpace>("v"); diff --git a/src/library/spacing.rs b/src/library/spacing.rs new file mode 100644 index 00000000..afd26d80 --- /dev/null +++ b/src/library/spacing.rs @@ -0,0 +1,81 @@ +use crate::func::prelude::*; + +/// `line.break`, `n`: Ends the current line. +#[derive(Debug, PartialEq)] +pub struct LineBreak; + +function! { + data: LineBreak, + parse: plain, + layout(_, _) { Ok(commands![FinishRun]) } +} + +/// `paragraph.break`: Ends the current paragraph. +/// +/// This has the same effect as two subsequent newlines. +#[derive(Debug, PartialEq)] +pub struct ParagraphBreak; + +function! { + data: ParagraphBreak, + parse: plain, + layout(_, _) { Ok(commands![FinishBox]) } +} + +/// `page.break`: Ends the current page. +#[derive(Debug, PartialEq)] +pub struct PageBreak; + +function! { + data: PageBreak, + parse: plain, + layout(_, _) { Ok(commands![FinishLayout]) } +} + +macro_rules! space_func { + ($ident:ident, $doc:expr, $var:ident => $command:expr) => ( + #[doc = $doc] + #[derive(Debug, PartialEq)] + pub struct $ident(Spacing); + + function! { + data: $ident, + + parse(args, body, _ctx) { + parse!(forbidden: body); + + let arg = args.get_pos::<ArgExpr>()?; + let spacing = match arg.val { + Expression::Size(s) => Spacing::Absolute(*s), + Expression::Num(f) => Spacing::Relative(*f as f32), + _ => err!("invalid spacing, expected size or number"), + }; + + Ok($ident(spacing)) + } + + layout(this, ctx) { + let $var = match this.0 { + Spacing::Absolute(s) => s, + Spacing::Relative(f) => f * ctx.style.font_size, + }; + + Ok(commands![$command]) + } + } + ); +} + +/// Absolute or font-relative spacing. +#[derive(Debug, PartialEq)] +enum Spacing { + Absolute(Size), + Relative(f32), +} + +// FIXME: h != primary and v != secondary. +space_func!(HorizontalSpace, "📖 `h`: Adds horizontal whitespace.", + space => AddPrimarySpace(space)); + +space_func!(VerticalSpace, "📑 `v`: Adds vertical whitespace.", + space => AddSecondarySpace(space)); diff --git a/src/library/structure.rs b/src/library/structure.rs deleted file mode 100644 index 2dbf33ff..00000000 --- a/src/library/structure.rs +++ /dev/null @@ -1,172 +0,0 @@ -use crate::func::prelude::*; -use Command::*; - -/// ↩ `line.break`, `n`: Ends the current line. -#[derive(Debug, PartialEq)] -pub struct Linebreak; - -function! { - data: Linebreak, - parse: plain, - layout(_, _) { Ok(commands![BreakFlex]) } -} - -/// ↕ `paragraph.break`: Ends the current paragraph. -/// -/// This has the same effect as two subsequent newlines. -#[derive(Debug, PartialEq)] -pub struct Parbreak; - -function! { - data: Parbreak, - parse: plain, - layout(_, _) { Ok(commands![FinishFlex]) } -} - -/// 📜 `page.break`: Ends the current page. -#[derive(Debug, PartialEq)] -pub struct Pagebreak; - -function! { - data: Pagebreak, - parse: plain, - layout(_, _) { Ok(commands![BreakStack]) } -} - -/// 📐 `align`: Aligns content in different ways. -/// -/// **Positional arguments:** -/// - `left`, `right` or `center` _(required)_. -#[derive(Debug, PartialEq)] -pub struct Align { - body: Option<SyntaxTree>, - alignment: Alignment, -} - -function! { - data: Align, - - parse(args, body, ctx) { - let body = parse!(optional: body, ctx); - let arg = args.get_pos::<ArgIdent>()?; - let alignment = match arg.val { - "left" => Alignment::Left, - "right" => Alignment::Right, - "center" => Alignment::Center, - s => err!("invalid alignment specifier: {}", s), - }; - args.done()?; - - Ok(Align { - body, - alignment, - }) - } - - layout(this, ctx) { - Ok(commands![match &this.body { - Some(body) => { - AddMany(layout_tree(body, LayoutContext { - alignment: this.alignment, - .. ctx - })?) - } - None => SetAlignment(this.alignment) - }]) - } -} - -/// 📦 `box`: Layouts content into a box. -/// -/// **Positional arguments:** None. -/// -/// **Keyword arguments:** -/// - flow: either `horizontal` or `vertical` _(optional)_. -#[derive(Debug, PartialEq)] -pub struct Boxed { - body: SyntaxTree, - flow: Flow, -} - -function! { - data: Boxed, - - parse(args, body, ctx) { - let body = parse!(required: body, ctx); - - let mut flow = Flow::Vertical; - if let Some(ident) = args.get_key_opt::<ArgIdent>("flow")? { - flow = match ident.val { - "vertical" => Flow::Vertical, - "horizontal" => Flow::Horizontal, - f => err!("invalid flow specifier: {}", f), - }; - } - args.done()?; - - Ok(Boxed { - body, - flow, - }) - } - - layout(this, ctx) { - Ok(commands![ - AddMany(layout_tree(&this.body, LayoutContext { - flow: this.flow, - .. ctx - })?) - ]) - } -} - -macro_rules! spacefunc { - ($ident:ident, $doc:expr, $var:ident => $command:expr) => ( - #[doc = $doc] - /// - /// **Positional arguments:** - /// - Spacing as a size or number, which is interpreted as a multiple - /// of the font size _(required)_. - #[derive(Debug, PartialEq)] - pub struct $ident(Spacing); - - function! { - data: $ident, - - parse(args, body, _ctx) { - parse!(forbidden: body); - - let arg = args.get_pos::<ArgExpr>()?; - let spacing = match arg.val { - Expression::Size(s) => Spacing::Absolute(*s), - Expression::Num(f) => Spacing::Relative(*f as f32), - _ => err!("invalid spacing, expected size or number"), - }; - - Ok($ident(spacing)) - } - - layout(this, ctx) { - let $var = match this.0 { - Spacing::Absolute(s) => s, - Spacing::Relative(f) => f * ctx.style.font_size, - }; - - Ok(commands![$command]) - } - } - ); -} - -/// Absolute or font-relative spacing. -#[derive(Debug, PartialEq)] -enum Spacing { - Absolute(Size), - Relative(f32), -} - -spacefunc!(HorizontalSpace, "📖 `h`: Adds horizontal whitespace.", - space => AddFlex(Layout::empty(space, Size::zero()))); - -spacefunc!(VerticalSpace, "📑 `v`: Adds vertical whitespace.", - space => Add(Layout::empty(Size::zero(), space))); diff --git a/src/library/style.rs b/src/library/style.rs index 9bcdcccd..90a5fd31 100644 --- a/src/library/style.rs +++ b/src/library/style.rs @@ -23,17 +23,17 @@ macro_rules! stylefunc { Ok(match &this.body { Some(body) => commands![ - Command::SetStyle(new_style), - Command::LayoutTree(body), - Command::SetStyle(ctx.style.clone()), + SetStyle(new_style), + LayoutTree(body), + SetStyle(ctx.style.clone()), ], - None => commands![Command::SetStyle(new_style)] + None => commands![SetStyle(new_style)] }) } } ); } -stylefunc!(Italic, "💡 `italic`: Sets text in _italics_."); -stylefunc!(Bold, "🧱 `bold`: Sets text in **bold**."); -stylefunc!(Monospace, "👩💻 `mono`: Sets text in `monospace`."); +stylefunc!(Italic, "`italic`: Sets text in _italics_."); +stylefunc!(Bold, "`bold`: Sets text in **bold**."); +stylefunc!(Monospace, "`mono`: Sets text in `monospace`."); |
