-
Notifications
You must be signed in to change notification settings - Fork 54
Expand file tree
/
Copy pathpattern.rs
More file actions
104 lines (92 loc) · 2.7 KB
/
pattern.rs
File metadata and controls
104 lines (92 loc) · 2.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
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 {
/// Creates a multi pattern with `columns` empty column patterns.
pub fn new(columns: usize) -> Self {
Self {
cols: vec![Default::default(); columns],
}
}
/// Reparses a column. By specifying `append` the caller promises that text passed
/// to the previous `reparse` invocation is a prefix of `new_text`. This enables
/// additional optimizations but can lead to missing matches if an incorrect value
/// is passed.
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> {
// TODO: wheight columns?
let mut score = 0;
for ((pattern, _), haystack) in self.cols.iter().zip(haystack) {
score += pattern.score(haystack.slice(..), matcher).unwrap_or(0);
}
if score > 0 {
Some(score)
} else {
None
}
}
pub fn is_empty(&self) -> bool {
self.cols.iter().all(|(pat, _)| pat.atoms.is_empty())
}
}