egui_code_editor 0.3.3

egui Code Editor widget with numbered lines, syntax highlighting and auto-completion..
Documentation
#![allow(dead_code)]
use std::{iter::Peekable, str::Chars};

const ROOT_CHAR: char = ' ';

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Trie {
    root: char,
    is_word: bool,
    leaves: Vec<Trie>,
}

impl PartialOrd for Trie {
    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
        Some(self.cmp(other))
    }
}
impl Ord for Trie {
    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
        self.root.cmp(&other.root)
    }
}

impl Default for Trie {
    fn default() -> Self {
        Self {
            root: ROOT_CHAR,
            is_word: false,
            leaves: vec![],
        }
    }
}

impl Trie {
    pub fn new(root: char) -> Self {
        Trie {
            root,
            ..Default::default()
        }
    }
    pub fn clear(&mut self) {
        self.leaves.clear();
    }
    pub fn push(&mut self, word: &str) {
        self.push_chars(&mut word.chars());
    }

    pub fn push_chars(&mut self, word: &mut Chars) {
        if let Some(first) = word.next() {
            if let Some(leaf) = self.leaves.iter_mut().find(|l| l.root == first) {
                leaf.push_chars(word)
            } else {
                let mut new = Trie::new(first);
                new.push_chars(word);
                self.leaves.push(new);
            }
        } else {
            self.is_word = true;
            self.leaves.sort();
            self.leaves.reverse();
        }
    }

    pub fn from_words(words: &[&str]) -> Self {
        let mut trie = Trie::new(ROOT_CHAR);
        words.iter().for_each(|w| {
            trie.push_chars(&mut w.chars());
        });
        trie
    }

    pub fn words(&self) -> Vec<String> {
        let mut words = vec![];
        for child in self.leaves.iter() {
            child.words_recursive("", &mut words);
        }
        words.reverse();
        words
    }
    fn words_recursive(&self, prefix: &str, words: &mut Vec<String>) {
        let mut prefix = prefix.to_string();
        prefix.push(self.root);
        if self.is_word {
            words.push(prefix.clone());
        }
        for child in self.leaves.iter() {
            child.words_recursive(&prefix, words);
        }
    }

    pub fn find_completions(&self, prefix: &str) -> Vec<String> {
        self.find_by_prefix(prefix)
            .map(|t| t.words())
            .unwrap_or_default()
    }
    pub fn find_by_prefix(&self, prefix: &str) -> Option<&Trie> {
        let mut found = None;
        let mut start = " ".to_string();
        start.push_str(prefix);
        let mut part = start.chars().peekable();
        self.find_recursive(&mut part, &mut found);
        found
    }
    fn find_recursive<'a>(&'a self, part: &mut Peekable<Chars>, found: &mut Option<&'a Trie>) {
        if let Some(c) = part.next()
            && self.root == c
        {
            if part.peek().is_none() {
                *found = Some(self);
            }
            self.leaves
                .iter()
                .for_each(|l| l.find_recursive(&mut part.clone(), found))
        }
    }
}