refactor: extract Cli and add CliOptions struct

test: fix failing test
fix: applied clippy suggested fixes
This commit is contained in:
Mohammad Kanaan 2026-07-27 21:19:14 +03:00
parent 0e20aff140
commit 0f57d037e0
4 changed files with 36 additions and 22 deletions

23
src/cli.rs Normal file
View file

@ -0,0 +1,23 @@
use clap::Parser;
use std::path::PathBuf;
#[derive(Parser)]
pub struct Cli {
pub(crate) pattern: String,
#[arg(value_name = "FILES", num_args = 1..)]
pub(crate) file_paths: Vec<PathBuf>,
#[arg(short, long)]
pub(crate) ignore_case: bool,
}
pub struct CliOptions {
pub ignore_case: bool,
}
impl Cli {
pub fn get_options(&self) -> CliOptions {
CliOptions { ignore_case: self.ignore_case }
}
}

View file

@ -1,21 +1,11 @@
use std::{path::PathBuf, process::ExitCode}; use std::process::ExitCode;
use clap::Parser; use crate::{cli::Cli, matches::Matches, parser::process_files};
mod cli;
use crate::{matches::Matches, parser::process_files};
mod matches; mod matches;
mod parser; mod parser;
#[derive(Parser)] use clap::Parser;
struct Cli {
pattern: String,
#[arg(value_name = "FILES", num_args = 1..)]
file_paths: Vec<PathBuf>,
#[arg(short, long)]
ignore_case: bool,
}
fn main() -> ExitCode { fn main() -> ExitCode {
match run() { match run() {
@ -36,7 +26,7 @@ fn run() -> anyhow::Result<Matches> {
// println!("{:?} {}", cli.file_paths, cli.pattern); // println!("{:?} {}", cli.file_paths, cli.pattern);
let matches = process_files(&cli.file_paths, &cli.pattern, &cli)?; let matches = process_files(&cli.file_paths, &cli.pattern, &cli.get_options())?;
Ok(matches) Ok(matches)
} }

View file

@ -16,7 +16,7 @@ impl Matches {
self.items.is_empty() self.items.is_empty()
} }
pub fn append(&mut self, matches: &mut Self) -> () { pub fn append(&mut self, matches: &mut Self) {
self.items.append(&mut matches.items); self.items.append(&mut matches.items);
} }
} }

View file

@ -8,17 +8,17 @@ use anyhow::Context;
use regex::{Regex, RegexBuilder}; use regex::{Regex, RegexBuilder};
use crate::{ use crate::{
cli::CliOptions,
matches::{Match, Matches}, matches::{Match, Matches},
Cli,
}; };
pub fn process_files( pub fn process_files(
file_paths: &Vec<PathBuf>, file_paths: &Vec<PathBuf>,
pattern: &str, pattern: &str,
cli: &Cli, cli_options: &CliOptions,
) -> anyhow::Result<Matches, anyhow::Error> { ) -> anyhow::Result<Matches, anyhow::Error> {
let reg = RegexBuilder::new(pattern) let reg = RegexBuilder::new(pattern)
.case_insensitive(cli.ignore_case) .case_insensitive(cli_options.ignore_case)
.build() .build()
.with_context(|| format!("invalid regex: {:?}", pattern))?; .with_context(|| format!("invalid regex: {:?}", pattern))?;
@ -26,7 +26,7 @@ pub fn process_files(
for file_path in file_paths { for file_path in file_paths {
let lines_iter = read_lines(file_path)?; let lines_iter = read_lines(file_path)?;
let mut _matches = match_pattern(lines_iter, pattern, file_path, &reg, cli)?; let mut _matches = match_pattern(lines_iter, pattern, file_path, &reg)?;
matches.append(&mut _matches); matches.append(&mut _matches);
} }
@ -66,7 +66,6 @@ pub fn match_pattern(
pattern: &str, pattern: &str,
file_path: &Path, file_path: &Path,
regex: &Regex, regex: &Regex,
cli: &Cli,
) -> anyhow::Result<Matches, anyhow::Error> { ) -> anyhow::Result<Matches, anyhow::Error> {
let mut matches = Vec::new(); let mut matches = Vec::new();
@ -107,8 +106,10 @@ mod tests {
let input: Vec<std::io::Result<String>> = let input: Vec<std::io::Result<String>> =
vec![Ok("hola".into()), Ok("no".into()), Ok("hola again".into())]; vec![Ok("hola".into()), Ok("no".into()), Ok("hola again".into())];
let reg = Regex::new("hola").unwrap();
let result = let result =
match_pattern(input.into_iter(), r"^hola", Path::new("/tmp/test.txt")).unwrap(); match_pattern(input.into_iter(), r"^hola", Path::new("/tmp/test.txt"), &reg).unwrap();
assert_eq!(result.items.len(), 2); assert_eq!(result.items.len(), 2);