From 90cc6bc41c322fddfea4c654f157fb304d0b8acf Mon Sep 17 00:00:00 2001 From: rascul Date: Wed, 14 Jan 2026 22:19:03 -0600 Subject: [PATCH] init --- .editorconfig | 6 +++ .gitignore | 1 + Cargo.lock | 16 ++++++ Cargo.toml | 7 +++ examples/colors.rs | 127 +++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 78 ++++++++++++++++++++++++++++ 6 files changed, 235 insertions(+) create mode 100644 .editorconfig create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 examples/colors.rs create mode 100644 src/lib.rs diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..baf2ca9 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,6 @@ +[*] +indent_style = tab +tab_width = 4 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..7c99ff1 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,16 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "color" +version = "0.1.0" +dependencies = [ + "libc", +] + +[[package]] +name = "libc" +version = "0.2.180" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcc35a38544a891a5f7c865aca548a982ccb3b8650a5b06d0fd33a10283c56fc" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..98824f4 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "color" +version = "0.1.0" +edition = "2024" + +[dependencies] +libc = "0.2.180" diff --git a/examples/colors.rs b/examples/colors.rs new file mode 100644 index 0000000..5b22500 --- /dev/null +++ b/examples/colors.rs @@ -0,0 +1,127 @@ +use color::{Color, NO_COLOR, TTY}; + +fn main() { + println!("NO_COLOR: {:?}", *NO_COLOR); + println!("TTY: {:?}", *TTY); + println!("\nColor\tBold\tLine\tStrike\tItalic\tBg"); + println!( + "{}Black\t{}Black{}\t{}Black{}\t{}Black{}\t{}Black{}\t{}{}Black{}", + Color::Black, + Color::Bold, + Color::ResetBold, + Color::Line, + Color::ResetLine, + Color::Strike, + Color::ResetStrike, + Color::Italic, + Color::Reset, + Color::White, + Color::BgBlack, + Color::Reset + ); + println!( + "{}Red\t{}Red{}\t{}Red{}\t{}Red{}\t{}Red{}\t{}{}Red{}", + Color::Red, + Color::Bold, + Color::ResetBold, + Color::Line, + Color::ResetLine, + Color::Strike, + Color::ResetStrike, + Color::Italic, + Color::Reset, + Color::White, + Color::BgRed, + Color::Reset + ); + println!( + "{}Green\t{}Green{}\t{}Green{}\t{}Green{}\t{}Red{}\t{}{}Green{}", + Color::Green, + Color::Bold, + Color::ResetBold, + Color::Line, + Color::ResetLine, + Color::Strike, + Color::ResetStrike, + Color::Italic, + Color::Reset, + Color::White, + Color::BgGreen, + Color::Reset + ); + println!( + "{}Yellow\t{}Yellow{}\t{}Yellow{}\t{}Yellow{}\t{}Red{}\t{}{}Yellow{}", + Color::Yellow, + Color::Bold, + Color::ResetBold, + Color::Line, + Color::ResetLine, + Color::Strike, + Color::ResetStrike, + Color::Italic, + Color::Reset, + Color::White, + Color::BgYellow, + Color::Reset + ); + println!( + "{}Blue\t{}Blue{}\t{}Blue{}\t{}Blue{}\t{}Red{}\t{}{}Blue{}", + Color::Blue, + Color::Bold, + Color::ResetBold, + Color::Line, + Color::ResetLine, + Color::Strike, + Color::ResetStrike, + Color::Italic, + Color::Reset, + Color::White, + Color::BgBlue, + Color::Reset + ); + println!( + "{}Purple\t{}Purple{}\t{}Purple{}\t{}Purple{}\t{}Red{}\t{}{}Purple{}", + Color::Purple, + Color::Bold, + Color::ResetBold, + Color::Line, + Color::ResetLine, + Color::Strike, + Color::ResetStrike, + Color::Italic, + Color::Reset, + Color::White, + Color::BgPurple, + Color::Reset + ); + println!( + "{}Cyan\t{}Cyan{}\t{}Cyan{}\t{}Cyan{}\t{}Red{}\t{}{}Cyan{}", + Color::Cyan, + Color::Bold, + Color::ResetBold, + Color::Line, + Color::ResetLine, + Color::Strike, + Color::ResetStrike, + Color::Italic, + Color::Reset, + Color::White, + Color::BgCyan, + Color::Reset + ); + println!( + "{}White\t{}White{}\t{}White{}\t{}White{}\t{}Red{}\t{}{}White{}", + Color::White, + Color::Bold, + Color::ResetBold, + Color::Line, + Color::ResetLine, + Color::Strike, + Color::ResetStrike, + Color::Italic, + Color::Reset, + Color::Black, + Color::BgWhite, + Color::Reset + ); +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..560294e --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,78 @@ +use libc::{STDOUT_FILENO, isatty}; + +use std::env::var_os; +use std::sync::LazyLock; + +pub static NO_COLOR: LazyLock = LazyLock::new(|| var_os("NO_COLOR").is_some()); + +pub static TTY: LazyLock = LazyLock::new(|| unsafe { isatty(STDOUT_FILENO) } != 0); + +pub enum Color { + Black, + Red, + Green, + Yellow, + Blue, + Purple, + Cyan, + White, + BgBlack, + BgRed, + BgGreen, + BgYellow, + BgBlue, + BgPurple, + BgCyan, + BgWhite, + Bold, + Italic, + Line, + Strike, + Reset, + ResetBold, + ResetItalic, + ResetLine, + ResetStrike, +} + +impl std::fmt::Display for Color { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.as_str()) + } +} + +impl Color { + fn as_str(&self) -> &'static str { + if *NO_COLOR || !*TTY { + "" + } else { + match self { + Self::Black => "\x1b[0;30m", + Self::Red => "\x1b[0;31m", + Self::Green => "\x1b[0;32m", + Self::Yellow => "\x1b[0;33m", + Self::Blue => "\x1b[0;34m", + Self::Purple => "\x1b[0;35m", + Self::Cyan => "\x1b[0;36m", + Self::White => "\x1b[0;37m", + Self::BgBlack => "\x1b[40m", + Self::BgRed => "\x1b[0;41m", + Self::BgGreen => "\x1b[42m", + Self::BgYellow => "\x1b[43m", + Self::BgBlue => "\x1b[44m", + Self::BgPurple => "\x1b[45m", + Self::BgCyan => "\x1b[46m", + Self::BgWhite => "\x1b[47m", + Self::Bold => "\x1b[1m", + Self::Italic => "\x1b[3m", + Self::Line => "\x1b[4m", + Self::Strike => "\x1b[9m", + Self::Reset => "\x1b[0m", + Self::ResetBold => "\x1b[22m", + Self::ResetItalic => "\x1b[23m", + Self::ResetLine => "\x1b[24m", + Self::ResetStrike => "\x1b[29m", + } + } + } +}