From c1fdfbdcc88d741ebae68ff7b552cd8bc54716d3 Mon Sep 17 00:00:00 2001 From: Paul Campbell Date: Tue, 21 Mar 2023 20:43:10 +0000 Subject: [PATCH] skip until matching lines seen --- src/lib.rs | 82 ++++++++++++++++++++++++++++++++++++++++++++++------- src/main.rs | 4 +-- 2 files changed, 73 insertions(+), 13 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index c82db68..7e89d00 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -22,23 +22,69 @@ pub struct Cli { ignore_extras: bool, } -pub fn skip(cli: Cli, mut out: F) -> io::Result<()> +pub fn skip(cli: &Cli, mut out: F) -> io::Result<()> where F: FnMut(String) -> () { match &cli.file { - Some(file) => { - let content = fs::read_to_string(file).expect("Could not read file"); - let mut counter = 0usize; - for current_line in content.lines() { - counter += 1; - if counter > cli.lines { - out(String::from(current_line)); - } + Some(ref file) => { + if let Some(line) = &cli.line { + skip_file_lines_matching(&cli, out, file, line) + } else if let Some(ref token) = cli.token { + skip_file_tokens(cli, out, file, token) + } else { + skip_file_lines(cli, out, file) } }, None => todo!("reading from stdin") } +} +fn skip_file_lines(cli: &Cli, mut out: F, file: &PathBuf) -> io::Result<()> + where F: FnMut(String) -> () +{ + eprintln!("skip_file_lines"); + let content = fs::read_to_string(file).expect("Could not read file"); + let mut counter = 0usize; + for current_line in content.lines() { + if counter >= cli.lines { + out(String::from(current_line)); + } + counter += 1; + } + Ok(()) +} + +fn skip_file_lines_matching(cli: &Cli, mut out: F, file: &PathBuf, line: &str) -> io::Result<()> + where F: FnMut(String) -> () +{ + eprintln!("skip_file_lines_matching"); + let content = fs::read_to_string(file).expect("Could not read file"); + let mut counter = 0usize; + for current_line in content.lines() { + if counter >= cli.lines { + out(String::from(current_line)); + } + if line == current_line { + counter += 1; + } + } + Ok(()) +} + +fn skip_file_tokens(cli: &Cli, mut out: F, file: &PathBuf, token: &str) -> io::Result<()> + where F: FnMut(String) -> () +{ + eprintln!("skip_file_lines_tokens"); + let content = fs::read_to_string(file).expect("Could not read file"); + let mut counter = 0usize; + for current_line in content.lines() { + if counter >= cli.lines { + out(String::from(current_line)); + } + if current_line.contains(&token) { + counter += 1; + } + } Ok(()) } @@ -54,7 +100,7 @@ mod tests { let mut lines: Vec = Vec::new(); //when - skip(cli, |line| lines.push(line))?; + skip(&cli, |line| lines.push(line))?; //then assert_eq!(lines, vec!["line 2"]); @@ -68,11 +114,25 @@ mod tests { let mut lines: Vec = Vec::new(); //when - skip(cli, |line| lines.push(line))?; + skip(&cli, |line| lines.push(line))?; //then assert_eq!(lines, vec!["alpha", "gamma"]); Ok(()) } + #[test] + fn skip_two_matching_lines_of_alpha() -> io::Result<()> { + //given + let cli = Cli { lines: 2, file: Some(PathBuf::from("tests/four-lines.txt")), line: Some(String::from("alpha")), token: None, ignore_extras: false }; + let mut lines: Vec = Vec::new(); + + //when + skip(&cli, |line| lines.push(line))?; + + //then + assert_eq!(lines, vec!["gamma"]); + Ok(()) + } + } diff --git a/src/main.rs b/src/main.rs index 6c73ba1..418d4ca 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,12 +3,12 @@ use clap::Parser; use std::io::Write; fn main() -> std::io::Result<()> { - let args = Cli::parse(); + let cli = Cli::parse(); let stdout = std::io::stdout(); let mut output = stdout.lock(); - skip(args, |line| { + skip(&cli, |line| { match writeln!(output, "{}", line) { Err(_) => (), Ok(_) => ()