skim/helper/
selector.rs

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}