mirror of
https://github.com/nushell/nushell.git
synced 2024-12-02 05:13:56 +01:00
106 lines
2.7 KiB
Rust
106 lines
2.7 KiB
Rust
|
use crate::{rgb::Rgb, Color};
|
||
|
|
||
|
/// Linear color gradient between two color stops
|
||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||
|
pub struct Gradient {
|
||
|
/// Start Color of Gradient
|
||
|
pub start: Rgb,
|
||
|
|
||
|
/// End Color of Gradient
|
||
|
pub end: Rgb,
|
||
|
}
|
||
|
|
||
|
impl Gradient {
|
||
|
/// Creates a new [Gradient] with two [Rgb] colors, `start` and `end`
|
||
|
#[inline]
|
||
|
pub const fn new(start: Rgb, end: Rgb) -> Self {
|
||
|
Self { start, end }
|
||
|
}
|
||
|
pub const fn from_color_rgb(start: Color, end: Color) -> Self {
|
||
|
let start_grad = match start {
|
||
|
Color::Rgb(r, g, b) => Rgb { r, g, b },
|
||
|
_ => Rgb { r: 0, g: 0, b: 0 },
|
||
|
};
|
||
|
let end_grad = match end {
|
||
|
Color::Rgb(r, g, b) => Rgb { r, g, b },
|
||
|
_ => Rgb { r: 0, g: 0, b: 0 },
|
||
|
};
|
||
|
|
||
|
Self {
|
||
|
start: start_grad,
|
||
|
end: end_grad,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// Computes the [Rgb] color between `start` and `end` for `t`
|
||
|
pub fn at(&self, t: f32) -> Rgb {
|
||
|
self.start.lerp(self.end, t)
|
||
|
}
|
||
|
|
||
|
/// Returns the reverse of `self`
|
||
|
#[inline]
|
||
|
pub const fn reverse(&self) -> Self {
|
||
|
Self::new(self.end, self.start)
|
||
|
}
|
||
|
|
||
|
#[allow(dead_code)]
|
||
|
pub fn build(&self, text: &str, target: TargetGround) -> String {
|
||
|
let delta = 1.0 / text.len() as f32;
|
||
|
let mut result = text.char_indices().fold(String::new(), |mut acc, (i, c)| {
|
||
|
let temp = format!(
|
||
|
"\x1B[{}m{}",
|
||
|
self.at(i as f32 * delta).ansi_color_code(target),
|
||
|
c
|
||
|
);
|
||
|
acc.push_str(&temp);
|
||
|
acc
|
||
|
});
|
||
|
|
||
|
result.push_str("\x1B[0m");
|
||
|
result
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#[allow(dead_code)]
|
||
|
pub fn build_all_gradient_text(text: &str, foreground: Gradient, background: Gradient) -> String {
|
||
|
let delta = 1.0 / text.len() as f32;
|
||
|
let mut result = text.char_indices().fold(String::new(), |mut acc, (i, c)| {
|
||
|
let step = i as f32 * delta;
|
||
|
let temp = format!(
|
||
|
"\x1B[{};{}m{}",
|
||
|
foreground
|
||
|
.at(step)
|
||
|
.ansi_color_code(TargetGround::Foreground),
|
||
|
background
|
||
|
.at(step)
|
||
|
.ansi_color_code(TargetGround::Background),
|
||
|
c
|
||
|
);
|
||
|
acc.push_str(&temp);
|
||
|
acc
|
||
|
});
|
||
|
|
||
|
result.push_str("\x1B[0m");
|
||
|
result
|
||
|
}
|
||
|
|
||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||
|
pub enum TargetGround {
|
||
|
Foreground,
|
||
|
Background,
|
||
|
}
|
||
|
|
||
|
impl TargetGround {
|
||
|
#[inline]
|
||
|
pub const fn code(&self) -> u8 {
|
||
|
match self {
|
||
|
Self::Foreground => 30,
|
||
|
Self::Background => 40,
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pub trait ANSIColorCode {
|
||
|
fn ansi_color_code(&self, target: TargetGround) -> String;
|
||
|
}
|