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
72
73
74
75
76
77
78
79
80
use {
    super::*,
    crate::{
        CompoundStyle,
        ATTRIBUTES,
    },
};

/// Read a Minimad CompoundStyle from a string.
///
/// May contain attributes and from 0 to 2 colors, the first encountered
/// one being the foreground.
///
/// Examples:
/// * `#ab00c1 strikeout`
/// * `"red yellow bold italic"`
/// * `""`
/// * `"gray(2) gray(20)"`
/// * `""`
pub fn parse_compound_style(s: &str) -> Result<CompoundStyle, ParseStyleTokenError> {
    let tokens = parse_style_tokens(s)?;
    Ok(tokens.as_slice().into())
}

impl From<&[StyleToken]> for CompoundStyle {
    fn from(tokens: &[StyleToken]) -> Self {
        let mut style = Self::default();
        // first encountered color or None is considered as the foreground
        // and the following one(s) as the background
        let mut fg_set = false;
        for token in tokens {
            match token {
                StyleToken::Color(c) => {
                    if fg_set {
                        style.set_bg(*c);
                    } else {
                        style.set_fg(*c);
                        fg_set = true;
                    }
                }
                StyleToken::None => {
                    if !fg_set {
                        fg_set = true;
                    }
                }
                StyleToken::Attribute(attribute) => {
                    style.add_attr(*attribute);
                }
                StyleToken::Char(_) => {
                    // not of use for compound styles
                }
                StyleToken::Align(_) => {
                    // not of use for compound styles
                }
                StyleToken::Dimension(_) => {
                    // not of use for compound styles
                }
            }
        }
        style
    }
}

impl PushStyleTokens for CompoundStyle {
    fn push_style_tokens(&self, tokens: &mut Vec<StyleToken>) {
        if let Some(fg) = self.get_fg() {
            tokens.push(StyleToken::Color(fg));
        } else if self.get_bg().is_some() {
            tokens.push(StyleToken::None);
        }
        if let Some(bg) = self.get_bg() {
            tokens.push(StyleToken::Color(bg));
        }
        for &attr in ATTRIBUTES {
            if self.has_attr(attr) {
                tokens.push(StyleToken::Attribute(attr));
            }
        }
    }
}