use crate::style::Style;
use std::collections::HashMap;
#[derive(Clone, Debug)]
pub struct SyntaxStyle {
pub id: u32,
pub name: String,
pub style: Style,
}
impl SyntaxStyle {
#[must_use]
pub fn new(id: u32, name: impl Into<String>, style: Style) -> Self {
Self {
id,
name: name.into(),
style,
}
}
}
#[derive(Clone, Debug, Default)]
pub struct SyntaxStyleRegistry {
styles: HashMap<u32, SyntaxStyle>,
by_name: HashMap<String, u32>,
next_id: u32,
}
impl SyntaxStyleRegistry {
#[must_use]
pub fn new() -> Self {
Self::default()
}
pub fn register(&mut self, name: impl Into<String>, style: Style) -> u32 {
let id = self.next_id;
self.next_id += 1;
let name = name.into();
self.by_name.insert(name.clone(), id);
self.styles.insert(id, SyntaxStyle::new(id, name, style));
id
}
pub fn register_with_id(&mut self, id: u32, name: impl Into<String>, style: Style) {
let name = name.into();
self.by_name.insert(name.clone(), id);
self.styles.insert(id, SyntaxStyle::new(id, name, style));
self.next_id = self.next_id.max(id.saturating_add(1));
}
#[must_use]
pub fn get(&self, id: u32) -> Option<&SyntaxStyle> {
self.styles.get(&id)
}
#[must_use]
pub fn get_by_name(&self, name: &str) -> Option<&SyntaxStyle> {
self.by_name.get(name).and_then(|id| self.styles.get(id))
}
#[must_use]
pub fn id_for_name(&self, name: &str) -> Option<u32> {
self.by_name.get(name).copied()
}
#[must_use]
pub fn style(&self, id: u32) -> Option<Style> {
self.styles.get(&id).map(|s| s.style)
}
#[must_use]
pub fn contains(&self, id: u32) -> bool {
self.styles.contains_key(&id)
}
#[must_use]
pub fn len(&self) -> usize {
self.styles.len()
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.styles.is_empty()
}
pub fn iter(&self) -> impl Iterator<Item = &SyntaxStyle> {
self.styles.values()
}
pub fn clear(&mut self) {
self.styles.clear();
self.by_name.clear();
self.next_id = 0;
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::color::Rgba;
#[test]
fn test_registry_basic() {
let mut registry = SyntaxStyleRegistry::new();
let id = registry.register("keyword", Style::fg(Rgba::BLUE).with_bold());
assert_eq!(registry.len(), 1);
assert!(registry.contains(id));
assert_eq!(registry.get(id).unwrap().name, "keyword");
}
#[test]
fn test_registry_by_name() {
let mut registry = SyntaxStyleRegistry::new();
registry.register("string", Style::fg(Rgba::GREEN));
let style = registry.get_by_name("string").unwrap();
assert_eq!(style.name, "string");
assert_eq!(style.style.fg, Some(Rgba::GREEN));
}
#[test]
fn test_registry_with_id() {
let mut registry = SyntaxStyleRegistry::new();
registry.register_with_id(100, "comment", Style::dim());
assert!(registry.contains(100));
assert_eq!(registry.id_for_name("comment"), Some(100));
}
}