diff --git a/Cargo.toml b/Cargo.toml index 3d93f1d..40a9121 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rematch" -version = "0.2.0" +version = "0.3.0" authors = ["Avril "] edition = "2024" diff --git a/src/main.rs b/src/main.rs index 4cbb19f..3fccdf6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -18,15 +18,43 @@ fn initialise() -> eyre::Result<()> Ok(()) } -fn print_group(to: &mut S, g: G, group: usize) -> std::io::Result<()> +#[inline] +fn print_groups<'a, S: ?Sized, G, T: 'a, I>(to: &mut S, g: G, groups: I) -> std::io::Result<()> where S: std::io::Write, - G: IntoIterator>, - T: std::borrow::Borrow + G: IntoIterator> + Clone + Copy, // NOTE: Copy bound to ensure we're not accidentally doing deep clones of `g`. +//G: std::ops::Index, G::Output: std::borrow::Borrow>, + T: std::borrow::Borrow, + I: IntoIterator/*, IntoIter: ExactSizeIterator*/>, { - match g.into_iter().nth(group) { - Some(None) => writeln!(to, ""), - Some(Some(g)) => writeln!(to, "{}", g.borrow()), - None => Ok(()), + use std::borrow::Borrow; + let mut first = true; + for group in groups.into_iter() { + let group = group.borrow(); + // // Moved to into match group (skipping invalid groups.) + // if !first { + // write!(to, "\t")?; + // } + let print_delim = || first.then_some("").unwrap_or("\t"); // If it's not the first iteration, print `\t`. + match g.into_iter().nth(*group) { + Some(None) => write!(to, "{}", print_delim()), + Some(Some(g)) => write!(to, "{}{}", print_delim(), g.borrow()), + + //TODO: What should be the behaviour of a non-existent group index here? (NOTE: This now corresponds to the previous `g.len() > group` check in caller.) // (NOTE: The original behaviour is to just ignore groups that are out of range entirely (i.e. no printing, no delimit char, no error,) maybe treat non-existent groups as non-matched groups and *just* print the delim char?) + // (NOTE: Moved out of branch, see above ^) // None if !first => write!(to, "\t"), + // XXX: Should this do what it does now...? Or should it `break` to prevent the checking for more groups...? Print a warning maybe...? + None => { + eprintln!("Warning: Invalid group index {}!", group); + continue; // Do not set `first = false` if it was an invalid index. + //Ok(()) + }, + }?; + first = false; + } + // If `first == true`, no groups were printed, so we do not print the new-line. + if !first { + to.write_all(b"\n") + } else { + Ok(()) } } @@ -34,30 +62,49 @@ fn main() -> eyre::Result<()> { initialise().wrap_err("Fatal: Failed to install panic handle")?; - // let cli = args::parse_cli();//.wrap_err("Error parsing command-line arguments")?; - // - // eprintln!("{:#?}", cli); + //let cli = args::parse_cli();//.wrap_err("Error parsing command-line arguments")?; + + //eprintln!("{:#?}", cli); // return Ok(()); - let args: Vec = std::env::args().collect(); + let args: re::FrozenVec = std::env::args().map(String::into_boxed_str).collect(); if args.len() < 4 { - println!("Usage: {} ", args[0]); + println!("Usage: {} ...", args[0]); println!("Pass `-' as `' to read lines from stdin"); - std::process::exit(1); + std::process::exit(1) } else { let re = re::Regex::compile(&args[2])?; let text = &args[1]; - let group: usize = args[3].parse().expect("Invalid group number."); + + let groups = &args[3..]; + + if groups.len() < 1 { + eprintln!("Warning: No capture groups requested."); + // NOTE: Unexpected branch... + return Ok(()); + } + + let groups = groups.iter().enumerate() + .map(|(i, x)| x.parse() + .with_section(|| format!("{:?}", groups).header("Groups specified were")) + .with_section(|| x.clone().header("Specified capture group index was")) + .with_section(move || i.header("Argument index in provided groups"))) + .collect::, _>>() + .wrap_err("Invalid group index specified")?; + + //TODO: XXX: How to handle multiple groups in `stdin_lines()` case? + //let group = groups[0]; //args[3].parse().expect("Invalid group number."); use std::io::Write; let mut stdout = std::io::stdout(); - if text == "-" { + if &text[..] == "-" { text::stdin_lines(|text| -> eyre::Result { let mut stdout = stdout.lock(); match re.exec(&text)? { - Some(g) if g.len() > group => print_group(&mut stdout, g, group)?, //println!("{}", &g[group]), + Some(g) /*if g.len() > group*/ => // NOTE: This check branch has now been moved into `print_groups()` + print_groups(&mut stdout, &g, &groups)?, //println!("{}", &g[group]), _ => (), } Ok(true) @@ -65,7 +112,7 @@ fn main() -> eyre::Result<()> } else { match re.exec(&text)? { - Some(g) if g.len() > group => print_group(&mut stdout, g, group)?,//println!("{}", &g.nth(group).unwrap().map(|x| x.as_ref()).unwrap_or("")), + Some(g) /*if g.len() > group*/ => print_groups(&mut stdout, &g[..], &groups)?,//println!("{}", &g.nth(group).unwrap().map(|x| x.as_ref()).unwrap_or("")), _ => (), } }