org_rust_parser/object/
export_snippet.rs

1use crate::constants::{COLON, HYPHEN, NEWLINE};
2use crate::node_pool::NodeID;
3use crate::types::{Cursor, MatchError, ParseOpts, Parseable, Parser, Result};
4
5#[derive(Debug, Clone, PartialEq, Eq)]
6pub struct ExportSnippet<'a> {
7    pub backend: &'a str,
8    pub contents: &'a str,
9}
10
11impl<'a> Parseable<'a> for ExportSnippet<'a> {
12    fn parse(
13        parser: &mut Parser<'a>,
14        mut cursor: Cursor<'a>,
15        parent: Option<NodeID>,
16        parse_opts: ParseOpts,
17    ) -> Result<NodeID> {
18        let start = cursor.index;
19        cursor.word("@@")?;
20        let backend_match = cursor
21            .fn_until(|chr| chr == COLON || !(chr.is_ascii_alphanumeric() || chr == HYPHEN))?;
22
23        cursor.index = backend_match.end;
24        cursor.word(":")?;
25
26        let start_contents = cursor.index;
27        loop {
28            let pot_match = cursor.fn_until(|chr| chr == b'@' || chr == NEWLINE)?;
29            cursor.index = pot_match.end;
30            match cursor.curr() {
31                b'@' => {
32                    if cursor.peek(1)? == b'@' {
33                        return Ok(parser.alloc(
34                            Self {
35                                backend: backend_match.obj,
36                                contents: cursor.clamp_backwards(start_contents),
37                            },
38                            start,
39                            cursor.index + 2,
40                            parent,
41                        ));
42                    } else {
43                        cursor.next();
44                    }
45                }
46                _ => return Err(MatchError::InvalidLogic),
47            }
48        }
49    }
50}
51
52#[cfg(test)]
53mod tests {
54    use crate::{expr_in_pool, parse_org, types::Expr};
55
56    use super::*;
57
58    #[test]
59    fn basic_export() {
60        let input = r"
61@@:@@
62";
63
64        let parsed = parse_org(input);
65        let l = expr_in_pool!(parsed, ExportSnippet).unwrap();
66        assert_eq!(
67            l,
68            &ExportSnippet {
69                backend: "",
70                contents: ""
71            }
72        );
73    }
74
75    #[test]
76    fn cool_export() {
77        let input = r"
78@@html:valuesss@@
79";
80        let parsed = parse_org(input);
81        let l = expr_in_pool!(parsed, ExportSnippet).unwrap();
82        assert_eq!(
83            l,
84            &ExportSnippet {
85                backend: "html",
86                contents: "valuesss"
87            }
88        );
89    }
90
91    #[test]
92    fn newline_export_snippet() {
93        let input = r"
94@@html:value
95sss@@
96";
97        let pool = parse_org(input);
98        let parsed = parse_org(input);
99        let l = expr_in_pool!(parsed, ExportSnippet);
100        assert!(l.is_none());
101    }
102
103    #[test]
104    fn at_export_snippet() {
105        let input = r"
106@@html:va@lue sss@@
107";
108        let pool = parse_org(input);
109        let head = pool.pool.iter().find_map(|x| {
110            if let Expr::ExportSnippet(snip) = &x.obj {
111                Some(snip)
112            } else {
113                None
114            }
115        });
116        assert_eq!(
117            head.unwrap(),
118            &ExportSnippet {
119                backend: "html",
120                contents: "va@lue sss"
121            }
122        );
123    }
124}