Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'helix-view/src/theme.rs')
| -rw-r--r-- | helix-view/src/theme.rs | 73 |
1 files changed, 28 insertions, 45 deletions
diff --git a/helix-view/src/theme.rs b/helix-view/src/theme.rs index af8f03bc..61d490ff 100644 --- a/helix-view/src/theme.rs +++ b/helix-view/src/theme.rs @@ -294,43 +294,36 @@ fn build_theme_values( 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; + /// we interpret the last 256^3 numbers as RGB. + const RGB_START: u32 = (u32::MAX << (8 + 8 + 8)) - 1 - (u32::MAX - Highlight::MAX); /// 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(); + fn decode_rgb_highlight(highlight: Highlight) -> Option<(u8, u8, u8)> { + (highlight.get() > Self::RGB_START).then(|| { + let [b, g, r, ..] = (highlight.get() + 1).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, - ])) + // -1 because highlight is "non-max": u32::MAX is reserved for the null pointer + // optimization. + Highlight::new(u32::from_ne_bytes([b, g, r, u8::MAX]) - 1) } #[inline] - pub fn highlight(&self, index: usize) -> Style { - if let Some((red, green, blue)) = Self::decode_rgb_highlight(index) { + pub fn highlight(&self, highlight: Highlight) -> Style { + if let Some((red, green, blue)) = Self::decode_rgb_highlight(highlight) { Style::new().fg(Color::Rgb(red, green, blue)) } else { - self.highlights[index] + self.highlights[highlight.idx()] } } #[inline] - pub fn scope(&self, index: usize) -> &str { - &self.scopes[index] + pub fn scope(&self, highlight: Highlight) -> &str { + &self.scopes[highlight.idx()] } pub fn name(&self) -> &str { @@ -361,13 +354,16 @@ impl Theme { &self.scopes } - pub fn find_scope_index_exact(&self, scope: &str) -> Option<usize> { - self.scopes().iter().position(|s| s == scope) + pub fn find_highlight_exact(&self, scope: &str) -> Option<Highlight> { + self.scopes() + .iter() + .position(|s| s == scope) + .map(|idx| Highlight::new(idx as u32)) } - pub fn find_scope_index(&self, mut scope: &str) -> Option<usize> { + pub fn find_highlight(&self, mut scope: &str) -> Option<Highlight> { loop { - if let Some(highlight) = self.find_scope_index_exact(scope) { + if let Some(highlight) = self.find_highlight_exact(scope) { return Some(highlight); } if let Some(new_end) = scope.rfind('.') { @@ -626,23 +622,13 @@ mod tests { fn convert_to_and_from() { let (r, g, b) = (0xFF, 0xFE, 0xFA); let highlight = Theme::rgb_highlight(r, g, b); - assert_eq!(Theme::decode_rgb_highlight(highlight.0), Some((r, g, b))); + assert_eq!(Theme::decode_rgb_highlight(highlight), Some((r, g, b))); } /// make sure we can store all the colors at the end - /// ``` - /// FF FF FF FF FF FF FF FF - /// xor - /// FF FF FF FF FF 00 00 00 - /// = - /// 00 00 00 00 00 FF FF FF - /// ``` - /// - /// where the ending `(FF, FF, FF)` represents `(r, g, b)` #[test] fn full_numeric_range() { - assert_eq!(usize::MAX ^ Theme::RGB_START, 256_usize.pow(3)); - assert_eq!(Theme::RGB_START + 256_usize.pow(3), usize::MAX); + assert_eq!(Highlight::MAX - Theme::RGB_START, 256_u32.pow(3)); } #[test] @@ -650,30 +636,27 @@ mod tests { // color in the middle let (r, g, b) = (0x14, 0xAA, 0xF7); assert_eq!( - Theme::default().highlight(Theme::rgb_highlight(r, g, b).0), + Theme::default().highlight(Theme::rgb_highlight(r, g, b)), Style::new().fg(Color::Rgb(r, g, b)) ); // pure black let (r, g, b) = (0x00, 0x00, 0x00); assert_eq!( - Theme::default().highlight(Theme::rgb_highlight(r, g, b).0), + Theme::default().highlight(Theme::rgb_highlight(r, g, b)), Style::new().fg(Color::Rgb(r, g, b)) ); // pure white let (r, g, b) = (0xff, 0xff, 0xff); assert_eq!( - Theme::default().highlight(Theme::rgb_highlight(r, g, b).0), + Theme::default().highlight(Theme::rgb_highlight(r, g, b)), Style::new().fg(Color::Rgb(r, g, b)) ); } #[test] - #[should_panic( - expected = "index out of bounds: the len is 0 but the index is 18446744073692774399" - )] + #[should_panic(expected = "index out of bounds: the len is 0 but the index is 4278190078")] fn out_of_bounds() { - let (r, g, b) = (0x00, 0x00, 0x00); - - Theme::default().highlight(Theme::rgb_highlight(r, g, b).0 - 1); + let highlight = Highlight::new(Theme::rgb_highlight(0, 0, 0).get() - 1); + Theme::default().highlight(highlight); } } |