#![allow(unused)]
use crate::Config;
use anyhow::{Context, Result};
use regex::Regex;
use std::io::{self, read_to_string, BufRead, BufReader, Write};
use std::{error::Error, fs::File, path::PathBuf};
pub fn run_regex(config: Config) -> Result<()> {
let file = File::open(&config.file_path)
.with_context(|| format!("could not open the file `{:?}`", &config.file_path))?;
let reader = BufReader::new(file);
let contents = read_to_string(reader)
.with_context(|| format!("could not read the file `{:?}`", &config.file_path))?;
let results = if config.ignore_case {
let query_formatted = format!("(?i){}", &config.query);
let query_re = Regex::new(&query_formatted[..])
.with_context(|| format!("given regular expression `{:?}` is wrong", &config.query))?;
search_regex(&query_re, &contents, config.invert_match)
} else {
let query_re = Regex::new(&config.query)
.with_context(|| format!("given regular expression `{:?}` is wrong", &config.query))?;
search_regex(&query_re, &contents, config.invert_match)
};
for line in results {
writeln!(io::BufWriter::new(io::stdout().lock()), "{line}");
}
Ok(())
}
pub fn search_regex<'a>(query_re: &Regex, contents: &'a str, invert: bool) -> Vec<&'a str> {
let mut results = Vec::new();
if invert {
for line in contents.lines() {
if !query_re.is_match(line) {
results.push(line);
}
}
} else {
for line in contents.lines() {
if query_re.is_match(line) {
results.push(line);
}
}
}
results
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn regex_case_sensitive() {
let query = Regex::new("HR[0-9]{3}-[0-9]{3}-[0-9]{4}").unwrap();
let contents = "\
Rust:
safe, fast, productive.
Duckt three.
phone: HR111-222-3333";
assert_eq!(
vec!["phone: HR111-222-3333"],
search_regex(&query, contents, false)
);
}
#[test]
fn regex_case_insensitive() {
let query = Regex::new("(?i)rUsT[0-9]{3}").unwrap();
let contents = "\
Rust123:
RUst324
safe, fast, productive.
Pick three.
Trust me.";
assert_eq!(
vec!["Rust123:", "RUst324"],
search_regex(&query, contents, false)
);
}
#[test]
fn regex_invert_search() {
let query = Regex::new("Duckt[0-9]{3}").unwrap();
let query_insensitive = Regex::new("(?i)Duckt[0-9]{3}").unwrap();
let contents = "\
safe, fast, productive.
Duckt567 three.
duckt980";
assert_ne!(
vec!["Duckt567 three."],
search_regex(&query, contents, true)
);
assert_eq!(
vec!["safe, fast, productive."],
search_regex(&query_insensitive, contents, true)
);
}
}