diff options
| author | Laurenz <laurmaedje@gmail.com> | 2019-10-22 21:40:37 +0200 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2019-10-22 21:40:37 +0200 |
| commit | cff325b520727ac0eec46a3757831afaa0916cc1 (patch) | |
| tree | 18cef7a7880fef41050678ab479818e0abb91f14 /src/library | |
| parent | 991e879e1d2ed53125dbff4edba80804ff28f2a9 (diff) | |
Add spacing functions 🔛
Diffstat (limited to 'src/library')
| -rw-r--r-- | src/library/mod.rs | 12 | ||||
| -rw-r--r-- | src/library/spacing.rs | 76 |
2 files changed, 86 insertions, 2 deletions
diff --git a/src/library/mod.rs b/src/library/mod.rs index d0c987a4..784ef204 100644 --- a/src/library/mod.rs +++ b/src/library/mod.rs @@ -5,6 +5,7 @@ use crate::func::Scope; mod align; mod boxed; mod breaks; +mod spacing; mod styles; /// Useful imports for creating your own functions. @@ -20,6 +21,7 @@ pub mod prelude { pub use align::AlignFunc; pub use boxed::BoxFunc; pub use breaks::{LinebreakFunc, PagebreakFunc}; +pub use spacing::{HorizontalSpaceFunc, VerticalSpaceFunc}; pub use styles::{BoldFunc, ItalicFunc, MonospaceFunc}; /// Create a scope with all standard functions. @@ -27,15 +29,21 @@ pub fn std() -> Scope { let mut std = Scope::new(); std.add::<AlignFunc>("align"); std.add::<BoxFunc>("box"); - std.add::<LinebreakFunc>("linebreak"); + + std.add::<LinebreakFunc>("line.break"); std.add::<LinebreakFunc>("n"); - std.add::<PagebreakFunc>("pagebreak"); + std.add::<PagebreakFunc>("page.break"); + + std.add::<HorizontalSpaceFunc>("h"); + std.add::<VerticalSpaceFunc>("v"); + std.add::<BoldFunc>("bold"); std.add::<ItalicFunc>("italic"); std.add::<MonospaceFunc>("mono"); std } +/// Helpers for writing custom functions. pub mod helpers { use super::prelude::*; diff --git a/src/library/spacing.rs b/src/library/spacing.rs new file mode 100644 index 00000000..91288edc --- /dev/null +++ b/src/library/spacing.rs @@ -0,0 +1,76 @@ +use std::marker::PhantomData; +use super::prelude::*; +use crate::size::Size; + +/// Adds vertical space. +pub type VerticalSpaceFunc = SpaceFunc<SpaceVertical>; + +/// Adds horizontal space. +pub type HorizontalSpaceFunc = SpaceFunc<SpaceHorizontal>; + +/// Adds generic space. +#[derive(Debug, PartialEq)] +pub struct SpaceFunc<F: SpaceFlow> { + spacing: Spacing, + _phantom: PhantomData<F>, +} + +/// Absolute or font-relative spacing. +#[derive(Debug, PartialEq)] +enum Spacing { + Absolute(Size), + Relative(f32), +} + +impl<F: SpaceFlow> Function for SpaceFunc<F> { + fn parse(header: &FuncHeader, body: Option<&str>, _: ParseContext) -> ParseResult<Self> + where Self: Sized { + if header.args.len() != 1 || !header.kwargs.is_empty() { + return err("align: expected exactly one positional argument"); + } + + let spacing = match header.args[0] { + Expression::Size(s) => Spacing::Absolute(s), + Expression::Number(f) => Spacing::Relative(f as f32), + _ => return err("space: expected size or number"), + }; + + if body.is_some() { + return err("space: expected no body"); + } + + Ok(SpaceFunc { + spacing, + _phantom: PhantomData, + }) + } + + fn layout(&self, ctx: LayoutContext) -> LayoutResult<CommandList> { + let space = match self.spacing { + Spacing::Absolute(s) => s, + Spacing::Relative(f) => Size::pt(f * ctx.style.font_size), + }; + + Ok(commands![F::cmd(space)]) + } +} + +pub trait SpaceFlow: std::fmt::Debug + PartialEq + 'static { + fn cmd(space: Size) -> Command<'static>; +} + +#[derive(Debug, PartialEq)] +pub struct SpaceVertical; +impl SpaceFlow for SpaceVertical { + fn cmd(space: Size) -> Command<'static> { + Command::Add(Layout::empty(Size::zero(), space)) + } +} + +#[derive(Debug, PartialEq)] +pub struct SpaceHorizontal; +impl SpaceFlow for SpaceHorizontal { + fn cmd(space: Size) -> Command<'static> { + Command::AddFlex(Layout::empty(space, Size::zero())) + } +} |
