1.3 KiB · text History e745ef6
//! The Material Symbols name -> codepoint table.
//!
//! Parsed at startup from the `.codepoints` file shipped alongside the font,
//! rather than hard-coded, so swapping in a newer font updates both together.

pub struct IconEntry {
    pub name: &'static str,
    pub ch: char,
}

const CODEPOINTS: &str = include_str!("../assets/MaterialSymbolsRounded-Regular.codepoints");

pub fn all() -> Vec<IconEntry> {
    CODEPOINTS
        .lines()
        .filter_map(|line| {
            let (name, hex) = line.split_once(' ')?;
            let ch = char::from_u32(u32::from_str_radix(hex.trim(), 16).ok()?)?;
            Some(IconEntry { name, ch })
        })
        .collect()
}

/// Case-insensitive substring match, exact-prefix hits first so typing
/// "lock" offers `lock` before `lock_clock`.
pub fn search<'a>(all: &'a [IconEntry], query: &str, limit: usize) -> Vec<&'a IconEntry> {
    let q = query.trim().to_ascii_lowercase();
    if q.is_empty() {
        return all.iter().take(limit).collect();
    }
    let mut hits: Vec<&IconEntry> = all.iter().filter(|e| e.name.contains(&q)).collect();
    hits.sort_by_key(|e| {
        (
            e.name != q,
            !e.name.starts_with(&q),
            e.name.len(),
        )
    });
    hits.truncate(limit);
    hits
}