1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
#![cfg(feature = "truecolor")]
use std::env;
use crate::Rgb;
fn is_supported() -> bool {
env::var("COLORTERM").ok().is_some_and(|s| s == "truecolor" || s == "24bit")
}
/// Changes the background color of a string using three [ANSI escape codes](https://en.wikipedia.org/wiki/ANSI_escape_code#24-bit)
/// if the terminal support [truecolors](https://en.wikipedia.org/wiki/Color_depth#True_color_(24-bit)).
///
/// If the environment variable `COLORTERM` is not defined or contains neither `truecolor` nor `24bit`, the string parameter
/// is returned as is.
///
/// This function also changes the foreground color according to the specified background color in order to ensure that the
/// text is visible.
///
/// # Examples
///
/// ```
/// use chocodye::{Rgb, ansi_text};
/// use std::env;
///
/// env::remove_var("COLORTERM");
/// assert_eq!(ansi_text(Rgb::RED, "hello world!"), "hello world!");
///
/// env::set_var("COLORTERM", "truecolor");
/// assert_eq!(ansi_text(Rgb::RED, "hello world!"), "\x1B[48;2;255;0;0m\x1B[38;2;255;255;255mhello world!\x1B[0m");
/// // ^^^^^^^ ^^^^^^^^^^^ ^^^^^^^^^^^^
/// // background foreground text
/// ```
#[cfg_attr(docsrs, doc(cfg(feature = "truecolor")))]
#[must_use]
pub fn ansi_text(bg: Rgb, s: &str) -> String {
if !is_supported() {
s.to_owned()
}
else {
let fg = {
const LIMIT: u32 = Rgb::gray(127).distance(Rgb::WHITE);
if bg.distance(Rgb::WHITE) >= LIMIT {
Rgb::WHITE
} else {
Rgb::BLACK
}
};
format!("\x1B[48;2;{};{};{}m\x1B[38;2;{};{};{}m{s}\x1B[0m",
bg.r, bg.g, bg.b,
fg.r, fg.g, fg.b
)
}
}