Skip to main content

snapper_fmt/parser/
plaintext.rs

1use crate::parser::{
2    ByteSpan, FormatParser, SpannedRegion, flush_prose_spanned, iter_lines, push_prose_line,
3};
4
5/// Trivial parser: everything is prose, blank lines are preserved.
6pub struct PlaintextParser;
7
8impl FormatParser for PlaintextParser {
9    fn parse_full(&self, input: &str) -> Vec<SpannedRegion> {
10        let mut regions = Vec::new();
11        let mut current_prose = String::new();
12        let mut prose_span: Option<ByteSpan> = None;
13        let mut pragma_off = false;
14
15        for line in iter_lines(input) {
16            // Check for snapper:off/on pragmas
17            if let Some(on) = super::check_pragma(line.text) {
18                flush_prose_spanned(&mut current_prose, &mut prose_span, &mut regions);
19                pragma_off = !on;
20                regions.push(SpannedRegion::structure(input, line.span()));
21                continue;
22            }
23
24            if pragma_off {
25                flush_prose_spanned(&mut current_prose, &mut prose_span, &mut regions);
26                regions.push(SpannedRegion::structure(input, line.span()));
27                continue;
28            }
29
30            if line.text.trim().is_empty() {
31                flush_prose_spanned(&mut current_prose, &mut prose_span, &mut regions);
32                regions.push(SpannedRegion::blank(input, line.span()));
33            } else {
34                push_prose_line(&mut current_prose, &mut prose_span, &line, true, true);
35            }
36        }
37
38        flush_prose_spanned(&mut current_prose, &mut prose_span, &mut regions);
39        regions
40    }
41}
42
43#[cfg(test)]
44mod tests {
45    use super::*;
46    use crate::parser::Region;
47
48    #[test]
49    fn simple_paragraph() {
50        let input = "Hello world. This is a test.\nAnother line here.";
51        let regions = PlaintextParser.parse(input);
52        assert_eq!(
53            regions,
54            vec![Region::Prose(
55                "Hello world. This is a test. Another line here.".to_string()
56            )]
57        );
58    }
59
60    #[test]
61    fn two_paragraphs() {
62        let input = "First paragraph.\n\nSecond paragraph.";
63        let regions = PlaintextParser.parse(input);
64        assert_eq!(
65            regions,
66            vec![
67                Region::Prose("First paragraph.".to_string()),
68                Region::BlankLines("\n".to_string()),
69                Region::Prose("Second paragraph.".to_string()),
70            ]
71        );
72    }
73
74    #[test]
75    fn empty_input() {
76        let regions = PlaintextParser.parse("");
77        assert!(regions.is_empty());
78    }
79}