amen 0.0.3

A CLI menu tool utilizing abbreviations
Documentation
use std::collections::HashMap;
use trie_rs::TrieBuilder;

pub struct AbbrevPhrase<'a> {
    pub phrase: &'a str,
    pub abbrev: String,
    pub indices: Vec<usize>,
}

pub fn assign_abbrevs<'a>(all_options: &[&'a str]) -> HashMap<String, AbbrevPhrase<'a>> {
    let all_options_trie = copy_to_trie(all_options);
    let mut items_by_abbrev = HashMap::new();
    let count = all_options.len();

    for original in all_options {
        let (abbrev, indices) = assign_abbrev_indices(original, &all_options_trie, count);
        items_by_abbrev.insert(
            abbrev.clone(),
            AbbrevPhrase {
                phrase: original,
                abbrev,
                indices,
            },
        );
    }
    items_by_abbrev
}

fn copy_to_trie(items: &[&str]) -> trie_rs::Trie<u8> {
    let mut trie_builder = TrieBuilder::new();
    for item in items.iter() {
        trie_builder.push(item);
    }
    trie_builder.build()
}

fn assign_abbrev_indices(
    text: &str,
    all_texts: &trie_rs::Trie<u8>,
    count: usize,
) -> (String, Vec<usize>) {
    let mut abbrev = String::new();
    let mut indices = vec![];
    let mut prev_matches = count;
    for i in 0..text.len() {
        let query = &text[..=i];
        let search = all_texts.predictive_search(query);
        let matches: Vec<_> = search
            .iter()
            .map(|u8s| std::str::from_utf8(u8s).unwrap())
            .collect();

        if matches.len() < prev_matches {
            use std::fmt::Write;
            indices.push(i);
            write!(abbrev, "{}", &text[i..(i + 1)]).unwrap();
        } else if matches.is_empty() {
            break;
        }

        prev_matches = matches.len();
    }
    (abbrev, indices)
}