modcli/output/
gradient.rs1use crossterm::style::{Color, Stylize};
2
3pub fn generate(text: &str, start: Color, end: Color) -> String {
12 let chars: Vec<char> = text.chars().collect();
13 let steps = chars.len().max(1);
14 let mut result = String::with_capacity(text.len() * 10); for (i, c) in chars.iter().enumerate() {
17 let r = interpolate(get_r(&start), get_r(&end), i, steps);
18 let g = interpolate(get_g(&start), get_g(&end), i, steps);
19 let b = interpolate(get_b(&start), get_b(&end), i, steps);
20 let color = Color::Rgb { r, g, b };
21 result.push_str(&c.to_string().with(color).to_string());
22 }
23
24 result
25}
26
27pub fn two_color(text: &str, start: Color, end: Color) -> String {
32 generate(text, start, end)
33}
34
35pub fn three_color(text: &str, start: Color, mid: Color, end: Color) -> String {
39 let chars: Vec<char> = text.chars().collect();
40 let total = chars.len().max(1);
41 let midpoint = total / 2;
42 let mut result = String::with_capacity(text.len() * 10);
43
44 for (i, c) in chars.iter().enumerate() {
45 let (from, to, step, steps) = if i < midpoint {
46 (start, mid, i, midpoint)
47 } else {
48 (mid, end, i - midpoint, total - midpoint)
49 };
50
51 let r = interpolate(get_r(&from), get_r(&to), step, steps);
52 let g = interpolate(get_g(&from), get_g(&to), step, steps);
53 let b = interpolate(get_b(&from), get_b(&to), step, steps);
54 let color = Color::Rgb { r, g, b };
55 result.push_str(&c.to_string().with(color).to_string());
56 }
57
58 result
59}
60
61pub fn multi_color(text: &str, colors: Vec<Color>) -> String {
65 let chars: Vec<char> = text.chars().collect();
66 let steps = chars.len().max(1);
67 let segments = colors.len().saturating_sub(1).max(1);
68 let mut result = String::with_capacity(text.len() * 10);
69
70 for (i, c) in chars.iter().enumerate() {
71 let t = i as f32 / (steps - 1).max(1) as f32;
72 let seg_float = t * segments as f32;
73 let seg = seg_float.floor() as usize;
74 let seg_t = seg_float - seg as f32;
75
76 let from = colors.get(seg).unwrap_or(&colors[0]);
77 let to = colors.get(seg + 1).unwrap_or(from);
78
79 let r = interpolate(get_r(from), get_r(to), (seg_t * 100.0) as usize, 100);
80 let g = interpolate(get_g(from), get_g(to), (seg_t * 100.0) as usize, 100);
81 let b = interpolate(get_b(from), get_b(to), (seg_t * 100.0) as usize, 100);
82
83 let color = Color::Rgb { r, g, b };
84 result.push_str(&c.to_string().with(color).to_string());
85 }
86
87 result
88}
89
90fn get_r(c: &Color) -> u8 {
100 match c {
101 Color::Rgb { r, .. } => *r,
102 _ => 255,
103 }
104}
105
106fn get_g(c: &Color) -> u8 {
109 match c {
110 Color::Rgb { g, .. } => *g,
111 _ => 255,
112 }
113}
114
115fn get_b(c: &Color) -> u8 {
118 match c {
119 Color::Rgb { b, .. } => *b,
120 _ => 255,
121 }
122}
123
124fn interpolate(start: u8, end: u8, step: usize, total: usize) -> u8 {
130 let start_f = start as f32;
131 let end_f = end as f32;
132 let ratio = step as f32 / (total - 1).max(1) as f32;
133 (start_f + (end_f - start_f) * ratio).round() as u8
134}