From 4b6723192ef285ddbf7f18db7a65254b91a0028f Mon Sep 17 00:00:00 2001 From: Amaan Qureshi Date: Sat, 25 Jan 2025 16:14:53 -0500 Subject: [PATCH] refactor(cli): replace embedded xterm colors file with `ansi_colours` --- Cargo.lock | Bin 71481 -> 72190 bytes Cargo.toml | 1 + cli/Cargo.toml | 1 + cli/src/highlight.rs | 42 ++---- cli/vendor/xterm-colors.json | 258 ----------------------------------- 5 files changed, 10 insertions(+), 292 deletions(-) delete mode 100644 cli/vendor/xterm-colors.json diff --git a/Cargo.lock b/Cargo.lock index 7c72f4b92fde1e8690ea1c1e23bd0b6eed5113dd..8cfa6107aa15d11fe652c0c1f07263fb19d04932 100644 GIT binary patch delta 1663 zcmZ9NO^B6c6vw$UVn#=gJimp>74U?gEljZ+(dMzWkK?MoJUMcbQ=4>Y6KH( z5$ThS&?Yw#Eu?sB5m*t{CTKBQDbZ$Hlmrn*%ZSb$gQ(TZec_&u-~WI9@5dKM{^~~F z-#L8OfqnV#p~Le>=eDgm#z*H49DaIY&%`#Iq_(_nb_z9f){23G#{e!s)o5L)Yy(#p zJ%vJ%N-54~p8=E#?6pH+txRnf4vr5W-JjZtEq8a@hlfVmnVJ4nj>;&_&Y{N`at3Eq zh{a$f)L2v`tbzvK|y|FJD^Q_MTtY&i$~f8(ID3aL;#NjlI1kzed59Sae2J?_#>kOLerRQtV(4YOwE?TgVkJ9M%jdOP)<{@s4E%fDofU&sQ?qX ztRnf^mV2AJSF;|KqMtqa(`fr~U4J@x4U}VYk!xh6AmyD)32MdUYY7oFCzA|v%?6@_ z#L-|b5wZ)U+sxVV?xDGNhNS54^M45I?&oLsjv{>>6*ww5T=}D{8XrV z3q|=LoL#l9WOO;!?32$a`%oaO6&UTi<4aQW-4}NZwb@nu=>mqyF%v3_SS!0?mG((? zWk1+BDTk=VbYdZuIg=4AChCaJ8{!qf#}=*$(vSL6RyN37z_LIrVzL^wFUF-%WoBcF z4``|Z=|z}CTQ-WG1GUp%#;x3#b_;f?##e>?({ ze$uoHzCUf83a+5F+B%R@DhU8N7i$oU3kqcs+0)e`pirD)ZR99yG!}&r+tU2_==0C; zz=rM2*)83%H+n-o-9Ep!zq^Q586#7Q(FF7WrJ~ItN9QeuB>v3Oa!@M;n+1?5h(u6) zUhJ>$-Pt}J8x!C=7a!X`_HPXA>W*JJJKA15AvP58y%(z_k<4mA4j>1M$%^Md*BrB0 zT(PL0i@c@CiJX|wm>?%{OV!^lukJqi;=QpU1VJ)8#YIGy*l;?8nzcwNJ|mJplSX4~ z7W3&i@E(zpz+s14+e$GeF{Tk~Pqy=UZQFPCw&s_n24$Duo_(M~1fd#Drj#W|yi0`< zndLmQ_)TYna+XD`STse8fK@WhqUe%xyRdt_ZM|}8P;F*@c1rS1$>kLYTx1AJ1$=Nx z$;}y6SeRI2y|hx*1y5DW4@h$J1(F6gxWD%6EwbwxX>ER#25dzp&k+Ke=ulWO zt}n6LTPvP5UB)l~&l3lC(0 zZ2(BZA+jT6ucJ^A%LM2-K#ti3jE=o3G8_JR@%^!ao;>{bNFQ&#vS+1VxqJUEiVQ;F z*p&*+T5{lu;&HN=Le!&OB|%*hSUAQQpc!_)Fsowy-s@ZYxmVZq<43+y)B~?=A1_{* zsfkV1grt;?#~`w9d^9_?X*Ao z>3mJMXHIB?8rMQ5pN;C-at?@`T|--|a`mX*stjPWo)kPm_DMo<{mST$;pFk>rW1O| zbhzuzVf%@HCubI;alfX%sRc_V1aq^_8yllHk(FejNGTa~N-{bJQ6ZBkO&wnCiwY&k z2`q_4>y5Fs=>Qr)u2}Rh-{d?0eSN<%x~-r8e%}%`jrZ;jEwauQ(PLJopq?lXm9OOp zDz!EeT4kqWduL5^nnkaxL36={`o06R{>i0dOSsPu&3Bf95SJUYx@<)nHfhkDh62Q? ze&Pdh=15w}Mq1z`64X)cweR0ew)A(*Ey{0mpZxgb5){_WcbZCxH32%2D?YGsqEqQH zT3d~lCSHOFW6WAY37S>!Ycs7>=S;tNmipC8oB9KnpIHJPeOIM)DQSXgQlG76OpMjo zxF88k)=P*rxGtn7oLeg?TD^e`$5f3NOpATv(bj(O^2%`Fr>~dYy6@+EmXF7OG0Vce z{OiM;mN&zi@wJlGa9OIshM??8`(gCE%eIN30$vplEv10V8fG;PR3|8!=5jN@PyBUu F$N!*Kll=ey diff --git a/Cargo.toml b/Cargo.toml index c579773e3..a5a850e09 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -93,6 +93,7 @@ incremental = true codegen-units = 256 [workspace.dependencies] +ansi_colours = "1.2.3" anstyle = "1.0.10" anyhow = "1.0.94" bstr = "1.11.3" diff --git a/cli/Cargo.toml b/cli/Cargo.toml index d1c6172bd..1353f815b 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -28,6 +28,7 @@ harness = false wasm = ["tree-sitter/wasm", "tree-sitter-loader/wasm"] [dependencies] +ansi_colours.workspace = true anstyle.workspace = true anyhow.workspace = true bstr.workspace = true diff --git a/cli/src/highlight.rs b/cli/src/highlight.rs index cfdd2f76c..8611374dc 100644 --- a/cli/src/highlight.rs +++ b/cli/src/highlight.rs @@ -5,10 +5,11 @@ use std::{ io::{self, Write as _}, path::{self, Path, PathBuf}, str, - sync::{atomic::AtomicUsize, Arc, LazyLock}, + sync::{atomic::AtomicUsize, Arc}, time::Instant, }; +use ansi_colours::{ansi256_from_rgb, rgb_from_ansi256}; use anstyle::{Ansi256Color, AnsiColor, Color, Effects, RgbColor}; use anyhow::Result; use serde::{ser::SerializeMap, Deserialize, Deserializer, Serialize, Serializer}; @@ -44,9 +45,6 @@ pub const HTML_FOOTER: &str = " "; -static CSS_STYLES_BY_COLOR_ID: LazyLock> = - LazyLock::new(|| serde_json::from_str(include_str!("../vendor/xterm-colors.json")).unwrap()); - #[derive(Debug, Default)] pub struct Style { pub ansi: anstyle::Style, @@ -224,9 +222,8 @@ fn parse_style(style: &mut Style, json: Value) { if let Some(Color::Rgb(RgbColor(red, green, blue))) = style.ansi.get_fg_color() { if !terminal_supports_truecolor() { - style.ansi = style - .ansi - .fg_color(Some(closest_xterm_color(red, green, blue))); + let ansi256 = Color::Ansi256(Ansi256Color(ansi256_from_rgb((red, green, blue)))); + style.ansi = style.ansi.fg_color(Some(ansi256)); } } } @@ -303,7 +300,8 @@ fn write_color(buffer: &mut String, color: Color) { _ => unreachable!(), }, Color::Ansi256(Ansi256Color(n)) => { - write!(buffer, "color: {}", CSS_STYLES_BY_COLOR_ID[n as usize]).unwrap(); + let (r, g, b) = rgb_from_ansi256(n); + write!(buffer, "color: #{r:02x}{g:02x}{b:02x}").unwrap(); } Color::Rgb(RgbColor(r, g, b)) => write!(buffer, "color: #{r:02x}{g:02x}{b:02x}").unwrap(), } @@ -314,30 +312,6 @@ fn terminal_supports_truecolor() -> bool { .is_ok_and(|truecolor| truecolor == "truecolor" || truecolor == "24bit") } -fn closest_xterm_color(red: u8, green: u8, blue: u8) -> Color { - use std::cmp::{max, min}; - - let colors = CSS_STYLES_BY_COLOR_ID - .iter() - .enumerate() - .map(|(color_id, hex)| (color_id as u8, hex_string_to_rgb(hex).unwrap())); - - // Get the xterm color with the minimum Euclidean distance to the target color - // i.e. distance = √ (r2 - r1)² + (g2 - g1)² + (b2 - b1)² - let distances = colors.map(|(color_id, (r, g, b))| { - let r_delta = (max(r, red) - min(r, red)) as u32; - let g_delta = (max(g, green) - min(g, green)) as u32; - let b_delta = (max(b, blue) - min(b, blue)) as u32; - let distance = r_delta.pow(2) + g_delta.pow(2) + b_delta.pow(2); - // don't need to actually take the square root for the sake of comparison - (color_id, distance) - }); - - Color::Ansi256(Ansi256Color( - distances.min_by(|(_, d1), (_, d2)| d1.cmp(d2)).unwrap().0, - )) -} - pub struct HighlightOptions { pub theme: Theme, pub check: bool, @@ -518,12 +492,12 @@ mod tests { ); assert_eq!(style.css, Some("color: #26a69a".to_string())); - // junglegreen gets approximated as darkcyan when the terminal does not support it + // junglegreen gets approximated as cadetblue when the terminal does not support it env::set_var("COLORTERM", ""); parse_style(&mut style, Value::String(JUNGLE_GREEN.to_string())); assert_eq!( style.ansi.get_fg_color(), - Some(Color::Ansi256(Ansi256Color(36))) + Some(Color::Ansi256(Ansi256Color(72))) ); assert_eq!(style.css, Some("color: #26a69a".to_string())); diff --git a/cli/vendor/xterm-colors.json b/cli/vendor/xterm-colors.json deleted file mode 100644 index 479944967..000000000 --- a/cli/vendor/xterm-colors.json +++ /dev/null @@ -1,258 +0,0 @@ -[ - "#000000", - "#800000", - "#008000", - "#808000", - "#000080", - "#800080", - "#008080", - "#c0c0c0", - "#808080", - "#ff0000", - "#00ff00", - "#ffff00", - "#0000ff", - "#ff00ff", - "#00ffff", - "#ffffff", - "#000000", - "#00005f", - "#000087", - "#0000af", - "#0000d7", - "#0000ff", - "#005f00", - "#005f5f", - "#005f87", - "#005faf", - "#005fd7", - "#005fff", - "#008700", - "#00875f", - "#008787", - "#0087af", - "#0087d7", - "#0087ff", - "#00af00", - "#00af5f", - "#00af87", - "#00afaf", - "#00afd7", - "#00afff", - "#00d700", - "#00d75f", - "#00d787", - "#00d7af", - "#00d7d7", - "#00d7ff", - "#00ff00", - "#00ff5f", - "#00ff87", - "#00ffaf", - "#00ffd7", - "#00ffff", - "#5f0000", - "#5f005f", - "#5f0087", - "#5f00af", - "#5f00d7", - "#5f00ff", - "#5f5f00", - "#5f5f5f", - "#5f5f87", - "#5f5faf", - "#5f5fd7", - "#5f5fff", - "#5f8700", - "#5f875f", - "#5f8787", - "#5f87af", - "#5f87d7", - "#5f87ff", - "#5faf00", - "#5faf5f", - "#5faf87", - "#5fafaf", - "#5fafd7", - "#5fafff", - "#5fd700", - "#5fd75f", - "#5fd787", - "#5fd7af", - "#5fd7d7", - "#5fd7ff", - "#5fff00", - "#5fff5f", - "#5fff87", - "#5fffaf", - "#5fffd7", - "#5fffff", - "#870000", - "#87005f", - "#870087", - "#8700af", - "#8700d7", - "#8700ff", - "#875f00", - "#875f5f", - "#875f87", - "#875faf", - "#875fd7", - "#875fff", - "#878700", - "#87875f", - "#878787", - "#8787af", - "#8787d7", - "#8787ff", - "#87af00", - "#87af5f", - "#87af87", - "#87afaf", - "#87afd7", - "#87afff", - "#87d700", - "#87d75f", - "#87d787", - "#87d7af", - "#87d7d7", - "#87d7ff", - "#87ff00", - "#87ff5f", - "#87ff87", - "#87ffaf", - "#87ffd7", - "#87ffff", - "#af0000", - "#af005f", - "#af0087", - "#af00af", - "#af00d7", - "#af00ff", - "#af5f00", - "#af5f5f", - "#af5f87", - "#af5faf", - "#af5fd7", - "#af5fff", - "#af8700", - "#af875f", - "#af8787", - "#af87af", - "#af87d7", - "#af87ff", - "#afaf00", - "#afaf5f", - "#afaf87", - "#afafaf", - "#afafd7", - "#afafff", - "#afd700", - "#afd75f", - "#afd787", - "#afd7af", - "#afd7d7", - "#afd7ff", - "#afff00", - "#afff5f", - "#afff87", - "#afffaf", - "#afffd7", - "#afffff", - "#d70000", - "#d7005f", - "#d70087", - "#d700af", - "#d700d7", - "#d700ff", - "#d75f00", - "#d75f5f", - "#d75f87", - "#d75faf", - "#d75fd7", - "#d75fff", - "#d78700", - "#d7875f", - "#d78787", - "#d787af", - "#d787d7", - "#d787ff", - "#d7af00", - "#d7af5f", - "#d7af87", - "#d7afaf", - "#d7afd7", - "#d7afff", - "#d7d700", - "#d7d75f", - "#d7d787", - "#d7d7af", - "#d7d7d7", - "#d7d7ff", - "#d7ff00", - "#d7ff5f", - "#d7ff87", - "#d7ffaf", - "#d7ffd7", - "#d7ffff", - "#ff0000", - "#ff005f", - "#ff0087", - "#ff00af", - "#ff00d7", - "#ff00ff", - "#ff5f00", - "#ff5f5f", - "#ff5f87", - "#ff5faf", - "#ff5fd7", - "#ff5fff", - "#ff8700", - "#ff875f", - "#ff8787", - "#ff87af", - "#ff87d7", - "#ff87ff", - "#ffaf00", - "#ffaf5f", - "#ffaf87", - "#ffafaf", - "#ffafd7", - "#ffafff", - "#ffd700", - "#ffd75f", - "#ffd787", - "#ffd7af", - "#ffd7d7", - "#ffd7ff", - "#ffff00", - "#ffff5f", - "#ffff87", - "#ffffaf", - "#ffffd7", - "#ffffff", - "#080808", - "#121212", - "#1c1c1c", - "#262626", - "#303030", - "#3a3a3a", - "#444444", - "#4e4e4e", - "#585858", - "#626262", - "#6c6c6c", - "#767676", - "#808080", - "#8a8a8a", - "#949494", - "#9e9e9e", - "#a8a8a8", - "#b2b2b2", - "#bcbcbc", - "#c6c6c6", - "#d0d0d0", - "#dadada", - "#e4e4e4", - "#eeeeee" -]