summaryrefslogtreecommitdiffstats
path: root/src/style.rs
diff options
context:
space:
mode:
authorDan Davison <dandavison7@gmail.com>2021-11-22 20:15:06 -0500
committerDan Davison <dandavison7@gmail.com>2021-11-23 19:30:36 -0500
commit5dc0d6ef7e37a565b06d794b50fcc763079f9ed7 (patch)
treefc660d958f4d6f341dfa7a8942cb75b489861f28 /src/style.rs
parent87f458ae6be9377c040afadecae0f7f81d5e72b3 (diff)
New option to map raw styles encountered in input
Unify handling of styles parsed from raw line and computed diff styles. This enables syntax highlighting to be used in color-moved sections. Fixes #72
Diffstat (limited to 'src/style.rs')
-rw-r--r--src/style.rs104
1 files changed, 104 insertions, 0 deletions
diff --git a/src/style.rs b/src/style.rs
index b745cf33..047b9cc9 100644
--- a/src/style.rs
+++ b/src/style.rs
@@ -1,5 +1,6 @@
use std::borrow::Cow;
use std::fmt;
+use std::hash::{Hash, Hasher};
use lazy_static::lazy_static;
@@ -210,6 +211,89 @@ pub fn ansi_term_style_equality(a: ansi_term::Style, b: ansi_term::Style) -> boo
}
}
+// TODO: The equality methods were implemented first, and the equality_key
+// methods later. The former should be re-implemented in terms of the latter.
+// But why did the former not address equality of ansi_term::Color::RGB values?
+pub struct AnsiTermStyleEqualityKey {
+ attrs_key: (bool, bool, bool, bool, bool, bool, bool, bool),
+ foreground_key: Option<(u8, u8, u8, u8)>,
+ background_key: Option<(u8, u8, u8, u8)>,
+}
+
+impl PartialEq for AnsiTermStyleEqualityKey {
+ fn eq(&self, other: &Self) -> bool {
+ let option_eq = |opt_a, opt_b| match (opt_a, opt_b) {
+ (Some(a), Some(b)) => a == b,
+ (None, None) => true,
+ _ => false,
+ };
+
+ if self.attrs_key != other.attrs_key {
+ false
+ } else {
+ option_eq(self.foreground_key, other.foreground_key)
+ && option_eq(self.background_key, other.background_key)
+ }
+ }
+}
+
+impl Eq for AnsiTermStyleEqualityKey {}
+
+impl Hash for AnsiTermStyleEqualityKey {
+ fn hash<H: Hasher>(&self, state: &mut H) {
+ self.attrs_key.hash(state);
+ self.foreground_key.hash(state);
+ self.background_key.hash(state);
+ }
+}
+
+pub fn ansi_term_style_equality_key(style: ansi_term::Style) -> AnsiTermStyleEqualityKey {
+ let attrs_key = (
+ style.is_bold,
+ style.is_dimmed,
+ style.is_italic,
+ style.is_underline,
+ style.is_blink,
+ style.is_reverse,
+ style.is_hidden,
+ style.is_strikethrough,
+ );
+ AnsiTermStyleEqualityKey {
+ attrs_key,
+ foreground_key: style.foreground.map(ansi_term_color_equality_key),
+ background_key: style.background.map(ansi_term_color_equality_key),
+ }
+}
+
+impl fmt::Debug for AnsiTermStyleEqualityKey {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ let is_set = |c: char, set: bool| -> String {
+ if set {
+ c.to_uppercase().to_string()
+ } else {
+ c.to_lowercase().to_string()
+ }
+ };
+
+ let (bold, dimmed, italic, underline, blink, reverse, hidden, strikethrough) =
+ self.attrs_key;
+ write!(
+ f,
+ "ansi_term::Style {{ {:?} {:?} {}{}{}{}{}{}{}{} }}",
+ self.foreground_key,
+ self.background_key,
+ is_set('b', bold),
+ is_set('d', dimmed),
+ is_set('i', italic),
+ is_set('u', underline),
+ is_set('l', blink),
+ is_set('r', reverse),
+ is_set('h', hidden),
+ is_set('s', strikethrough),
+ )
+ }
+}
+
fn ansi_term_color_equality(a: Option<ansi_term::Color>, b: Option<ansi_term::Color>) -> bool {
match (a, b) {
(None, None) => true,
@@ -239,6 +323,26 @@ fn ansi_term_16_color_equality(a: ansi_term::Color, b: ansi_term::Color) -> bool
)
}
+fn ansi_term_color_equality_key(color: ansi_term::Color) -> (u8, u8, u8, u8) {
+ // Same (r, g, b, a) encoding as in utils::bat::terminal::to_ansi_color.
+ // When a = 0xFF, then a 256-color number is stored in the red channel, and
+ // the green and blue channels are meaningless. But a=0 signifies an RGB
+ // color.
+ let default = 0xFF;
+ match color {
+ ansi_term::Color::Fixed(0) | ansi_term::Color::Black => (0, default, default, default),
+ ansi_term::Color::Fixed(1) | ansi_term::Color::Red => (1, default, default, default),
+ ansi_term::Color::Fixed(2) | ansi_term::Color::Green => (2, default, default, default),
+ ansi_term::Color::Fixed(3) | ansi_term::Color::Yellow => (3, default, default, default),
+ ansi_term::Color::Fixed(4) | ansi_term::Color::Blue => (4, default, default, default),
+ ansi_term::Color::Fixed(5) | ansi_term::Color::Purple => (5, default, default, default),
+ ansi_term::Color::Fixed(6) | ansi_term::Color::Cyan => (6, default, default, default),
+ ansi_term::Color::Fixed(7) | ansi_term::Color::White => (7, default, default, default),
+ ansi_term::Color::Fixed(n) => (n, default, default, default),
+ ansi_term::Color::RGB(r, g, b) => (r, g, b, 0),
+ }
+}
+
lazy_static! {
pub static ref GIT_DEFAULT_MINUS_STYLE: Style = Style {
ansi_term_style: ansi_term::Color::Red.normal(),