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