asciidoc_parser/inlines/
macro.rs

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
use crate::{span::MatchedItem, HasSpan, Span};

/// An inline macro can be used in an inline context to create new inline
/// content.
///
/// This struct is returned when the inline form of a *named macro* is detected.
///
/// ```ignore
/// <name>:<target>?[<attrlist>?].
/// ```
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct InlineMacro<'src> {
    name: Span<'src>,
    target: Option<Span<'src>>,
    attrlist: Option<Span<'src>>,
    source: Span<'src>,
}

impl<'src> InlineMacro<'src> {
    pub(crate) fn parse(source: Span<'src>) -> Option<MatchedItem<'src, Self>> {
        let name = source.take_ident()?;
        let colon = name.after.take_prefix(":")?;
        let target = colon.after.take_while(|c| c != '[');
        let open_brace = target.after.take_prefix("[")?;
        let attrlist = open_brace.after.take_while(|c| c != ']');
        let close_brace = attrlist.after.take_prefix("]")?;
        let source = source.trim_remainder(close_brace.after);

        Some(MatchedItem {
            item: Self {
                name: name.item,
                target: if target.item.is_empty() {
                    None
                } else {
                    Some(target.item)
                },
                attrlist: if attrlist.item.is_empty() {
                    None
                } else {
                    Some(attrlist.item)
                },
                source,
            },
            after: close_brace.after,
        })
    }

    /// Return a [`Span`] describing the macro name.
    pub fn name(&'src self) -> &'src Span<'src> {
        &self.name
    }

    /// Return a [`Span`] describing the macro target.
    pub fn target(&'src self) -> Option<&'src Span<'src>> {
        self.target.as_ref()
    }

    /// Return a [`Span`] describing the macro's attribute list.
    pub fn attrlist(&'src self) -> Option<&'src Span<'src>> {
        self.attrlist.as_ref()
    }
}

impl<'src> HasSpan<'src> for InlineMacro<'src> {
    fn span(&'src self) -> &'src Span<'src> {
        &self.source
    }
}