From a6b9dadff5971b60ec2556d452c4eedc82614ab6 Mon Sep 17 00:00:00 2001 From: Rain Date: Wed, 11 Oct 2023 14:24:01 -0700 Subject: [PATCH 1/6] Revert "build(deps): update supports-color requirement from 1.3 to 2.0" This reverts commit abb63524634712d3c562ac0685a93f5e19ac5130. This is done because the update was a breaking change. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 315217c..3933d98 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,4 +29,4 @@ supports-colors = ["supports-color"] alloc = [] [dependencies] -supports-color = { version = "2.0", optional = true } +supports-color = { version = "1.3", optional = true } From 26c631bf30b7ca5242e69a9c73acb50bbb0d7b9f Mon Sep 17 00:00:00 2001 From: Rain Date: Wed, 11 Oct 2023 14:52:27 -0700 Subject: [PATCH 2/6] Add a way to support both v1 and v2 of supports-colors Also deprecate supports-color v1 to the greatest extent possible. Fixes #114. --- Cargo.toml | 2 + src/lib.rs | 49 ++++++++++++++++++------ src/overrides.rs | 15 ++++---- src/supports_colors.rs | 85 ++++++++++++++++++++++++++++++++++++++---- 4 files changed, 124 insertions(+), 27 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 3933d98..ed729a2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,7 +26,9 @@ required-features = ["supports-colors"] [features] supports-colors = ["supports-color"] +supports-colors-2 = ["supports-color-2"] alloc = [] [dependencies] supports-color = { version = "1.3", optional = true } +supports-color-2 = { package = "supports-color", version = "2.0", optional = true } diff --git a/src/lib.rs b/src/lib.rs index 2796755..6894998 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -85,10 +85,10 @@ mod dyn_styles; mod styled_list; pub mod styles; -#[cfg(feature = "supports-colors")] +#[cfg(any(feature = "supports-colors", feature = "supports-colors-2"))] mod overrides; -#[cfg(feature = "supports-colors")] +#[cfg(any(feature = "supports-colors", feature = "supports-colors-2"))] pub(crate) use overrides::OVERRIDE; use core::fmt; @@ -437,41 +437,66 @@ pub trait OwoColorize: Sized { /// supports at least basic ANSI colors, allowing you to conditionally apply /// given styles/colors. /// - /// Requires the `supports-colors` feature. + /// Requires the `supports-colors-2` feature, or the deprecated `supports-colors` feature. /// /// ```rust - /// use owo_colors::{OwoColorize, Stream}; + /// use owo_colors::{OutputStream, OwoColorize}; /// /// println!( /// "{}", /// "woah! error! if this terminal supports colors, it's blue" - /// .if_supports_color(Stream::Stdout, |text| text.bright_blue()) + /// .if_supports_color(OutputStream::Stdout, |text| text.bright_blue()) /// ); /// ``` + /// + /// This function also accepts `supports_color` version 2's `Stream`, and also the deprecated + /// `supports_color` version 1's `Stream`. + /// + /// ```rust + /// use owo_colors::OwoColorize; + /// #[cfg(feature = "supports-colors-2")] + /// use supports_color_2::Stream; + /// #[cfg(all(feature = "supports-colors", not(feature = "supports-colors-2")))] + /// use supports_color::Stream; + /// + /// println!( + /// "{}", + /// "woah! error! if this terminal supports colors, it's blue" + /// .if_supports_color(Stream::Stdout, |text| text.bright_blue()) + /// ); #[must_use] - #[cfg(feature = "supports-colors")] + #[cfg(any(feature = "supports-colors", feature = "supports-colors-2"))] fn if_supports_color<'a, Out, ApplyFn>( &'a self, - stream: Stream, + stream: impl Into, apply: ApplyFn, ) -> SupportsColorsDisplay<'a, Self, Out, ApplyFn> where ApplyFn: Fn(&'a Self) -> Out, { - SupportsColorsDisplay(self, apply, stream) + SupportsColorsDisplay(self, apply, stream.into()) } } -#[cfg(feature = "supports-colors")] +#[cfg(any(feature = "supports-colors", feature = "supports-colors-2"))] mod supports_colors; -#[cfg(feature = "supports-colors")] +#[cfg(any(feature = "supports-colors", feature = "supports-colors-2"))] pub use { overrides::{set_override, unset_override, with_override}, - supports_color::Stream, - supports_colors::SupportsColorsDisplay, + supports_colors::{OutputStream, SupportsColorsDisplay}, }; +/// Exports cannot be deprecated yet: https://github.com/rust-lang/rust/issues/30827 but this is put +/// in here to enable deprecations as soon as that is enabled. +#[cfg(feature = "supports-colors")] +#[deprecated( + since = "3.7.0", + note = "Use supports-colors-2 and OutputStream instead of Stream" +)] +#[doc(no_inline)] +pub use supports_color::Stream; + pub use colors::{ ansi_colors::AnsiColors, css::dynamic::CssColors, dynamic::Rgb, xterm::dynamic::XtermColors, }; diff --git a/src/overrides.rs b/src/overrides.rs index f5d31af..d6287e8 100644 --- a/src/overrides.rs +++ b/src/overrides.rs @@ -10,21 +10,20 @@ use core::sync::atomic::{AtomicU8, Ordering}; /// override the supported color set, without impacting previous configurations. /// /// ``` -/// # use supports_color::Stream; -/// # use owo_colors::{OwoColorize, set_override, unset_override, with_override}; +/// # use owo_colors::{OutputStream, OwoColorize, set_override, unset_override, with_override}; /// # use owo_colors::colors::Black; /// # /// set_override(false); -/// assert_eq!("example".if_supports_color(Stream::Stdout, |value| value.bg::()).to_string(), "example"); +/// assert_eq!("example".if_supports_color(OutputStream::Stdout, |value| value.bg::()).to_string(), "example"); /// /// with_override(true, || { -/// assert_eq!("example".if_supports_color(Stream::Stdout, |value| value.bg::()).to_string(), "\x1b[40mexample\x1b[49m"); +/// assert_eq!("example".if_supports_color(OutputStream::Stdout, |value| value.bg::()).to_string(), "\x1b[40mexample\x1b[49m"); /// }); /// -/// assert_eq!("example".if_supports_color(Stream::Stdout, |value| value.bg::()).to_string(), "example"); +/// assert_eq!("example".if_supports_color(OutputStream::Stdout, |value| value.bg::()).to_string(), "example"); /// # unset_override() // make sure that other doc tests are not impacted /// ``` -#[cfg(feature = "supports-colors")] +#[cfg(any(feature = "supports-colors", feature = "supports-colors-2"))] pub fn with_override T>(enabled: bool, f: F) -> T { let previous = OVERRIDE.inner(); OVERRIDE.set_force(enabled); @@ -48,7 +47,7 @@ pub fn with_override T>(enabled: bool, f: F) -> T { /// /// This behavior can be disabled using [`unset_override`], allowing /// `owo-colors` to return to inferring if colors are supported. -#[cfg(feature = "supports-colors")] +#[cfg(any(feature = "supports-colors", feature = "supports-colors-2"))] pub fn set_override(enabled: bool) { OVERRIDE.set_force(enabled); } @@ -59,7 +58,7 @@ pub fn set_override(enabled: bool) { /// supports colors. /// /// This override can be set using [`set_override`]. -#[cfg(feature = "supports-colors")] +#[cfg(any(feature = "supports-colors", feature = "supports-colors-2"))] pub fn unset_override() { OVERRIDE.unset(); } diff --git a/src/supports_colors.rs b/src/supports_colors.rs index 5dbcac0..3103447 100644 --- a/src/supports_colors.rs +++ b/src/supports_colors.rs @@ -1,12 +1,58 @@ use core::fmt; +mod private { + pub(super) trait Sealed {} +} + +/// A possible stream source. +/// +/// This can be used +#[derive(Clone, Copy, Debug)] +pub enum OutputStream { + /// Standard output. + Stdout, + + /// Standard error. + Stderr, + + /// Standard input. Only used to retain compatibility with supports-colors v1. + #[doc(hidden)] + #[deprecated( + since = "3.7.0", + note = "This is only used to retain compatibility with supports-colors v1." + )] + Stdin, +} + #[cfg(feature = "supports-colors")] +impl From for OutputStream { + fn from(stream: supports_color::Stream) -> Self { + match stream { + supports_color::Stream::Stdout => OutputStream::Stdout, + supports_color::Stream::Stderr => OutputStream::Stderr, + #[allow(deprecated)] + supports_color::Stream::Stdin => OutputStream::Stdin, + } + } +} + +#[cfg(feature = "supports-colors-2")] +impl From for OutputStream { + fn from(stream: supports_color_2::Stream) -> Self { + match stream { + supports_color_2::Stream::Stdout => OutputStream::Stdout, + supports_color_2::Stream::Stderr => OutputStream::Stderr, + } + } +} + +#[cfg(any(feature = "supports-colors", feature = "supports-colors-2"))] /// A display wrapper which applies a transformation based on if the given stream supports /// colored terminal output pub struct SupportsColorsDisplay<'a, InVal, Out, ApplyFn>( pub(crate) &'a InVal, pub(crate) ApplyFn, - pub(crate) supports_color::Stream, + pub(crate) OutputStream, ) where InVal: ?Sized, @@ -25,12 +71,7 @@ macro_rules! impl_fmt_for { #[inline(always)] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let (force_enabled, force_disabled) = OVERRIDE.is_force_enabled_or_disabled(); - if force_enabled || ( - supports_color::on_cached(self.2) - .map(|level| level.has_basic) - .unwrap_or(false) - && !force_disabled - ) { + if force_enabled || (on_cached(self.2) && !force_disabled) { ::fmt(&self.1(self.0), f) } else { ::fmt(self.0, f) @@ -41,6 +82,36 @@ macro_rules! impl_fmt_for { }; } +/// Use supports-colors v2 if it is enabled. +#[cfg(feature = "supports-colors-2")] +fn on_cached(stream: OutputStream) -> bool { + let stream = match stream { + OutputStream::Stdout => supports_color_2::Stream::Stdout, + OutputStream::Stderr => supports_color_2::Stream::Stderr, + #[allow(deprecated)] + OutputStream::Stdin => { + panic!("stdin is not supported if supports-colors-2 is enabled") + } + }; + supports_color_2::on_cached(stream) + .map(|level| level.has_basic) + .unwrap_or(false) +} + +/// Use supports-colors v1 if v2 is not enabled. +#[cfg(all(feature = "supports-color", not(feature = "supports-colors-2")))] +fn on_cached(stream: OutputStream) -> bool { + let stream = match stream { + OutputStream::Stdout => supports_color::Stream::Stdout, + OutputStream::Stderr => supports_color::Stream::Stderr, + #[allow(deprecated)] + OutputStream::Stdin => supports_color::Stream::Stdin, + }; + supports_color::on_cached(stream) + .map(|level| level.has_basic) + .unwrap_or(false) +} + impl_fmt_for! { fmt::Display, fmt::Debug, From 64f11abefd92233543e60257d8a500006a2f39cc Mon Sep 17 00:00:00 2001 From: Rain Date: Wed, 11 Oct 2023 15:02:53 -0700 Subject: [PATCH 3/6] Run tests with feature-powerset Use cargo-hack to run all possible combinations of features. --- .github/workflows/ci.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c717a20..551928a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -80,3 +80,12 @@ jobs: with: command: test args: --all-features --example all_xterm_colors --example colors --example dyn_colors --example override --example custom_colors --example extra_colors --example supports_color + + - name: Install cargo-hack + uses: taiki-e/install-action@cargo-hack + + - name: Run tests with feature powerset + # Note: you might think that we can also pass in `--exclude-all-features` here, but that + # isn't the case because if you pass in a --example, it doesn't run doctests. The below + # expression will run doctests as well. + run: cargo hack --feature-powerset From e0e4d90cf64d4fa9a33baebcf0d40f3f5ebd8307 Mon Sep 17 00:00:00 2001 From: Dhruv Bhanushali Date: Sun, 25 Jun 2023 08:48:57 +0400 Subject: [PATCH 4/6] Fix typo in `Color` trait documentation Fix a typo where `BgColorDisplay` was accidentally spelled as 'BgCBgColorDisplay'. --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 6894998..a747a1a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -95,7 +95,7 @@ use core::fmt; use core::marker::PhantomData; /// A trait for describing a type which can be used with [`FgColorDisplay`](FgColorDisplay) or -/// [`BgCBgColorDisplay`](BgColorDisplay) +/// [`BgColorDisplay`](BgColorDisplay) pub trait Color { /// The ANSI format code for setting this color as the foreground const ANSI_FG: &'static str; From 709d8703b91f295bf1d594cef8c3328d1068a3a8 Mon Sep 17 00:00:00 2001 From: squoop Date: Thu, 30 Mar 2023 12:26:31 +0100 Subject: [PATCH 5/6] Generate byte digits lookup table. Generates the byte digits lookup table (at compile-time) instead of storing it inline in the code. --- src/colors/custom.rs | 275 +++---------------------------------------- 1 file changed, 17 insertions(+), 258 deletions(-) diff --git a/src/colors/custom.rs b/src/colors/custom.rs index ecfb890..2e4c7ea 100644 --- a/src/colors/custom.rs +++ b/src/colors/custom.rs @@ -1,263 +1,22 @@ use crate::Color; -const U8_TO_STR: [[u8; 3]; 256] = [ - [48, 48, 48], - [48, 48, 49], - [48, 48, 50], - [48, 48, 51], - [48, 48, 52], - [48, 48, 53], - [48, 48, 54], - [48, 48, 55], - [48, 48, 56], - [48, 48, 57], - [48, 49, 48], - [48, 49, 49], - [48, 49, 50], - [48, 49, 51], - [48, 49, 52], - [48, 49, 53], - [48, 49, 54], - [48, 49, 55], - [48, 49, 56], - [48, 49, 57], - [48, 50, 48], - [48, 50, 49], - [48, 50, 50], - [48, 50, 51], - [48, 50, 52], - [48, 50, 53], - [48, 50, 54], - [48, 50, 55], - [48, 50, 56], - [48, 50, 57], - [48, 51, 48], - [48, 51, 49], - [48, 51, 50], - [48, 51, 51], - [48, 51, 52], - [48, 51, 53], - [48, 51, 54], - [48, 51, 55], - [48, 51, 56], - [48, 51, 57], - [48, 52, 48], - [48, 52, 49], - [48, 52, 50], - [48, 52, 51], - [48, 52, 52], - [48, 52, 53], - [48, 52, 54], - [48, 52, 55], - [48, 52, 56], - [48, 52, 57], - [48, 53, 48], - [48, 53, 49], - [48, 53, 50], - [48, 53, 51], - [48, 53, 52], - [48, 53, 53], - [48, 53, 54], - [48, 53, 55], - [48, 53, 56], - [48, 53, 57], - [48, 54, 48], - [48, 54, 49], - [48, 54, 50], - [48, 54, 51], - [48, 54, 52], - [48, 54, 53], - [48, 54, 54], - [48, 54, 55], - [48, 54, 56], - [48, 54, 57], - [48, 55, 48], - [48, 55, 49], - [48, 55, 50], - [48, 55, 51], - [48, 55, 52], - [48, 55, 53], - [48, 55, 54], - [48, 55, 55], - [48, 55, 56], - [48, 55, 57], - [48, 56, 48], - [48, 56, 49], - [48, 56, 50], - [48, 56, 51], - [48, 56, 52], - [48, 56, 53], - [48, 56, 54], - [48, 56, 55], - [48, 56, 56], - [48, 56, 57], - [48, 57, 48], - [48, 57, 49], - [48, 57, 50], - [48, 57, 51], - [48, 57, 52], - [48, 57, 53], - [48, 57, 54], - [48, 57, 55], - [48, 57, 56], - [48, 57, 57], - [49, 48, 48], - [49, 48, 49], - [49, 48, 50], - [49, 48, 51], - [49, 48, 52], - [49, 48, 53], - [49, 48, 54], - [49, 48, 55], - [49, 48, 56], - [49, 48, 57], - [49, 49, 48], - [49, 49, 49], - [49, 49, 50], - [49, 49, 51], - [49, 49, 52], - [49, 49, 53], - [49, 49, 54], - [49, 49, 55], - [49, 49, 56], - [49, 49, 57], - [49, 50, 48], - [49, 50, 49], - [49, 50, 50], - [49, 50, 51], - [49, 50, 52], - [49, 50, 53], - [49, 50, 54], - [49, 50, 55], - [49, 50, 56], - [49, 50, 57], - [49, 51, 48], - [49, 51, 49], - [49, 51, 50], - [49, 51, 51], - [49, 51, 52], - [49, 51, 53], - [49, 51, 54], - [49, 51, 55], - [49, 51, 56], - [49, 51, 57], - [49, 52, 48], - [49, 52, 49], - [49, 52, 50], - [49, 52, 51], - [49, 52, 52], - [49, 52, 53], - [49, 52, 54], - [49, 52, 55], - [49, 52, 56], - [49, 52, 57], - [49, 53, 48], - [49, 53, 49], - [49, 53, 50], - [49, 53, 51], - [49, 53, 52], - [49, 53, 53], - [49, 53, 54], - [49, 53, 55], - [49, 53, 56], - [49, 53, 57], - [49, 54, 48], - [49, 54, 49], - [49, 54, 50], - [49, 54, 51], - [49, 54, 52], - [49, 54, 53], - [49, 54, 54], - [49, 54, 55], - [49, 54, 56], - [49, 54, 57], - [49, 55, 48], - [49, 55, 49], - [49, 55, 50], - [49, 55, 51], - [49, 55, 52], - [49, 55, 53], - [49, 55, 54], - [49, 55, 55], - [49, 55, 56], - [49, 55, 57], - [49, 56, 48], - [49, 56, 49], - [49, 56, 50], - [49, 56, 51], - [49, 56, 52], - [49, 56, 53], - [49, 56, 54], - [49, 56, 55], - [49, 56, 56], - [49, 56, 57], - [49, 57, 48], - [49, 57, 49], - [49, 57, 50], - [49, 57, 51], - [49, 57, 52], - [49, 57, 53], - [49, 57, 54], - [49, 57, 55], - [49, 57, 56], - [49, 57, 57], - [50, 48, 48], - [50, 48, 49], - [50, 48, 50], - [50, 48, 51], - [50, 48, 52], - [50, 48, 53], - [50, 48, 54], - [50, 48, 55], - [50, 48, 56], - [50, 48, 57], - [50, 49, 48], - [50, 49, 49], - [50, 49, 50], - [50, 49, 51], - [50, 49, 52], - [50, 49, 53], - [50, 49, 54], - [50, 49, 55], - [50, 49, 56], - [50, 49, 57], - [50, 50, 48], - [50, 50, 49], - [50, 50, 50], - [50, 50, 51], - [50, 50, 52], - [50, 50, 53], - [50, 50, 54], - [50, 50, 55], - [50, 50, 56], - [50, 50, 57], - [50, 51, 48], - [50, 51, 49], - [50, 51, 50], - [50, 51, 51], - [50, 51, 52], - [50, 51, 53], - [50, 51, 54], - [50, 51, 55], - [50, 51, 56], - [50, 51, 57], - [50, 52, 48], - [50, 52, 49], - [50, 52, 50], - [50, 52, 51], - [50, 52, 52], - [50, 52, 53], - [50, 52, 54], - [50, 52, 55], - [50, 52, 56], - [50, 52, 57], - [50, 53, 48], - [50, 53, 49], - [50, 53, 50], - [50, 53, 51], - [50, 53, 52], - [50, 53, 53], -]; +const U8_TO_STR: [[u8; 3]; 256] = generate_lookup(); + +const fn generate_lookup() -> [[u8; 3]; 256] { + let mut table = [[0, 0, 0]; 256]; + + let mut i = 0; + while i < 256 { + table[i] = [ + b'0' + (i / 100) as u8, + b'0' + (i / 10 % 10) as u8, + b'0' + (i % 10) as u8, + ]; + i += 1; + } + + table +} const fn rgb_to_ansi(r: u8, g: u8, b: u8, is_fg: bool) -> [u8; 19] { let mut buf = if is_fg { From fd770669217b77e0b43b2d34affd518d5c12d9cf Mon Sep 17 00:00:00 2001 From: LingMan Date: Wed, 15 Mar 2023 19:54:27 +0100 Subject: [PATCH 6/6] Raise MSRV to 1.56 The `banners` example already requires Rust 1.55 to build. Going one version further to 1.56 silences the (harmless) warning about the `rust-version` key in the Cargo.toml being unsupported and unlocks Rust 2021. The example could instead be fixed to build with Rust 1.51, but don't bother and just bump the MSRV since 1.56 is already one and a half years old at this point. --- .github/workflows/ci.yml | 2 +- Cargo.toml | 2 +- README.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 551928a..1295bdb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -42,7 +42,7 @@ jobs: fail-fast: false matrix: rust: - - 1.51.0 + - 1.56.0 - stable - nightly steps: diff --git a/Cargo.toml b/Cargo.toml index ed729a2..793e9fe 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "owo-colors" version = "3.6.0" -rust-version = "1.51" +rust-version = "1.56" authors = ["jam1garner <8260240+jam1garner@users.noreply.github.com>"] edition = "2018" documentation = "https://docs.rs/owo-colors" diff --git a/README.md b/README.md index 5a339f2..cda9176 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![Current Crates.io Version](https://img.shields.io/crates/v/owo-colors.svg)](https://crates.io/crates/owo-colors) [![docs-rs](https://docs.rs/owo-colors/badge.svg)](https://docs.rs/owo-colors) -![MSRV 1.51+](https://img.shields.io/badge/rustc-1.51+-blue.svg) +![MSRV 1.56+](https://img.shields.io/badge/rustc-1.56+-blue.svg) ![Downloads](https://img.shields.io/crates/d/owo-colors) A zero-allocation no_std-compatible zero-cost way to add color to your Rust