1use crate::{rgb::Rgb, Color};
2use alloc::{format, string::String};
3
4#[derive(Debug, Clone, Copy, PartialEq, Eq)]
6pub struct Gradient {
7 pub start: Rgb,
9
10 pub end: Rgb,
12}
13
14impl Gradient {
15 #[inline]
17 pub const fn new(start: Rgb, end: Rgb) -> Self {
18 Self { start, end }
19 }
20
21 pub const fn from_color_rgb(start: Color, end: Color) -> Self {
22 let start_grad = match start {
23 Color::Rgb(r, g, b) => Rgb { r, g, b },
24 _ => Rgb { r: 0, g: 0, b: 0 },
25 };
26 let end_grad = match end {
27 Color::Rgb(r, g, b) => Rgb { r, g, b },
28 _ => Rgb { r: 0, g: 0, b: 0 },
29 };
30
31 Self {
32 start: start_grad,
33 end: end_grad,
34 }
35 }
36
37 pub fn at(&self, t: f32) -> Rgb {
39 self.start.lerp(self.end, t)
40 }
41
42 #[inline]
44 pub const fn reverse(&self) -> Self {
45 Self::new(self.end, self.start)
46 }
47
48 pub fn build(&self, text: &str, target: TargetGround) -> String {
49 let delta = 1.0 / text.len() as f32;
50 let mut result = text.char_indices().fold(String::new(), |mut acc, (i, c)| {
51 let temp = format!(
52 "\x1B[{}m{}",
53 self.at(i as f32 * delta).ansi_color_code(target),
54 c
55 );
56 acc.push_str(&temp);
57 acc
58 });
59
60 result.push_str("\x1B[0m");
61 result
62 }
63}
64
65pub fn build_all_gradient_text(text: &str, foreground: Gradient, background: Gradient) -> String {
66 let delta = 1.0 / text.len() as f32;
67 let mut result = text.char_indices().fold(String::new(), |mut acc, (i, c)| {
68 let step = i as f32 * delta;
69 let temp = format!(
70 "\x1B[{};{}m{}",
71 foreground
72 .at(step)
73 .ansi_color_code(TargetGround::Foreground),
74 background
75 .at(step)
76 .ansi_color_code(TargetGround::Background),
77 c
78 );
79 acc.push_str(&temp);
80 acc
81 });
82
83 result.push_str("\x1B[0m");
84 result
85}
86
87#[derive(Debug, Clone, Copy, PartialEq, Eq)]
88pub enum TargetGround {
89 Foreground,
90 Background,
91}
92
93impl TargetGround {
94 #[inline]
95 pub const fn code(&self) -> u8 {
96 match self {
97 Self::Foreground => 30,
98 Self::Background => 40,
99 }
100 }
101}
102
103pub trait ANSIColorCode {
104 fn ansi_color_code(&self, target: TargetGround) -> String;
105}