Skip to content

Commit 9c7d3d5

Browse files
committed
Implement "or" query
1 parent d50048b commit 9c7d3d5

File tree

2 files changed

+68
-28
lines changed

2 files changed

+68
-28
lines changed

src/view/table.rs

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -587,17 +587,20 @@ impl TableView {
587587

588588
fn filter_view_indices(&mut self) {
589589
let query = self.filter_input.value();
590-
self.view_indices = self
591-
.row_cell_items
592-
.iter()
593-
.enumerate()
594-
.filter(|(_, cell_items)| {
595-
cell_items
596-
.iter()
597-
.any(|cell_item| cell_item.matched_index(query).is_some())
598-
})
599-
.map(|(i, _)| i)
600-
.collect();
590+
self.view_indices = if query.is_empty() {
591+
(0..self.items.len()).collect()
592+
} else {
593+
self.row_cell_items
594+
.iter()
595+
.enumerate()
596+
.filter(|(_, cell_items)| {
597+
cell_items
598+
.iter()
599+
.any(|cell_item| !cell_item.matched_indices(query).is_empty())
600+
})
601+
.map(|(i, _)| i)
602+
.collect()
603+
};
601604
self.table_state = self
602605
.table_state
603606
.with_new_total_rows(self.view_indices.len());

src/widget/table.rs

Lines changed: 54 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -422,26 +422,63 @@ impl<'a> CellItem<'a> {
422422
if query.is_empty() {
423423
return Cell::from(Line::from(self.content.clone()));
424424
}
425-
match self.matched_index(query) {
426-
Some(i) => {
427-
let mut hm = highlight_matched_text(self.content.clone());
428-
if self.plain_width > col_width {
429-
hm = hm.ellipsis(ELLIPSIS);
430-
}
431-
let spans = hm
432-
.matched_range(i, i + query.len())
433-
.matched_fg(matched_fg)
434-
.matched_bg(matched_bg)
435-
.into_spans();
436-
Cell::from(Line::from(spans))
425+
let indices = self.matched_indices(query);
426+
if indices.is_empty() {
427+
Cell::from(Line::from(self.content.clone()))
428+
} else {
429+
let mut hm = highlight_matched_text(self.content.clone());
430+
if self.plain_width > col_width {
431+
hm = hm.ellipsis(ELLIPSIS);
437432
}
438-
None => Cell::from(Line::from(self.content.clone())),
433+
let spans = hm
434+
.matched_indices(indices)
435+
.matched_fg(matched_fg)
436+
.matched_bg(matched_bg)
437+
.into_spans();
438+
Cell::from(Line::from(spans))
439439
}
440440
}
441441

442-
pub fn matched_index(&self, query: &str) -> Option<usize> {
443-
let lower_query = query.to_lowercase();
444-
let lower_plain = self.plain.to_lowercase();
445-
lower_plain.find(&lower_query)
442+
pub fn matched_indices(&self, query: &str) -> Vec<usize> {
443+
matched_indices(query, &self.plain)
444+
}
445+
}
446+
447+
fn matched_indices(query: &str, plain: &str) -> Vec<usize> {
448+
let mut indices = Vec::new();
449+
let lower_plain = plain.to_lowercase();
450+
for q in query.split("|") {
451+
if q.is_empty() {
452+
continue;
453+
}
454+
let lower_query = q.to_lowercase();
455+
let l = lower_query.len();
456+
if let Some(i) = lower_plain.find(&lower_query) {
457+
for idx in i..i + l {
458+
indices.push(idx);
459+
}
460+
}
461+
}
462+
indices
463+
}
464+
465+
#[cfg(test)]
466+
mod tests {
467+
use rstest::*;
468+
469+
use super::*;
470+
471+
#[rstest]
472+
#[case("", vec![])]
473+
#[case("o", vec![4])]
474+
#[case("lo", vec![3, 4])]
475+
#[case("WOR", vec![6, 7, 8])]
476+
#[case("el|or", vec![1, 2, 7, 8])]
477+
#[case("ll|", vec![2, 3])]
478+
#[case("|rl", vec![8, 9])]
479+
fn test_matched_indices(#[case] query: &str, #[case] expected: Vec<usize>) {
480+
let plain = "Hello World";
481+
let actual = matched_indices(query, plain);
482+
assert_eq!(actual, expected);
446483
}
447484
}

0 commit comments

Comments
 (0)