skip until matching lines seen

This commit is contained in:
Paul Campbell 2023-03-21 20:43:10 +00:00
parent 47acf65bf7
commit c1fdfbdcc8
2 changed files with 73 additions and 13 deletions

View file

@ -22,23 +22,69 @@ pub struct Cli {
ignore_extras: bool, ignore_extras: bool,
} }
pub fn skip<F>(cli: Cli, mut out: F) -> io::Result<()> pub fn skip<F>(cli: &Cli, mut out: F) -> io::Result<()>
where F: FnMut(String) -> () where F: FnMut(String) -> ()
{ {
match &cli.file { match &cli.file {
Some(file) => { Some(ref file) => {
let content = fs::read_to_string(file).expect("Could not read file"); if let Some(line) = &cli.line {
let mut counter = 0usize; skip_file_lines_matching(&cli, out, file, line)
for current_line in content.lines() { } else if let Some(ref token) = cli.token {
counter += 1; skip_file_tokens(cli, out, file, token)
if counter > cli.lines { } else {
out(String::from(current_line)); skip_file_lines(cli, out, file)
}
} }
}, },
None => todo!("reading from stdin") None => todo!("reading from stdin")
} }
}
fn skip_file_lines<F>(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<F>(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<F>(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(()) Ok(())
} }
@ -54,7 +100,7 @@ mod tests {
let mut lines: Vec<String> = Vec::new(); let mut lines: Vec<String> = Vec::new();
//when //when
skip(cli, |line| lines.push(line))?; skip(&cli, |line| lines.push(line))?;
//then //then
assert_eq!(lines, vec!["line 2"]); assert_eq!(lines, vec!["line 2"]);
@ -68,11 +114,25 @@ mod tests {
let mut lines: Vec<String> = Vec::new(); let mut lines: Vec<String> = Vec::new();
//when //when
skip(cli, |line| lines.push(line))?; skip(&cli, |line| lines.push(line))?;
//then //then
assert_eq!(lines, vec!["alpha", "gamma"]); assert_eq!(lines, vec!["alpha", "gamma"]);
Ok(()) 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<String> = Vec::new();
//when
skip(&cli, |line| lines.push(line))?;
//then
assert_eq!(lines, vec!["gamma"]);
Ok(())
}
} }

View file

@ -3,12 +3,12 @@ use clap::Parser;
use std::io::Write; use std::io::Write;
fn main() -> std::io::Result<()> { fn main() -> std::io::Result<()> {
let args = Cli::parse(); let cli = Cli::parse();
let stdout = std::io::stdout(); let stdout = std::io::stdout();
let mut output = stdout.lock(); let mut output = stdout.lock();
skip(args, |line| { skip(&cli, |line| {
match writeln!(output, "{}", line) { match writeln!(output, "{}", line) {
Err(_) => (), Err(_) => (),
Ok(_) => () Ok(_) => ()