From b4dba962d63ab14e57d8896b484c298742f0aa70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tau=20G=C3=A4rtli?= Date: Fri, 27 Dec 2024 13:48:18 +0100 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20Add=20support=20for=20CLITHEME?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crates/terminal-colorsaurus/examples/theme.rs | 13 +++---- crates/terminal-colorsaurus/src/cli_theme.rs | 36 +++++++++++++++++++ crates/terminal-colorsaurus/src/lib.rs | 13 ++++++- 3 files changed, 52 insertions(+), 10 deletions(-) create mode 100644 crates/terminal-colorsaurus/src/cli_theme.rs diff --git a/crates/terminal-colorsaurus/examples/theme.rs b/crates/terminal-colorsaurus/examples/theme.rs index 3c025cf..8333b81 100644 --- a/crates/terminal-colorsaurus/examples/theme.rs +++ b/crates/terminal-colorsaurus/examples/theme.rs @@ -1,21 +1,16 @@ //! This example shows how to detect if the terminal uses //! a dark-on-light or a light-on-dark theme. -use terminal_colorsaurus::{color_palette, ColorScheme, Error, QueryOptions}; +use terminal_colorsaurus::{color_scheme, ColorScheme, Error, QueryOptions}; fn main() -> Result<(), display::DisplayAsDebug> { - let colors = color_palette(QueryOptions::default())?; - - let theme = match colors.color_scheme() { + let theme = color_scheme(QueryOptions::default())?; + let theme_name = match theme { ColorScheme::Dark => "dark", ColorScheme::Light => "light", }; - println!( - "{theme}, fg: {}, bg: {}", - colors.foreground.perceived_lightness(), - colors.background.perceived_lightness() - ); + println!("{theme_name}"); Ok(()) } diff --git a/crates/terminal-colorsaurus/src/cli_theme.rs b/crates/terminal-colorsaurus/src/cli_theme.rs new file mode 100644 index 0000000..cb2eed4 --- /dev/null +++ b/crates/terminal-colorsaurus/src/cli_theme.rs @@ -0,0 +1,36 @@ +//! Implements . + +use std::env; +use std::ffi::OsStr; +use std::os::unix::ffi::OsStrExt; + +pub(crate) fn cli_theme() -> Option { + let raw = env::var_os("CLITHEME")?; + let preference = parse_preference(&raw); + Some(CliTheme { preference }) +} + +fn parse_preference(raw: &OsStr) -> CliThemePreference { + if raw == "dark" || raw.as_bytes().starts_with(b"dark:") { + CliThemePreference::Dark + } else if raw == "light" || raw.as_bytes().starts_with(b"light:") { + CliThemePreference::Light + } else { + CliThemePreference::Auto + } +} + +#[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] +pub(crate) struct CliTheme { + pub(crate) preference: CliThemePreference, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] +#[allow(clippy::exhaustive_enums)] +pub(crate) enum CliThemePreference { + Dark, + Light, + #[default] + Auto, +} diff --git a/crates/terminal-colorsaurus/src/lib.rs b/crates/terminal-colorsaurus/src/lib.rs index fb8e888..84c4d2a 100644 --- a/crates/terminal-colorsaurus/src/lib.rs +++ b/crates/terminal-colorsaurus/src/lib.rs @@ -53,6 +53,7 @@ cfg_if! { mod xparsecolor; mod xterm; use xterm as imp; + mod cli_theme; } else { mod unsupported; use unsupported as imp; @@ -130,6 +131,7 @@ impl ColorPalette { /// Result used by this library. pub type Result = std::result::Result; +use cli_theme::CliThemePreference; pub use error::Error; /// Options to be used with [`foreground_color`] and [`background_color`]. @@ -172,10 +174,19 @@ impl Default for QueryOptions { } /// Detects if the terminal is dark or light. +/// +/// This function supports the [`CLITHEME`] environment variable +/// and skips detection if it is set to either **dark** or **light**. +/// +/// [`CLITHEME`]: https://wiki.tau.garden/cli-theme/ #[doc = include_str!("../doc/caveats.md")] #[doc(alias = "theme")] pub fn color_scheme(options: QueryOptions) -> Result { - color_palette(options).map(|p| p.color_scheme()) + match cli_theme::cli_theme().map(|t| t.preference) { + Some(CliThemePreference::Dark) => Ok(ColorScheme::Dark), + Some(CliThemePreference::Light) => Ok(ColorScheme::Light), + _ => color_palette(options).map(|p| p.color_scheme()), + } } /// Queries the terminal for it's color scheme (foreground and background color).