use crate::regex;
use crate::utils::Loc;
use regex::Regex;
#[derive(Debug, PartialEq, Eq)]
pub struct Match {
pub loc: Loc,
pub text: String,
}
pub struct Searcher {
pub re: Regex,
}
impl Searcher {
#[must_use]
pub fn new(re: &str) -> Self {
Self { re: regex!(re) }
}
pub fn lfind(&mut self, st: &str) -> Option<Match> {
for cap in self.re.captures_iter(st) {
if let Some(c) = cap.get(cap.len().saturating_sub(1)) {
let x = Self::raw_to_char(c.start(), st);
return Some(Match { loc: Loc::at(x, 0), text: c.as_str().to_string() });
}
}
None
}
pub fn rfind(&mut self, st: &str) -> Option<Match> {
let mut caps: Vec<_> = self.re.captures_iter(st).collect();
caps.reverse();
for cap in caps {
if let Some(c) = cap.get(cap.len().saturating_sub(1)) {
let x = Self::raw_to_char(c.start(), st);
return Some(Match { loc: Loc::at(x, 0), text: c.as_str().to_string() });
}
}
None
}
#[must_use]
pub fn raw_to_char(x: usize, st: &str) -> usize {
let mut raw = 0;
for (c, ch) in st.chars().enumerate() {
if raw == x {
return c;
}
raw += ch.len_utf8();
}
st.chars().count()
}
}