/rust/registry/src/index.crates.io-1949cf8c6b5b557f/nu-ansi-term-0.46.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 | 0 | pub const fn from_color_rgb(start: Color, end: Color) -> Self { |
20 | 0 | let start_grad = match start { |
21 | 0 | Color::Rgb(r, g, b) => Rgb { r, g, b }, |
22 | 0 | _ => Rgb { r: 0, g: 0, b: 0 }, |
23 | | }; |
24 | 0 | let end_grad = match end { |
25 | 0 | Color::Rgb(r, g, b) => Rgb { r, g, b }, |
26 | 0 | _ => Rgb { r: 0, g: 0, b: 0 }, |
27 | | }; |
28 | | |
29 | 0 | Self { |
30 | 0 | start: start_grad, |
31 | 0 | end: end_grad, |
32 | 0 | } |
33 | 0 | } |
34 | | |
35 | | /// Computes the [Rgb] color between `start` and `end` for `t` |
36 | 0 | pub fn at(&self, t: f32) -> Rgb { |
37 | 0 | self.start.lerp(self.end, t) |
38 | 0 | } |
39 | | |
40 | | /// Returns the reverse of `self` |
41 | | #[inline] |
42 | 0 | pub const fn reverse(&self) -> Self { |
43 | 0 | Self::new(self.end, self.start) |
44 | 0 | } |
45 | | |
46 | | #[allow(dead_code)] |
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 | | #[allow(dead_code)] |
65 | 0 | pub fn build_all_gradient_text(text: &str, foreground: Gradient, background: Gradient) -> String { |
66 | 0 | let delta = 1.0 / text.len() as f32; |
67 | 0 | let mut result = text.char_indices().fold(String::new(), |mut acc, (i, c)| { |
68 | 0 | let step = i as f32 * delta; |
69 | 0 | let temp = format!( |
70 | 0 | "\x1B[{};{}m{}", |
71 | 0 | foreground |
72 | 0 | .at(step) |
73 | 0 | .ansi_color_code(TargetGround::Foreground), |
74 | 0 | background |
75 | 0 | .at(step) |
76 | 0 | .ansi_color_code(TargetGround::Background), |
77 | | c |
78 | | ); |
79 | 0 | acc.push_str(&temp); |
80 | 0 | acc |
81 | 0 | }); |
82 | | |
83 | 0 | result.push_str("\x1B[0m"); |
84 | 0 | result |
85 | 0 | } |
86 | | |
87 | | #[derive(Debug, Clone, Copy, PartialEq, Eq)] |
88 | | pub enum TargetGround { |
89 | | Foreground, |
90 | | Background, |
91 | | } |
92 | | |
93 | | impl TargetGround { |
94 | | #[inline] |
95 | 0 | pub const fn code(&self) -> u8 { |
96 | 0 | match self { |
97 | 0 | Self::Foreground => 30, |
98 | 0 | Self::Background => 40, |
99 | | } |
100 | 0 | } |
101 | | } |
102 | | |
103 | | pub trait ANSIColorCode { |
104 | | fn ansi_color_code(&self, target: TargetGround) -> String; |
105 | | } |