Changes: - the composer and user messages now have a colored background that stretches the entire width of the terminal. - the prompt character was changed from a cyan `▌` to a bold `›`. - the "working" shimmer now follows the "dark gray" color of the terminal, better matching the terminal's color scheme | Terminal + Background | Screenshot | |------------------------------|------------| | iTerm with dark bg | <img width="810" height="641" alt="Screenshot 2025-09-25 at 11 44 52 AM" src="https://github.com/user-attachments/assets/1317e579-64a9-4785-93e6-98b0258f5d92" /> | | iTerm with light bg | <img width="845" height="540" alt="Screenshot 2025-09-25 at 11 46 29 AM" src="https://github.com/user-attachments/assets/e671d490-c747-4460-af0b-3f8d7f7a6b8e" /> | | iTerm with color bg | <img width="825" height="564" alt="Screenshot 2025-09-25 at 11 47 12 AM" src="https://github.com/user-attachments/assets/141cda1b-1164-41d5-87da-3be11e6a3063" /> | | Terminal.app with dark bg | <img width="577" height="367" alt="Screenshot 2025-09-25 at 11 45 22 AM" src="https://github.com/user-attachments/assets/93fc4781-99f7-4ee7-9c8e-3db3cd854fe5" /> | | Terminal.app with light bg | <img width="577" height="367" alt="Screenshot 2025-09-25 at 11 46 04 AM" src="https://github.com/user-attachments/assets/19bf6a3c-91e0-447b-9667-b8033f512219" /> | | Terminal.app with color bg | <img width="577" height="367" alt="Screenshot 2025-09-25 at 11 45 50 AM" src="https://github.com/user-attachments/assets/dd7c4b5b-342e-4028-8140-f4e65752bd0b" /> |
76 lines
2.2 KiB
Rust
76 lines
2.2 KiB
Rust
pub(crate) fn is_light(bg: (u8, u8, u8)) -> bool {
|
|
let (r, g, b) = bg;
|
|
let y = 0.299 * r as f32 + 0.587 * g as f32 + 0.114 * b as f32;
|
|
y > 128.0
|
|
}
|
|
|
|
pub(crate) fn blend(fg: (u8, u8, u8), bg: (u8, u8, u8), alpha: f32) -> (u8, u8, u8) {
|
|
let r = (fg.0 as f32 * alpha + bg.0 as f32 * (1.0 - alpha)) as u8;
|
|
let g = (fg.1 as f32 * alpha + bg.1 as f32 * (1.0 - alpha)) as u8;
|
|
let b = (fg.2 as f32 * alpha + bg.2 as f32 * (1.0 - alpha)) as u8;
|
|
(r, g, b)
|
|
}
|
|
|
|
/// Returns the perceptual color distance between two RGB colors.
|
|
/// Uses the CIE76 formula (Euclidean distance in Lab space approximation).
|
|
pub(crate) fn perceptual_distance(a: (u8, u8, u8), b: (u8, u8, u8)) -> f32 {
|
|
// Convert sRGB to linear RGB
|
|
fn srgb_to_linear(c: u8) -> f32 {
|
|
let c = c as f32 / 255.0;
|
|
if c <= 0.04045 {
|
|
c / 12.92
|
|
} else {
|
|
((c + 0.055) / 1.055).powf(2.4)
|
|
}
|
|
}
|
|
|
|
// Convert RGB to XYZ
|
|
fn rgb_to_xyz(r: u8, g: u8, b: u8) -> (f32, f32, f32) {
|
|
let r = srgb_to_linear(r);
|
|
let g = srgb_to_linear(g);
|
|
let b = srgb_to_linear(b);
|
|
|
|
let x = r * 0.4124 + g * 0.3576 + b * 0.1805;
|
|
let y = r * 0.2126 + g * 0.7152 + b * 0.0722;
|
|
let z = r * 0.0193 + g * 0.1192 + b * 0.9505;
|
|
(x, y, z)
|
|
}
|
|
|
|
// Convert XYZ to Lab
|
|
fn xyz_to_lab(x: f32, y: f32, z: f32) -> (f32, f32, f32) {
|
|
// D65 reference white
|
|
let xr = x / 0.95047;
|
|
let yr = y / 1.00000;
|
|
let zr = z / 1.08883;
|
|
|
|
fn f(t: f32) -> f32 {
|
|
if t > 0.008856 {
|
|
t.powf(1.0 / 3.0)
|
|
} else {
|
|
7.787 * t + 16.0 / 116.0
|
|
}
|
|
}
|
|
|
|
let fx = f(xr);
|
|
let fy = f(yr);
|
|
let fz = f(zr);
|
|
|
|
let l = 116.0 * fy - 16.0;
|
|
let a = 500.0 * (fx - fy);
|
|
let b = 200.0 * (fy - fz);
|
|
(l, a, b)
|
|
}
|
|
|
|
let (x1, y1, z1) = rgb_to_xyz(a.0, a.1, a.2);
|
|
let (x2, y2, z2) = rgb_to_xyz(b.0, b.1, b.2);
|
|
|
|
let (l1, a1, b1) = xyz_to_lab(x1, y1, z1);
|
|
let (l2, a2, b2) = xyz_to_lab(x2, y2, z2);
|
|
|
|
let dl = l1 - l2;
|
|
let da = a1 - a2;
|
|
let db = b1 - b2;
|
|
|
|
(dl * dl + da * da + db * db).sqrt()
|
|
}
|