feat: improve match_pattern to surface errors and avoid collecting everything at once
feat: implement Match and Matches to hold more info and display it
This commit is contained in:
parent
d58ae9ffbe
commit
660b710cac
3 changed files with 62 additions and 6 deletions
|
|
@ -1,4 +1,5 @@
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
|
mod matches;
|
||||||
mod parser;
|
mod parser;
|
||||||
|
|
||||||
#[derive(Parser)]
|
#[derive(Parser)]
|
||||||
|
|
@ -11,12 +12,12 @@ fn main() -> anyhow::Result<()> {
|
||||||
let cli = Cli::parse();
|
let cli = Cli::parse();
|
||||||
|
|
||||||
let lines_iter = parser::read_lines(&cli.file_path)?;
|
let lines_iter = parser::read_lines(&cli.file_path)?;
|
||||||
let matches = parser::match_pattern(lines_iter, &cli.pattern);
|
let matches = parser::match_pattern(lines_iter, &cli.pattern, &cli.file_path);
|
||||||
|
|
||||||
println!("Pattern: {}", cli.pattern);
|
println!("Pattern: {}", cli.pattern);
|
||||||
println!("File path: {}", cli.file_path);
|
println!("File path: {}", cli.file_path);
|
||||||
println!("---");
|
println!("---");
|
||||||
println!("{:?}", matches);
|
println!("{}", matches?);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
33
src/matches.rs
Normal file
33
src/matches.rs
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
use std::fmt::Display;
|
||||||
|
|
||||||
|
pub struct Match {
|
||||||
|
pub file_name: String,
|
||||||
|
pub line_number: usize,
|
||||||
|
pub text: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Matches {
|
||||||
|
pub items: Vec<Match>,
|
||||||
|
pub pattern: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for Match {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, "{}: line {}: {}", self.file_name, self.line_number, self.text)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for Matches {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
writeln!(f, "Matches for pattern {}:", self.pattern);
|
||||||
|
|
||||||
|
for (idx, item) in self.items.iter().enumerate() {
|
||||||
|
if idx > 0 {
|
||||||
|
writeln!(f)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
write!(f, "{}", item);
|
||||||
|
}
|
||||||
|
write!(f, "{}", "")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -6,6 +6,8 @@ use std::{
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
|
|
||||||
|
use crate::matches::{self, Match, Matches};
|
||||||
|
|
||||||
pub fn read_lines(
|
pub fn read_lines(
|
||||||
file_path: &str,
|
file_path: &str,
|
||||||
) -> anyhow::Result<impl Iterator<Item = std::io::Result<String>>, anyhow::Error> {
|
) -> anyhow::Result<impl Iterator<Item = std::io::Result<String>>, anyhow::Error> {
|
||||||
|
|
@ -20,14 +22,34 @@ pub fn read_lines(
|
||||||
Ok(reader.lines())
|
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(
|
pub fn match_pattern(
|
||||||
iter: impl Iterator<Item = std::io::Result<String>>,
|
iter: impl Iterator<Item = std::io::Result<String>>,
|
||||||
pattern: &str,
|
pattern: &str,
|
||||||
) -> anyhow::Result<Vec<String>, anyhow::Error> {
|
file_path: &str,
|
||||||
|
) -> anyhow::Result<Matches, anyhow::Error> {
|
||||||
let reg = Regex::new(pattern).with_context(|| format!("invalid regex: {:?}", pattern))?;
|
let reg = Regex::new(pattern).with_context(|| format!("invalid regex: {:?}", pattern))?;
|
||||||
let lines = iter.collect::<std::io::Result<Vec<_>>>()?;
|
let mut matches = Vec::new();
|
||||||
|
|
||||||
let matches = lines.into_iter().filter(|line| reg.is_match(line)).collect::<Vec<_>>();
|
for (idx, line) in iter.enumerate() {
|
||||||
|
let line = line?;
|
||||||
|
|
||||||
Ok(matches)
|
if reg.is_match(&line) {
|
||||||
|
let m = Match {
|
||||||
|
line_number: idx,
|
||||||
|
text: line,
|
||||||
|
file_name: get_file_name_from_path(file_path),
|
||||||
|
};
|
||||||
|
|
||||||
|
matches.push(m);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Matches { items: matches, pattern: String::from(pattern) })
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue