summaryrefslogtreecommitdiff
path: root/src/library/align.rs
blob: 3b06fe2c34f71533673caa7236e682490897ad72 (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
use crate::func::prelude::*;
use super::maps::ConsistentMap;
use super::keys::{AxisKey, AlignmentKey};

function! {
    /// `align`: Aligns content along the layouting axes.
    #[derive(Debug, PartialEq)]
    pub struct Align {
        body: Option<SyntaxTree>,
        map: ConsistentMap<Key, AlignmentKey>,
    }

    parse(args, body, ctx) {
        let mut map = ConsistentMap::new();

        map.add_opt_span(Key::First, args.get_pos_opt::<AlignmentKey>()?)?;
        map.add_opt_span(Key::Second, args.get_pos_opt::<AlignmentKey>()?)?;

        for arg in args.keys() {
            let axis = AxisKey::from_ident(&arg.v.key)?;
            let value = AlignmentKey::from_expr(arg.v.value)?;

            map.add(Key::Axis(axis), value)?;
        }

        Align {
            body: parse!(optional: body, ctx),
            map,
        }
    }

    layout(self, mut ctx) {
        let axes = ctx.axes;

        let map = self.map.dedup(|key, alignment| {
            let axis = match key {
                Key::First => alignment.axis(axes, GenericAxisKind::Primary),
                Key::Second => alignment.axis(axes, GenericAxisKind::Secondary),
                Key::Axis(AxisKey::Primary) => GenericAxisKind::Primary,
                Key::Axis(AxisKey::Secondary) => GenericAxisKind::Secondary,
                Key::Axis(AxisKey::Horizontal) => axes.horizontal(),
                Key::Axis(AxisKey::Vertical) => axes.vertical(),
            };

            let alignment = alignment.generic(axes, axis)?;
            Ok((axis, alignment))
        })?;

        map.with(GenericAxisKind::Primary, |&val| ctx.alignment.primary = val);
        map.with(GenericAxisKind::Secondary, |&val| ctx.alignment.secondary = val);

        match &self.body {
            Some(body) => vec![AddMultiple(layout_tree(&body, ctx)?)],
            None => vec![Command::SetAlignment(ctx.alignment)],
        }
    }
}

#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
enum Key {
    First,
    Second,
    Axis(AxisKey),
}