1use std::collections::HashSet;
2
3use regex::Regex;
4
5use crate::{Selector, SkimItem};
6
7#[derive(Debug, Default)]
8pub struct DefaultSkimSelector {
9 first_n: usize,
10 regex: Option<Regex>,
11 preset: Option<HashSet<String>>,
12}
13
14impl DefaultSkimSelector {
15 pub fn first_n(mut self, first_n: usize) -> Self {
16 trace!("select first_n: {first_n}");
17 self.first_n = first_n;
18 self
19 }
20
21 pub fn preset(mut self, preset: impl IntoIterator<Item = String>) -> Self {
22 if self.preset.is_none() {
23 self.preset = Some(HashSet::new())
24 }
25
26 if let Some(set) = self.preset.as_mut() {
27 set.extend(preset)
28 }
29 self
30 }
31
32 pub fn regex(mut self, regex: &str) -> Self {
33 trace!("select regex: {regex}");
34 if !regex.is_empty() {
35 self.regex = Regex::new(regex).ok();
36 }
37 self
38 }
39}
40
41impl Selector for DefaultSkimSelector {
42 fn should_select(&self, index: usize, item: &dyn SkimItem) -> bool {
43 if self.first_n > index {
44 return true;
45 }
46
47 if self.preset.is_some()
48 && self
49 .preset
50 .as_ref()
51 .map(|preset| preset.contains(item.text().as_ref()))
52 .unwrap_or(false)
53 {
54 return true;
55 }
56
57 if self.regex.is_some() && self.regex.as_ref().map(|re| re.is_match(&item.text())).unwrap_or(false) {
58 return true;
59 }
60
61 false
62 }
63}
64
65#[cfg(test)]
66mod tests {
67 use super::*;
68
69 #[test]
70 pub fn test_first_n() {
71 let selector = DefaultSkimSelector::default().first_n(10);
72 assert!(selector.should_select(0, &"item"));
73 assert!(selector.should_select(1, &"item"));
74 assert!(selector.should_select(2, &"item"));
75 assert!(selector.should_select(9, &"item"));
76 assert!(!selector.should_select(10, &"item"));
77 }
78
79 #[test]
80 pub fn test_preset() {
81 let selector = DefaultSkimSelector::default().preset(vec!["a".to_string(), "b".to_string(), "c".to_string()]);
82 assert!(selector.should_select(0, &"a"));
83 assert!(selector.should_select(0, &"b"));
84 assert!(selector.should_select(0, &"c"));
85 assert!(!selector.should_select(0, &"d"));
86 }
87
88 #[test]
89 pub fn test_regex() {
90 let selector = DefaultSkimSelector::default().regex("^[0-9]");
91 assert!(selector.should_select(0, &"1"));
92 assert!(selector.should_select(0, &"2"));
93 assert!(selector.should_select(0, &"3"));
94 assert!(selector.should_select(0, &"1a"));
95 assert!(!selector.should_select(0, &"a"));
96 }
97
98 #[test]
99 pub fn test_all_together() {
100 let selector = DefaultSkimSelector::default()
101 .first_n(1)
102 .regex("b")
103 .preset(vec!["c".to_string()]);
104 assert!(selector.should_select(0, &"a"));
105 assert!(selector.should_select(1, &"b"));
106 assert!(selector.should_select(2, &"c"));
107 assert!(!selector.should_select(3, &"d"));
108 }
109}