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