aboutsummaryrefslogtreecommitdiff
path: root/src/backend/search.rs
blob: 675779094c3ebe2cd4908dfffbaadfe8616ceea6 (plain)
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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
use nucleo_matcher::{
    pattern::{CaseMatching, Normalization, Pattern},
    Config, Matcher,
};
use std::collections::HashMap;

#[derive(Debug)]
pub struct BibiSearch {
    pub search_string: String, // Search string show in footer, used for search
    pub inner_search: bool,    // True, if we trigger a search for already filtered list
    pub filtered_entry_list_by_search: Vec<Vec<String>>, // Temporary holds entry list filtered by search pattern to refilter it
    pub filtered_entry_list_by_tags: Vec<Vec<String>>, // Holds entry list filtered by tag to filter it further by search
    pub filtered_tag_list: Vec<String>,
}

impl Default for BibiSearch {
    fn default() -> Self {
        Self {
            search_string: String::new(),
            inner_search: false,
            filtered_entry_list_by_search: Vec::new(),
            filtered_entry_list_by_tags: Vec::new(),
            filtered_tag_list: Vec::new(),
        }
    }
}

impl BibiSearch {
    // Stringify inner Vec<String> by joining/concat
    fn convert_to_string(inner_vec: &Vec<String>) -> String {
        inner_vec[0..6].join(" ")
    }

    // Return a filtered entry list
    pub fn search_entry_list(
        search_pattern: &str,
        orig_list: Vec<Vec<String>>,
    ) -> Vec<Vec<String>> {
        // Create a hashmap to connect stingified entry with entry vec
        let mut entry_string_hm: HashMap<String, Vec<String>> = HashMap::new();

        // Convert all entries to string and insert them into the hashmap
        // next to the original inner Vec<String> of the entry list
        for entry in orig_list {
            entry_string_hm.insert(Self::convert_to_string(&entry), entry);
        }

        // Set up matcher (TODO: One time needed only, move to higher level)
        let mut matcher = Matcher::new(Config::DEFAULT);

        // Filter the stringified entries and collect them into a vec
        let filtered_matches: Vec<String> = {
            let matches =
                Pattern::parse(search_pattern, CaseMatching::Ignore, Normalization::Smart)
                    .match_list(entry_string_hm.keys(), &mut matcher);
            matches.into_iter().map(|f| f.0.to_string()).collect()
        };

        // Create filtered entry list and push the inner entry vec's to it
        // Use the filtered stringified hm-key as index
        let mut filtered_list: Vec<Vec<String>> = Vec::new();
        for m in filtered_matches {
            filtered_list.push(entry_string_hm[&m].to_owned());
        }
        filtered_list
    }

    pub fn search_tag_list(search_pattern: &str, orig_list: Vec<String>) -> Vec<String> {
        // Set up matcher (TODO: One time needed only)
        let mut matcher = Matcher::new(Config::DEFAULT);

        // Filter the list items by search pattern
        let filtered_matches: Vec<String> = {
            let matches =
                Pattern::parse(search_pattern, CaseMatching::Ignore, Normalization::Smart)
                    .match_list(orig_list, &mut matcher);
            matches.into_iter().map(|f| f.0.to_string()).collect()
        };
        filtered_matches
    }

    pub fn filter_entries_by_tag(keyword: &str, orig_list: &Vec<Vec<String>>) -> Vec<Vec<String>> {
        let mut filtered_list: Vec<Vec<String>> = Vec::new();

        for e in orig_list {
            if e[4].contains(keyword) {
                filtered_list.push(e.to_owned());
            }
        }

        filtered_list
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_vector_join() {
        let bibvec = vec![
            "Author".to_string(),
            "Title".to_string(),
            "1999".to_string(),
            "article".to_string(),
            "hello, bye".to_string(),
            "author_1999".to_string(),
            "An abstract with multiple sentences. Sometimes thats necessary".to_string(),
            "www.bibiman.org".to_string(),
            "/home/file/path.pdf".to_string(),
        ];

        let joined_vec = BibiSearch::convert_to_string(&bibvec);

        assert_eq!(
            joined_vec,
            "Author Title 1999 article hello, bye author_1999"
        )
    }
}