aboutsummaryrefslogtreecommitdiff
path: root/src/backend/search.rs
blob: 65d97d7d16829fe74ef78bcf8f2588a4d3a50fb5 (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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
use nucleo_matcher::{
    pattern::{CaseMatching, Normalization, Pattern},
    Config, Matcher,
};
use std::collections::HashMap;

use crate::frontend::entries::EntryTableItem;

#[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_tag_list: Vec<String>,
}

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

impl BibiSearch {
    // Stringify EntryTableItem by joining/concat
    fn convert_to_string(inner_vec: &EntryTableItem) -> String {
        let entry_table_item_str = {
            format!(
                "{} {} {} {} {} {}",
                &inner_vec.authors,
                &inner_vec.title,
                &inner_vec.year,
                &inner_vec.pubtype,
                &inner_vec.keywords,
                &inner_vec.citekey
            )
        };
        entry_table_item_str
    }

    // Return a filtered entry list
    pub fn search_entry_list(
        search_pattern: &str,
        orig_list: Vec<EntryTableItem>,
    ) -> Vec<EntryTableItem> {
        // Create a hashmap to connect stingified entry with entry vec
        let mut entry_string_hm: HashMap<String, EntryTableItem> = 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<EntryTableItem> = Vec::new();
        for m in filtered_matches {
            filtered_list.push(entry_string_hm[&m].to_owned());
        }
        filtered_list.sort();
        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<EntryTableItem>,
    ) -> Vec<EntryTableItem> {
        let mut filtered_list: Vec<EntryTableItem> = Vec::new();

        // Loop over the whole given entry table
        // Check if the selected keyword is present in the current entry
        // If present, push the entry to the filtered list
        for e in orig_list {
            if e.keywords.contains(keyword) {
                filtered_list.push(e.to_owned());
            }
        }

        filtered_list
    }
}

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

    #[test]
    fn test_vector_join() {
        let bibvec: EntryTableItem = EntryTableItem {
            authors: "Author".to_string(),
            short_author: "".to_string(),
            title: "Title".to_string(),
            year: "1999".to_string(),
            pubtype: "article".to_string(),
            keywords: "hello, bye".to_string(),
            citekey: "author_1999".to_string(),
            abstract_text: "An abstract with multiple sentences. Here is the second".to_string(),
            doi_url: "https://www.bibiman.org".to_string(),
            filepath: "/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"
        )
    }
}