Repository: helix-editor/helix
File: helix-view/src/theme.rs (Rust)

Code before:
    scopes.reserve(values.len());
    highlights.reserve(values.len());
    for (name, style_value) in values {
        let mut style = Style::default();
        if let Err(err) = palette.parse_style(&mut style, style_value) {
            warnings.push(format!("Failed to parse style for key {name:?}. {err}"));
        }

        // these are used both as UI and as highlights
        styles.insert(name.clone(), style);
        scopes.push(name);
        highlights.push(style);
    }

    (styles, scopes, highlights, warnings)
}

impl Theme {
    #[inline]
    pub fn highlight(&self, index: usize) -> Style {
        self.highlights[index]
    }

    #[inline]
    pub fn scope(&self, index: usize) -> &str {
        &self.scopes[index]
    }

    pub fn name(&self) -> &str {
        &self.name
    }

    pub fn get(&self, scope: &str) -> Style {
        self.try_get(scope).unwrap_or_default()
    }

    /// Get the style of a scope, falling back to dot separated broader
    /// scopes. For example if `ui.text.focus` is not defined in the theme,
    /// `ui.text` is tried and then `ui` is tried.
    pub fn try_get(&self, scope: &str) -> Option<Style> {
        std::iter::successors(Some(scope), |s| Some(s.rsplit_once('.')?.0))
            .find_map(|s| self.styles.get(s).copied())
    }

    /// Get the style of a scope, without falling back to dot separated broader
    /// scopes. For example if `ui.text.focus` is not defined in the theme, it
    /// will return `None`, even if `ui.text` is.
    pub fn try_get_exact(&self, scope: &str) -> Option<Style> {
        self.styles.get(scope).copied()
    }


Review comment (suggestion):
Wouldn't this make tests less reproducible? :confused: This assumes blue (for example) is always the 1st byte (regardless of positional weight), but the comparison above is mathematical (checks the most significant byte, regardless of position)

Code after:
    scopes.reserve(values.len());
    highlights.reserve(values.len());
    for (name, style_value) in values {
        let mut style = Style::default();
        if let Err(err) = palette.parse_style(&mut style, style_value) {
            warnings.push(format!("Failed to parse style for key {name:?}. {err}"));
        }

        // these are used both as UI and as highlights
        styles.insert(name.clone(), style);
        scopes.push(name);
        highlights.push(style);
    }

    (styles, scopes, highlights, warnings)
}

impl Theme {
    /// To allow `Highlight` to represent arbitrary RGB colors without turning it into an enum,
    /// we interpret the last 3 bytes of a `Highlight` as RGB colors.
    const RGB_START: usize = (usize::MAX << (8 + 8 + 8)) - 1;

    /// Interpret a Highlight with the RGB foreground
    fn decode_rgb_highlight(rgb: usize) -> Option<(u8, u8, u8)> {
        (rgb > Self::RGB_START).then(|| {
            let [b, g, r, ..] = rgb.to_ne_bytes();
            (r, g, b)
        })
    }

    /// Create a Highlight that represents an RGB color
    pub fn rgb_highlight(r: u8, g: u8, b: u8) -> Highlight {
        Highlight(usize::from_ne_bytes([
            b,
            g,
            r,
            u8::MAX,
            u8::MAX,
            u8::MAX,
            u8::MAX,
            u8::MAX,
        ]))
    }

    #[inline]
    pub fn highlight(&self, index: usize) -> Style {
        if let Some((red, green, blue)) = Self::decode_rgb_highlight(index) {
            Style::new().fg(Color::Rgb(red, green, blue))
        } else {
            self.highlights[index]
        }