thesaurus/
lib.rs

1#![doc = include_str!("../README.md")]
2#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
3
4use std::collections::HashMap;
5
6#[cfg(feature = "static")]
7use lazy_static::{lazy_static, initialize};
8
9#[cfg(feature = "static")]
10lazy_static! {
11    static ref DICT: HashMap<String, Vec<String>> = parse_dict();
12}
13
14/// Initialize a global dictionary so initialization isn't done on the first call to [`synonyms`] or [`dict`].
15#[cfg(feature = "static")]
16pub fn init() {
17    initialize(&DICT);
18}
19
20/// Return the internal dictionary.
21pub fn dict() -> HashMap<String, Vec<String>> {
22    let mut dict: HashMap<String, Vec<String>> = HashMap::new();
23
24    #[cfg(feature = "static")]
25    dict.extend(DICT.to_owned());
26
27    // if we're not static...
28    if dict.is_empty() {
29        dict.extend(parse_dict());
30    }
31
32    dict
33}
34
35/// Return synonyms for a word.
36pub fn synonyms(word: impl AsRef<str>) -> Vec<String> {
37    let mut s = dict()
38        .get(word.as_ref())
39        .map(|x| x.clone())
40        .unwrap_or_default();
41
42    s.dedup();
43    s.sort_by(|a, b| a.cmp(&b));
44
45    s
46}
47
48fn parse_dict() -> HashMap<String, Vec<String>> {
49    let mut dict: HashMap<String, Vec<String>> = HashMap::new();
50
51    #[cfg(feature = "wordnet")]
52    for line in thesaurus_wordnet::uncompress().lines() {
53        parse_dict_line(line, &mut dict);
54    }
55
56    #[cfg(feature = "moby")]
57    for line in thesaurus_moby::uncompress().lines() {
58        parse_dict_line(line, &mut dict);
59    }
60
61    dict
62}
63
64fn parse_dict_line(line: &str, dict: &mut HashMap<String, Vec<String>>) {
65    let mut line: Vec<String> = line.split('|').map(|x| x.to_string().to_lowercase()).collect();
66
67    let name = line.remove(0);
68
69    if let Some(x) = dict.get_mut(&name) {
70        x.extend_from_slice(&line);
71        x.dedup();
72    } else {
73        dict.insert(name, line);
74    }
75}