whiteout/parser/
inline.rs1use anyhow::Result;
2use once_cell::sync::Lazy;
3use regex::Regex;
4
5use super::Decoration;
6
7static INLINE_PATTERN: Lazy<Regex> = Lazy::new(|| {
9 Regex::new(r"(?m)^(.+?)\s*(?://|#|--)\s*@whiteout:\s*(.+?)$")
10 .expect("Failed to compile inline pattern")
11});
12
13pub struct InlineParser;
14
15impl Default for InlineParser {
16 fn default() -> Self {
17 Self::new()
18 }
19}
20
21impl InlineParser {
22 pub fn new() -> Self {
23 let _ = &*INLINE_PATTERN;
25 Self
26 }
27
28 pub fn parse(&self, content: &str) -> Result<Vec<Decoration>> {
29 let mut decorations = Vec::new();
30
31 for (line_num, line) in content.lines().enumerate() {
32 if line.contains(r"\@whiteout:") {
34 continue;
35 }
36 if let Some(captures) = INLINE_PATTERN.captures(line) {
37 let local_value = captures.get(1).unwrap().as_str().to_string();
38 let committed_value = captures.get(2).unwrap().as_str().to_string();
39
40 decorations.push(Decoration::Inline {
41 line: line_num + 1,
42 local_value: local_value.trim().to_string(),
43 committed_value: committed_value.trim().to_string(),
44 });
45 }
46 }
47
48 Ok(decorations)
49 }
50}
51
52#[cfg(test)]
53mod tests {
54 use super::*;
55
56 #[test]
57 fn test_inline_parser() {
58 let parser = InlineParser::new();
59 let content = r#"let api_key = "sk-12345"; // @whiteout: load_from_env()"#;
60
61 let decorations = parser.parse(content).unwrap();
62 assert_eq!(decorations.len(), 1);
63
64 match &decorations[0] {
65 Decoration::Inline { line, local_value, committed_value } => {
66 assert_eq!(*line, 1);
67 assert_eq!(local_value, r#"let api_key = "sk-12345";"#);
68 assert_eq!(committed_value, "load_from_env()");
69 }
70 _ => panic!("Expected inline decoration"),
71 }
72 }
73
74 #[test]
75 fn test_multiple_inline_decorations() {
76 let parser = InlineParser::new();
77 let content = r#"
78let api_key = "sk-12345"; // @whiteout: load_from_env()
79let debug = true; // @whiteout: false
80let url = "http://localhost"; // @whiteout: "https://api.example.com"
81"#;
82
83 let decorations = parser.parse(content).unwrap();
84 assert_eq!(decorations.len(), 3);
85 }
86}