aboutsummaryrefslogtreecommitdiff
path: root/vendor/anstyle/src/color.rs
diff options
context:
space:
mode:
authorValentin Popov <valentin@popov.link>2024-01-08 00:21:28 +0300
committerValentin Popov <valentin@popov.link>2024-01-08 00:21:28 +0300
commit1b6a04ca5504955c571d1c97504fb45ea0befee4 (patch)
tree7579f518b23313e8a9748a88ab6173d5e030b227 /vendor/anstyle/src/color.rs
parent5ecd8cf2cba827454317368b68571df0d13d7842 (diff)
downloadfparkan-1b6a04ca5504955c571d1c97504fb45ea0befee4.tar.xz
fparkan-1b6a04ca5504955c571d1c97504fb45ea0befee4.zip
Initial vendor packages
Signed-off-by: Valentin Popov <valentin@popov.link>
Diffstat (limited to 'vendor/anstyle/src/color.rs')
-rw-r--r--vendor/anstyle/src/color.rs611
1 files changed, 611 insertions, 0 deletions
diff --git a/vendor/anstyle/src/color.rs b/vendor/anstyle/src/color.rs
new file mode 100644
index 0000000..8dcf6ca
--- /dev/null
+++ b/vendor/anstyle/src/color.rs
@@ -0,0 +1,611 @@
+/// Any ANSI color code scheme
+#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
+pub enum Color {
+ Ansi(AnsiColor),
+ Ansi256(Ansi256Color),
+ Rgb(RgbColor),
+}
+
+impl Color {
+ /// Create a [`Style`][crate::Style] with this as the foreground
+ #[inline]
+ pub fn on(self, background: impl Into<Color>) -> crate::Style {
+ crate::Style::new()
+ .fg_color(Some(self))
+ .bg_color(Some(background.into()))
+ }
+
+ /// Create a [`Style`][crate::Style] with this as the foreground
+ #[inline]
+ pub const fn on_default(self) -> crate::Style {
+ crate::Style::new().fg_color(Some(self))
+ }
+
+ /// Render the ANSI code for a foreground color
+ #[inline]
+ pub fn render_fg(self) -> impl core::fmt::Display + Copy + Clone {
+ match self {
+ Self::Ansi(color) => DisplayBuffer::default().write_str(color.as_fg_str()),
+ Self::Ansi256(color) => color.as_fg_buffer(),
+ Self::Rgb(color) => color.as_fg_buffer(),
+ }
+ }
+
+ #[inline]
+ #[cfg(feature = "std")]
+ pub(crate) fn write_fg_to(self, write: &mut dyn std::io::Write) -> std::io::Result<()> {
+ let buffer = match self {
+ Self::Ansi(color) => DisplayBuffer::default().write_str(color.as_fg_str()),
+ Self::Ansi256(color) => color.as_fg_buffer(),
+ Self::Rgb(color) => color.as_fg_buffer(),
+ };
+ buffer.write_to(write)
+ }
+
+ /// Render the ANSI code for a background color
+ #[inline]
+ pub fn render_bg(self) -> impl core::fmt::Display + Copy + Clone {
+ match self {
+ Self::Ansi(color) => DisplayBuffer::default().write_str(color.as_bg_str()),
+ Self::Ansi256(color) => color.as_bg_buffer(),
+ Self::Rgb(color) => color.as_bg_buffer(),
+ }
+ }
+
+ #[inline]
+ #[cfg(feature = "std")]
+ pub(crate) fn write_bg_to(self, write: &mut dyn std::io::Write) -> std::io::Result<()> {
+ let buffer = match self {
+ Self::Ansi(color) => DisplayBuffer::default().write_str(color.as_bg_str()),
+ Self::Ansi256(color) => color.as_bg_buffer(),
+ Self::Rgb(color) => color.as_bg_buffer(),
+ };
+ buffer.write_to(write)
+ }
+
+ #[inline]
+ pub(crate) fn render_underline(self) -> impl core::fmt::Display + Copy + Clone {
+ match self {
+ Self::Ansi(color) => color.as_underline_buffer(),
+ Self::Ansi256(color) => color.as_underline_buffer(),
+ Self::Rgb(color) => color.as_underline_buffer(),
+ }
+ }
+
+ #[inline]
+ #[cfg(feature = "std")]
+ pub(crate) fn write_underline_to(self, write: &mut dyn std::io::Write) -> std::io::Result<()> {
+ let buffer = match self {
+ Self::Ansi(color) => color.as_underline_buffer(),
+ Self::Ansi256(color) => color.as_underline_buffer(),
+ Self::Rgb(color) => color.as_underline_buffer(),
+ };
+ buffer.write_to(write)
+ }
+}
+
+impl From<AnsiColor> for Color {
+ #[inline]
+ fn from(inner: AnsiColor) -> Self {
+ Self::Ansi(inner)
+ }
+}
+
+impl From<Ansi256Color> for Color {
+ #[inline]
+ fn from(inner: Ansi256Color) -> Self {
+ Self::Ansi256(inner)
+ }
+}
+
+impl From<RgbColor> for Color {
+ #[inline]
+ fn from(inner: RgbColor) -> Self {
+ Self::Rgb(inner)
+ }
+}
+
+impl From<u8> for Color {
+ #[inline]
+ fn from(inner: u8) -> Self {
+ Self::Ansi256(inner.into())
+ }
+}
+
+impl From<(u8, u8, u8)> for Color {
+ #[inline]
+ fn from(inner: (u8, u8, u8)) -> Self {
+ Self::Rgb(inner.into())
+ }
+}
+
+/// Available 4-bit ANSI color palette codes
+///
+/// The user's terminal defines the meaning of the each palette code.
+#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
+#[repr(u8)]
+pub enum AnsiColor {
+ /// Black: #0 (foreground code `30`, background code `40`).
+ Black,
+
+ /// Red: #1 (foreground code `31`, background code `41`).
+ Red,
+
+ /// Green: #2 (foreground code `32`, background code `42`).
+ Green,
+
+ /// Yellow: #3 (foreground code `33`, background code `43`).
+ Yellow,
+
+ /// Blue: #4 (foreground code `34`, background code `44`).
+ Blue,
+
+ /// Magenta: #5 (foreground code `35`, background code `45`).
+ Magenta,
+
+ /// Cyan: #6 (foreground code `36`, background code `46`).
+ Cyan,
+
+ /// White: #7 (foreground code `37`, background code `47`).
+ White,
+
+ /// Bright black: #0 (foreground code `90`, background code `100`).
+ BrightBlack,
+
+ /// Bright red: #1 (foreground code `91`, background code `101`).
+ BrightRed,
+
+ /// Bright green: #2 (foreground code `92`, background code `102`).
+ BrightGreen,
+
+ /// Bright yellow: #3 (foreground code `93`, background code `103`).
+ BrightYellow,
+
+ /// Bright blue: #4 (foreground code `94`, background code `104`).
+ BrightBlue,
+
+ /// Bright magenta: #5 (foreground code `95`, background code `105`).
+ BrightMagenta,
+
+ /// Bright cyan: #6 (foreground code `96`, background code `106`).
+ BrightCyan,
+
+ /// Bright white: #7 (foreground code `97`, background code `107`).
+ BrightWhite,
+}
+
+impl AnsiColor {
+ /// Create a [`Style`][crate::Style] with this as the foreground
+ #[inline]
+ pub fn on(self, background: impl Into<Color>) -> crate::Style {
+ crate::Style::new()
+ .fg_color(Some(self.into()))
+ .bg_color(Some(background.into()))
+ }
+
+ /// Create a [`Style`][crate::Style] with this as the foreground
+ #[inline]
+ pub const fn on_default(self) -> crate::Style {
+ crate::Style::new().fg_color(Some(Color::Ansi(self)))
+ }
+
+ /// Render the ANSI code for a foreground color
+ #[inline]
+ pub fn render_fg(self) -> impl core::fmt::Display + Copy + Clone {
+ self.as_fg_str()
+ }
+
+ #[inline]
+ fn as_fg_str(&self) -> &'static str {
+ match self {
+ Self::Black => escape!("3", "0"),
+ Self::Red => escape!("3", "1"),
+ Self::Green => escape!("3", "2"),
+ Self::Yellow => escape!("3", "3"),
+ Self::Blue => escape!("3", "4"),
+ Self::Magenta => escape!("3", "5"),
+ Self::Cyan => escape!("3", "6"),
+ Self::White => escape!("3", "7"),
+ Self::BrightBlack => escape!("9", "0"),
+ Self::BrightRed => escape!("9", "1"),
+ Self::BrightGreen => escape!("9", "2"),
+ Self::BrightYellow => escape!("9", "3"),
+ Self::BrightBlue => escape!("9", "4"),
+ Self::BrightMagenta => escape!("9", "5"),
+ Self::BrightCyan => escape!("9", "6"),
+ Self::BrightWhite => escape!("9", "7"),
+ }
+ }
+
+ /// Render the ANSI code for a background color
+ #[inline]
+ pub fn render_bg(self) -> impl core::fmt::Display + Copy + Clone {
+ self.as_bg_str()
+ }
+
+ #[inline]
+ fn as_bg_str(&self) -> &'static str {
+ match self {
+ Self::Black => escape!("4", "0"),
+ Self::Red => escape!("4", "1"),
+ Self::Green => escape!("4", "2"),
+ Self::Yellow => escape!("4", "3"),
+ Self::Blue => escape!("4", "4"),
+ Self::Magenta => escape!("4", "5"),
+ Self::Cyan => escape!("4", "6"),
+ Self::White => escape!("4", "7"),
+ Self::BrightBlack => escape!("10", "0"),
+ Self::BrightRed => escape!("10", "1"),
+ Self::BrightGreen => escape!("10", "2"),
+ Self::BrightYellow => escape!("10", "3"),
+ Self::BrightBlue => escape!("10", "4"),
+ Self::BrightMagenta => escape!("10", "5"),
+ Self::BrightCyan => escape!("10", "6"),
+ Self::BrightWhite => escape!("10", "7"),
+ }
+ }
+
+ #[inline]
+ fn as_underline_buffer(&self) -> DisplayBuffer {
+ // No per-color codes; must delegate to `Ansi256Color`
+ Ansi256Color::from(*self).as_underline_buffer()
+ }
+
+ /// Change the color to/from bright
+ #[must_use]
+ #[inline]
+ pub fn bright(self, yes: bool) -> Self {
+ if yes {
+ match self {
+ Self::Black => Self::BrightBlack,
+ Self::Red => Self::BrightRed,
+ Self::Green => Self::BrightGreen,
+ Self::Yellow => Self::BrightYellow,
+ Self::Blue => Self::BrightBlue,
+ Self::Magenta => Self::BrightMagenta,
+ Self::Cyan => Self::BrightCyan,
+ Self::White => Self::BrightWhite,
+ Self::BrightBlack => self,
+ Self::BrightRed => self,
+ Self::BrightGreen => self,
+ Self::BrightYellow => self,
+ Self::BrightBlue => self,
+ Self::BrightMagenta => self,
+ Self::BrightCyan => self,
+ Self::BrightWhite => self,
+ }
+ } else {
+ match self {
+ Self::Black => self,
+ Self::Red => self,
+ Self::Green => self,
+ Self::Yellow => self,
+ Self::Blue => self,
+ Self::Magenta => self,
+ Self::Cyan => self,
+ Self::White => self,
+ Self::BrightBlack => Self::Black,
+ Self::BrightRed => Self::Red,
+ Self::BrightGreen => Self::Green,
+ Self::BrightYellow => Self::Yellow,
+ Self::BrightBlue => Self::Blue,
+ Self::BrightMagenta => Self::Magenta,
+ Self::BrightCyan => Self::Cyan,
+ Self::BrightWhite => Self::White,
+ }
+ }
+ }
+
+ /// Report whether the color is bright
+ #[inline]
+ pub fn is_bright(self) -> bool {
+ match self {
+ Self::Black => false,
+ Self::Red => false,
+ Self::Green => false,
+ Self::Yellow => false,
+ Self::Blue => false,
+ Self::Magenta => false,
+ Self::Cyan => false,
+ Self::White => false,
+ Self::BrightBlack => true,
+ Self::BrightRed => true,
+ Self::BrightGreen => true,
+ Self::BrightYellow => true,
+ Self::BrightBlue => true,
+ Self::BrightMagenta => true,
+ Self::BrightCyan => true,
+ Self::BrightWhite => true,
+ }
+ }
+}
+
+/// 256 (8-bit) color support
+///
+/// - `0..16` are [`AnsiColor`] palette codes
+/// - `0..232` map to [`RgbColor`] color values
+/// - `232..` map to [`RgbColor`] gray-scale values
+#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
+#[repr(transparent)]
+pub struct Ansi256Color(pub u8);
+
+impl Ansi256Color {
+ /// Create a [`Style`][crate::Style] with this as the foreground
+ #[inline]
+ pub fn on(self, background: impl Into<Color>) -> crate::Style {
+ crate::Style::new()
+ .fg_color(Some(self.into()))
+ .bg_color(Some(background.into()))
+ }
+
+ /// Create a [`Style`][crate::Style] with this as the foreground
+ #[inline]
+ pub const fn on_default(self) -> crate::Style {
+ crate::Style::new().fg_color(Some(Color::Ansi256(self)))
+ }
+
+ #[inline]
+ pub const fn index(self) -> u8 {
+ self.0
+ }
+
+ #[inline]
+ pub const fn into_ansi(self) -> Option<AnsiColor> {
+ match self.index() {
+ 0 => Some(AnsiColor::Black),
+ 1 => Some(AnsiColor::Red),
+ 2 => Some(AnsiColor::Green),
+ 3 => Some(AnsiColor::Yellow),
+ 4 => Some(AnsiColor::Blue),
+ 5 => Some(AnsiColor::Magenta),
+ 6 => Some(AnsiColor::Cyan),
+ 7 => Some(AnsiColor::White),
+ 8 => Some(AnsiColor::BrightBlack),
+ 9 => Some(AnsiColor::BrightRed),
+ 10 => Some(AnsiColor::BrightGreen),
+ 11 => Some(AnsiColor::BrightYellow),
+ 12 => Some(AnsiColor::BrightBlue),
+ 13 => Some(AnsiColor::BrightMagenta),
+ 14 => Some(AnsiColor::BrightCyan),
+ 15 => Some(AnsiColor::BrightWhite),
+ _ => None,
+ }
+ }
+
+ #[inline]
+ pub const fn from_ansi(color: AnsiColor) -> Self {
+ match color {
+ AnsiColor::Black => Self(0),
+ AnsiColor::Red => Self(1),
+ AnsiColor::Green => Self(2),
+ AnsiColor::Yellow => Self(3),
+ AnsiColor::Blue => Self(4),
+ AnsiColor::Magenta => Self(5),
+ AnsiColor::Cyan => Self(6),
+ AnsiColor::White => Self(7),
+ AnsiColor::BrightBlack => Self(8),
+ AnsiColor::BrightRed => Self(9),
+ AnsiColor::BrightGreen => Self(10),
+ AnsiColor::BrightYellow => Self(11),
+ AnsiColor::BrightBlue => Self(12),
+ AnsiColor::BrightMagenta => Self(13),
+ AnsiColor::BrightCyan => Self(14),
+ AnsiColor::BrightWhite => Self(15),
+ }
+ }
+
+ /// Render the ANSI code for a foreground color
+ #[inline]
+ pub fn render_fg(self) -> impl core::fmt::Display + Copy + Clone {
+ self.as_fg_buffer()
+ }
+
+ #[inline]
+ fn as_fg_buffer(&self) -> DisplayBuffer {
+ DisplayBuffer::default()
+ .write_str("\x1B[38;5;")
+ .write_code(self.index())
+ .write_str("m")
+ }
+
+ /// Render the ANSI code for a background color
+ #[inline]
+ pub fn render_bg(self) -> impl core::fmt::Display + Copy + Clone {
+ self.as_bg_buffer()
+ }
+
+ #[inline]
+ fn as_bg_buffer(&self) -> DisplayBuffer {
+ DisplayBuffer::default()
+ .write_str("\x1B[48;5;")
+ .write_code(self.index())
+ .write_str("m")
+ }
+
+ #[inline]
+ fn as_underline_buffer(&self) -> DisplayBuffer {
+ DisplayBuffer::default()
+ .write_str("\x1B[58;5;")
+ .write_code(self.index())
+ .write_str("m")
+ }
+}
+
+impl From<u8> for Ansi256Color {
+ #[inline]
+ fn from(inner: u8) -> Self {
+ Self(inner)
+ }
+}
+
+impl From<AnsiColor> for Ansi256Color {
+ #[inline]
+ fn from(inner: AnsiColor) -> Self {
+ Self::from_ansi(inner)
+ }
+}
+
+/// 24-bit ANSI RGB color codes
+#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
+pub struct RgbColor(pub u8, pub u8, pub u8);
+
+impl RgbColor {
+ /// Create a [`Style`][crate::Style] with this as the foreground
+ #[inline]
+ pub fn on(self, background: impl Into<Color>) -> crate::Style {
+ crate::Style::new()
+ .fg_color(Some(self.into()))
+ .bg_color(Some(background.into()))
+ }
+
+ /// Create a [`Style`][crate::Style] with this as the foreground
+ #[inline]
+ pub const fn on_default(self) -> crate::Style {
+ crate::Style::new().fg_color(Some(Color::Rgb(self)))
+ }
+
+ #[inline]
+ pub const fn r(self) -> u8 {
+ self.0
+ }
+
+ #[inline]
+ pub const fn g(self) -> u8 {
+ self.1
+ }
+
+ #[inline]
+ pub const fn b(self) -> u8 {
+ self.2
+ }
+
+ /// Render the ANSI code for a foreground color
+ #[inline]
+ pub fn render_fg(self) -> impl core::fmt::Display + Copy + Clone {
+ self.as_fg_buffer()
+ }
+
+ #[inline]
+ fn as_fg_buffer(&self) -> DisplayBuffer {
+ DisplayBuffer::default()
+ .write_str("\x1B[38;2;")
+ .write_code(self.r())
+ .write_str(";")
+ .write_code(self.g())
+ .write_str(";")
+ .write_code(self.b())
+ .write_str("m")
+ }
+
+ /// Render the ANSI code for a background color
+ #[inline]
+ pub fn render_bg(self) -> impl core::fmt::Display + Copy + Clone {
+ self.as_bg_buffer()
+ }
+
+ #[inline]
+ fn as_bg_buffer(&self) -> DisplayBuffer {
+ DisplayBuffer::default()
+ .write_str("\x1B[48;2;")
+ .write_code(self.r())
+ .write_str(";")
+ .write_code(self.g())
+ .write_str(";")
+ .write_code(self.b())
+ .write_str("m")
+ }
+
+ #[inline]
+ fn as_underline_buffer(&self) -> DisplayBuffer {
+ DisplayBuffer::default()
+ .write_str("\x1B[58;2;")
+ .write_code(self.r())
+ .write_str(";")
+ .write_code(self.g())
+ .write_str(";")
+ .write_code(self.b())
+ .write_str("m")
+ }
+}
+
+impl From<(u8, u8, u8)> for RgbColor {
+ #[inline]
+ fn from(inner: (u8, u8, u8)) -> Self {
+ let (r, g, b) = inner;
+ Self(r, g, b)
+ }
+}
+
+#[derive(Copy, Clone, Default, Debug)]
+struct DisplayBuffer {
+ buffer: [u8; 19],
+ len: usize,
+}
+
+impl DisplayBuffer {
+ #[must_use]
+ #[inline(never)]
+ fn write_str(mut self, part: &'static str) -> Self {
+ for (i, b) in part.as_bytes().iter().enumerate() {
+ self.buffer[self.len + i] = *b;
+ }
+ self.len += part.len();
+ self
+ }
+
+ #[must_use]
+ #[inline(never)]
+ fn write_code(mut self, code: u8) -> Self {
+ let c1: u8 = (code / 100) % 10;
+ let c2: u8 = (code / 10) % 10;
+ let c3: u8 = code % 10;
+
+ let mut printed = true;
+ if c1 != 0 {
+ printed = true;
+ self.buffer[self.len] = b'0' + c1;
+ self.len += 1;
+ }
+ if c2 != 0 || printed {
+ self.buffer[self.len] = b'0' + c2;
+ self.len += 1;
+ }
+ // If we received a zero value we must still print a value.
+ self.buffer[self.len] = b'0' + c3;
+ self.len += 1;
+
+ self
+ }
+
+ #[inline]
+ fn as_str(&self) -> &str {
+ // SAFETY: Only `&str` can be written to the buffer
+ unsafe { core::str::from_utf8_unchecked(&self.buffer[0..self.len]) }
+ }
+
+ #[inline]
+ #[cfg(feature = "std")]
+ fn write_to(self, write: &mut dyn std::io::Write) -> std::io::Result<()> {
+ write.write_all(self.as_str().as_bytes())
+ }
+}
+
+impl core::fmt::Display for DisplayBuffer {
+ #[inline]
+ fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
+ self.as_str().fmt(f)
+ }
+}
+
+#[cfg(test)]
+#[cfg(feature = "std")]
+mod test {
+ use super::*;
+
+ #[test]
+ fn max_display_buffer() {
+ let c = RgbColor(255, 255, 255);
+ let actual = c.render_fg().to_string();
+ assert_eq!(actual, "\u{1b}[38;2;255;255;255m");
+ }
+}