diff options
author | Dan Davison <dandavison7@gmail.com> | 2021-11-14 21:39:35 -0500 |
---|---|---|
committer | Dan Davison <dandavison7@gmail.com> | 2021-11-14 21:39:35 -0500 |
commit | 7b200a76bbe086050d05fefa33ab6b04f4ee166a (patch) | |
tree | 786ab3f783edfdcf7f3e95b0e6421de838a89f28 | |
parent | b6b841b25870026a323236a2679708eabd074e77 (diff) |
Evolve grep line parsing regex769-git-grep-dev
-rw-r--r-- | src/handlers/grep.rs | 52 |
1 files changed, 41 insertions, 11 deletions
diff --git a/src/handlers/grep.rs b/src/handlers/grep.rs index 1a23e651..49b22435 100644 --- a/src/handlers/grep.rs +++ b/src/handlers/grep.rs @@ -202,7 +202,7 @@ pub struct GrepLine<'a> { pub code: &'a str, } -#[derive(Debug, PartialEq)] +#[derive(Clone, Copy, Debug, PartialEq)] pub enum LineType { ContextHeader, Match, @@ -214,12 +214,28 @@ lazy_static! { static ref GREP_LINE_REGEX: Regex = Regex::new( r"(?x) ^ -([^\ ].*?\.[^-.=: ]+) # 1. file name (TODO: it must have an extension) +( # 1. file name + [^\ ] # a file name cannot start with whitespace + .*? # anything, non-greedily + [^\ ] # a file name cannot end with whitespace +) (?: - [-=:]([0-9]+) # 2. optional line number -)? -([-=:]) # 3. line-type marker -(.*) # 4. code (i.e. line contents) + ( + : # 2. match marker + (?:([0-9]+)?:) # 3. optional line number followed by second match marker + ) + | + ( + - # 4. nomatch marker + (?:([0-9]+)?-) # 5. optional line number followed by second nomatch marker + ) + | + ( + = # 6. match marker + (?:([0-9]+)?=) # 7. optional line number followed by second header marker + ) +) +(.*) # 8. code (i.e. line contents) $ " ) @@ -229,14 +245,28 @@ $ pub fn parse_grep_line(line: &str) -> Option<GrepLine> { let caps = GREP_LINE_REGEX.captures(line)?; let file = caps.get(1).unwrap().as_str(); - let line_number = caps.get(2).map(|m| m.as_str().parse().ok()).flatten(); - let line_type = caps.get(3).map(|m| m.as_str()).try_into().ok()?; - let code = caps.get(4).unwrap().as_str(); + let (line_type, line_number) = &[ + (2, LineType::Match), + (4, LineType::NoMatch), + (6, LineType::ContextHeader), + ] + .iter() + .find_map(|(i, line_type)| { + if caps.get(*i).is_some() { + let line_number: Option<usize> = + caps.get(i + 1).map(|m| m.as_str().parse().ok()).flatten(); + Some((*line_type, line_number)) + } else { + None + } + }) + .unwrap(); // The regex matches so one of the three alternatrives must have matched + let code = caps.get(8).unwrap().as_str(); Some(GrepLine { file, - line_number, - line_type, + line_number: *line_number, + line_type: *line_type, code, }) } |