use std::{ fs::File, io::{BufRead, BufReader}, }; use anyhow::Context; use regex::Regex; use crate::matches::{Match, Matches}; pub fn read_lines( file_path: &str, ) -> anyhow::Result>, anyhow::Error> { if file_path.is_empty() { return Err(anyhow::anyhow!("File path cannot be empty")); } let file = File::open(file_path).with_context(|| format!("failed to open file: {file_path}"))?; let reader = BufReader::new(file); Ok(reader.lines()) } fn get_file_name_from_path(file_path: &str) -> String { match file_path.rsplit('/').next() { Some(name) => name.into(), None => file_path.into(), } } pub fn match_pattern( iter: impl Iterator>, pattern: &str, file_path: &str, ) -> anyhow::Result { let reg = Regex::new(pattern).with_context(|| format!("invalid regex: {:?}", pattern))?; let mut matches = Vec::new(); for (idx, line) in iter.enumerate() { let line = line?; if reg.is_match(&line) { let m = Match { line_number: idx + 1, text: line, file_name: get_file_name_from_path(file_path), }; matches.push(m); } } Ok(Matches { items: matches, pattern: String::from(pattern) }) }