pub use nucleo_matcher::pattern::{Atom, AtomKind, CaseMatching, Normalization, Pattern};
use nucleo_matcher::{Matcher, Utf32String};
#[cfg(test)]
mod tests;
#[derive(Debug, PartialEq, Eq, Clone, Copy, PartialOrd, Ord, Default)]
pub(crate) enum Status {
#[default]
Unchanged,
Update,
Rescore,
}
#[derive(Debug)]
pub struct MultiPattern {
cols: Vec<(Pattern, Status)>,
}
impl Clone for MultiPattern {
fn clone(&self) -> Self {
Self {
cols: self.cols.clone(),
}
}
fn clone_from(&mut self, source: &Self) {
self.cols.clone_from(&source.cols)
}
}
impl MultiPattern {
pub fn new(columns: usize) -> Self {
Self {
cols: vec![Default::default(); columns],
}
}
pub fn reparse(
&mut self,
column: usize,
new_text: &str,
case_matching: CaseMatching,
normalization: Normalization,
append: bool,
) {
let old_status = self.cols[column].1;
if append
&& old_status != Status::Rescore
&& self.cols[column]
.0
.atoms
.last()
.map_or(true, |last| !last.negative)
{
self.cols[column].1 = Status::Update;
} else {
self.cols[column].1 = Status::Rescore;
}
self.cols[column]
.0
.reparse(new_text, case_matching, normalization);
}
pub fn column_pattern(&self, column: usize) -> &Pattern {
&self.cols[column].0
}
pub(crate) fn status(&self) -> Status {
self.cols
.iter()
.map(|&(_, status)| status)
.max()
.unwrap_or(Status::Unchanged)
}
pub(crate) fn reset_status(&mut self) {
for (_, status) in &mut self.cols {
*status = Status::Unchanged
}
}
pub fn score(&self, haystack: &[Utf32String], matcher: &mut Matcher) -> Option<u32> {
let mut score = 0;
for ((pattern, _), haystack) in self.cols.iter().zip(haystack) {
score += pattern.score(haystack.slice(..), matcher)?
}
Some(score)
}
pub fn is_empty(&self) -> bool {
self.cols.iter().all(|(pat, _)| pat.atoms.is_empty())
}
}