whiteout/parser/
simple.rs1use anyhow::Result;
2use once_cell::sync::Lazy;
3use regex::Regex;
4
5use super::Decoration;
6
7static PATTERN: Lazy<Regex> = Lazy::new(|| {
10 Regex::new(r"(?m)^\s*(?://|#|--|/\*|\*)\s*@whiteout\s*(?:\*/)?$").expect("Failed to compile pattern")
11});
12
13pub struct SimpleParser;
15
16impl Default for SimpleParser {
17 fn default() -> Self {
18 Self::new()
19 }
20}
21
22impl SimpleParser {
23 pub fn new() -> Self {
24 let _ = &*PATTERN;
26 Self
27 }
28
29 pub fn parse(&self, content: &str) -> Result<Vec<Decoration>> {
30 let mut decorations = Vec::new();
31 let lines: Vec<&str> = content.lines().collect();
32 let mut i = 0;
33
34 while i < lines.len() {
35 if PATTERN.is_match(lines[i])
38 && !lines[i].contains(r"\@whiteout")
39 && !lines[i].contains("@whiteout-start")
40 && !lines[i].contains("@whiteout-end")
41 && !lines[i].contains("@whiteout:")
42 && !lines[i].contains("@whiteout-partial") {
43 let start_line = i + 1;
44
45 i += 1;
48
49 if i < lines.len() {
50 let local_content = lines[i].to_string();
52
53 decorations.push(Decoration::Block {
54 start_line,
55 end_line: start_line + 1, local_content,
57 committed_content: String::new(), });
59
60 i += 1; }
62 } else {
64 i += 1;
65 }
66 }
67
68 Ok(decorations)
69 }
70}
71
72#[cfg(test)]
73mod tests {
74 use super::*;
75
76 #[test]
77 fn test_simple_parser() {
78 let parser = SimpleParser::new();
79 let content = r#"normal line
80@whiteout
81this will be hidden
82this stays visible
83
84normal again"#;
85
86 let decorations = parser.parse(content).unwrap();
87 assert_eq!(decorations.len(), 1);
88
89 match &decorations[0] {
90 Decoration::Block { local_content, committed_content, .. } => {
91 assert_eq!(local_content, "this will be hidden");
92 assert!(!local_content.contains("this stays visible"));
93 assert!(committed_content.is_empty());
94 }
95 _ => panic!("Expected block decoration"),
96 }
97 }
98}