mod error;
use error::Error;
use mantid_core::{constants, Boxed};
use regex::{Regex, RegexBuilder};
use std::io::BufRead;
const RED_OUTPUT: &str = "\x1b[33m";
const NO_COLOUR_OUTPUT: &str = "\x1b[0m";
pub enum MatchesInput<'a> {
Expression(&'a str),
RE(&'a Regex),
}
pub fn matches<'a>(
test: &'a str,
input: MatchesInput,
case_insensitive: bool,
) -> Result<Vec<regex::Match<'a>>, Error> {
let get_match = |re: &Regex| {
let result = re.find_iter(test).collect::<Vec<regex::Match>>();
Ok(result)
};
match input {
MatchesInput::Expression(expression) => get_match(
&RegexBuilder::new(expression)
.case_insensitive(case_insensitive)
.build()?,
),
MatchesInput::RE(input_re) => get_match(input_re),
}
}
pub fn grep_cli(
expression: &str,
case_insensitive: bool,
only_matching: bool,
hash: bool,
) -> Boxed {
let tested_expression = if hash {
format!(
"{}|{}|{}",
constants::HASH_EXP
.get("SHA-256")
.ok_or(Error::HashRetrieve)?,
constants::HASH_EXP
.get("SHA-1")
.ok_or(Error::HashRetrieve)?,
constants::HASH_EXP.get("MD5").ok_or(Error::HashRetrieve)?
)
} else {
expression.to_string()
};
let re = RegexBuilder::new(&tested_expression)
.case_insensitive(case_insensitive)
.build()?;
for test in std::io::stdin().lock().lines() {
let test = test?;
let matches = matches(&test, MatchesInput::RE(&re), case_insensitive)?;
if only_matching {
for m in matches {
println!("{}", m.as_str());
}
} else {
match matches.first() {
Some(m) => {
let ss = test
.get(m.start()..m.end()) .ok_or(Error::InvalidSlice)?;
println!(
"{}",
test.replace(ss, &format!("{}{}{}", RED_OUTPUT, ss, NO_COLOUR_OUTPUT))
)
}
None => {}
}
}
}
Ok(())
}