summaryrefslogtreecommitdiff
path: root/src/library/spacing.rs
blob: 010594847585b3d07abff41820ac76b2243ca07b (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
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![FinishLine]) }
}

/// `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![BreakParagraph]) }
}

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.text_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));