@ -18,15 +18,43 @@ fn initialise() -> eyre::Result<()>
Ok ( ( ) )
Ok ( ( ) )
}
}
fn print_group < S : ? Sized , G , T > ( 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 ,
where S : std ::io ::Write ,
G : IntoIterator < Item = Option < T > > ,
G : IntoIterator < Item = & ' a Option < T > > + Clone + Copy , // NOTE: Copy bound to ensure we're not accidentally doing deep clones of `g`.
T : std ::borrow ::Borrow < str >
//G: std::ops::Index<usize>, G::Output: std::borrow::Borrow<Option<T>>,
T : std ::borrow ::Borrow < str > ,
I : IntoIterator < Item : std ::borrow ::Borrow < usize > /* , IntoIter: ExactSizeIterator */ > ,
{
{
match g . into_iter ( ) . nth ( group ) {
use std ::borrow ::Borrow ;
Some ( None ) = > writeln! ( to , "" ) ,
let mut first = true ;
Some ( Some ( g ) ) = > writeln! ( to , "{}" , g . borrow ( ) ) ,
for group in groups . into_iter ( ) {
None = > Ok ( ( ) ) ,
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 ( ( ) )
}
}
}
}
@ -35,29 +63,48 @@ fn main() -> eyre::Result<()>
initialise ( ) . wrap_err ( "Fatal: Failed to install panic handle" ) ? ;
initialise ( ) . wrap_err ( "Fatal: Failed to install panic handle" ) ? ;
//let cli = args::parse_cli();//.wrap_err("Error parsing command-line arguments")?;
//let cli = args::parse_cli();//.wrap_err("Error parsing command-line arguments")?;
//
//eprintln!("{:#?}", cli);
//eprintln!("{:#?}", cli);
// return Ok(());
// return Ok(());
let args : Vec < String> = std ::env ::args ( ) . collect ( ) ;
let args : re ::FrozenVec < re ::Frozen String> = std ::env ::args ( ) . map ( String ::into_boxed_str ) . collect ( ) ;
if args . len ( ) < 4 {
if args . len ( ) < 4 {
println! ( "Usage: {} <str> <regex> <group> ", args [ 0 ] ) ;
println! ( "Usage: {} <str> <regex> <group> ... ", args [ 0 ] ) ;
println! ( "Pass `-' as `<str>' to read lines from stdin" ) ;
println! ( "Pass `-' as `<str>' to read lines from stdin" ) ;
std ::process ::exit ( 1 ) ;
std ::process ::exit ( 1 )
} else {
} else {
let re = re ::Regex ::compile ( & args [ 2 ] ) ? ;
let re = re ::Regex ::compile ( & args [ 2 ] ) ? ;
let text = & args [ 1 ] ;
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 ::< Result < Box < [ usize ] > , _ > > ( )
. 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 ;
use std ::io ::Write ;
let mut stdout = std ::io ::stdout ( ) ;
let mut stdout = std ::io ::stdout ( ) ;
if text = = "-" {
if & text [ .. ] = = "-" {
text ::stdin_lines ( | text | -> eyre ::Result < bool > {
text ::stdin_lines ( | text | -> eyre ::Result < bool > {
let mut stdout = stdout . lock ( ) ;
let mut stdout = stdout . lock ( ) ;
match re . exec ( & text ) ? {
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 )
Ok ( true )
@ -65,7 +112,7 @@ fn main() -> eyre::Result<()>
} else {
} else {
match re . exec ( & text ) ? {
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_group s ( & mut stdout , & g [.. ] , & group s ) ? , //println!("{}", &g.nth(group).unwrap().map(|x| x.as_ref()).unwrap_or("")),
_ = > ( ) ,
_ = > ( ) ,
}
}
}
}