Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Polish #2

Merged
merged 16 commits into from
Jan 20, 2024
8 changes: 4 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,8 @@ jobs:
run: cargo build
- name: Check format
run: cargo fmt -- --check
- name: Run clippy
run: cargo clippy --all-targets --all-features -- --deny warnings
- name: Docs
run: cargo doc --features __docs
run: cargo doc --features docs,rgb
test:
strategy:
matrix:
Expand All @@ -32,4 +30,6 @@ jobs:
steps:
- uses: actions/checkout@v3
- name: Run tests
run: cargo test
run: cargo test --features __test_readme
- name: Run clippy
run: cargo clippy --all-targets --all-features -- --deny warnings
28 changes: 19 additions & 9 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

26 changes: 14 additions & 12 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,30 +1,32 @@
[package]
name = "term-color"
name = "terminal-colorsaurus"
description = "Determines the background and foreground color of the terminal"
readme = "readme.md"
repository = "https://github.com/bash/terminal-colorsaurus"
categories = ["command-line-interface"]
license = "MIT OR Apache-2.0"
version = "0.1.0"
edition = "2021"
license = "MIT or Apache-2.0"
rust-version = "1.70.0"
exclude = [".github", ".gitignore"]

[dependencies]
thiserror = "1.0.56"
rgb = { version = "0.8.37", optional = true }

[target.'cfg(unix)'.dependencies]
libc = "0.2.151"
mio = { version = "0.8.10", features = ["os-poll", "os-ext"], default-features = false }
terminal-trx = { git = "https://github.com/bash/terminal-trx" }
terminal-trx = "0.1.0"

[target.'cfg(windows)'.dependencies]
terminal-trx = { git = "https://github.com/bash/terminal-trx" }
windows-sys = { version = "0.52.0", features = ["Win32_System_Threading", "Win32_System_Console", "Win32_Foundation"] }
terminal-trx = "0.1.0"
windows-sys = { version = "0.52.0", features = ["Win32_System_Console", "Win32_Foundation"] }

[features]
__docs = []
docs = []
__test_readme = []

[package.metadata.docs.rs]
features = ["__docs"]

[workspace]
members = [
"termtheme"
]
features = ["docs", "rgb"]
rustdoc-args = ["--cfg", "docsrs"]
2 changes: 1 addition & 1 deletion doc/terminal-survey.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Terminal Survey
A list of terminals that were tested for support of `CSI c` and `OSC 10` / `OSC 11`.

| Terminal | `CSI c` | fg | bg | mean latency | `TERM` | `TERM_PROGRAM` | `TERM_PROGRAM_VERSION` | Version Tested |
|-----------------------|---------|----------------------|----------------------|--------------|------------------|-------------------|------------------------|----------------------------|
Expand Down
8 changes: 8 additions & 0 deletions examples/bg.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
use std::error::Error;
use terminal_colorsaurus::{background_color, QueryOptions};

fn main() -> Result<(), Box<dyn Error>> {
let fg = background_color(QueryOptions::default()).unwrap();
println!("rgb({}, {}, {})", fg.r >> 8, fg.g >> 8, fg.b >> 8);
Ok(())
}
8 changes: 8 additions & 0 deletions examples/fg.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
use std::error::Error;
use terminal_colorsaurus::{foreground_color, QueryOptions};

fn main() -> Result<(), Box<dyn Error>> {
let fg = foreground_color(QueryOptions::default()).unwrap();
println!("rgb({}, {}, {})", fg.r >> 8, fg.g >> 8, fg.b >> 8);
Ok(())
}
20 changes: 20 additions & 0 deletions examples/theme.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
use std::error::Error;
use terminal_colorsaurus::{color_scheme, QueryOptions};

fn main() -> Result<(), Box<dyn Error>> {
let colors = color_scheme(QueryOptions::default())?;

let theme = if colors.is_light_on_dark() {
"light on dark"
} else {
"dark on light"
};

println!(
"{theme}, fg: {}, bg: {}",
colors.foreground.perceived_lightness(),
colors.background.perceived_lightness()
);

Ok(())
}
10 changes: 5 additions & 5 deletions readme.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# term-color
# terminal-colorsaurus 🦕
Determines the background and foreground color of the terminal
using the `OSC 10` and `OSC 11` terminal sequence.
On Windows, the colors are queried using the Win32 Console API.
Expand All @@ -7,10 +7,10 @@ This is useful for answering the question *"Is this terminal dark or light?"*.

## Example
```rust,no_run
use term_color::{background_color, QueryOptions};
let bg = background_color(QueryOptions::default());
// Perceived lightness is a value between 0 (black) and 100 (white)
let is_light = bg.map(|c| c.perceived_lightness() >= 50).unwrap_or_default();
use terminal_colorsaurus::{color_scheme, QueryOptions};

let colors = color_scheme(QueryOptions::default()).unwrap();
dbg!(colors.is_dark_on_light());
```

## Wishlist
Expand Down
58 changes: 40 additions & 18 deletions src/color.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
/// An RGB color with 16 bits per channel.
#[derive(Debug, Clone, Default, Eq, PartialEq)]
pub struct Color {
pub red: u16,
pub green: u16,
pub blue: u16,
pub r: u16,
pub g: u16,
pub b: u16,
}

impl Color {
/// The perceived lightness of the color
/// as a value between `0` (black) and `100` (white)
/// where `50` is the perceptual "middle grey".
/// ```
/// # use term_color::Color;
/// # use terminal_colorsaurus::Color;
/// # let color = Color::default();
/// let is_dark = color.perceived_lightness() <= 50;
/// ```
Expand All @@ -20,24 +20,46 @@ impl Color {
}
}

#[cfg(feature = "rgb")]
impl From<Color> for rgb::RGB16 {
fn from(value: Color) -> Self {
rgb::RGB16 {
r: value.r,
g: value.g,
b: value.b,
}
}
}

#[cfg(feature = "rgb")]
impl From<rgb::RGB16> for Color {
fn from(value: rgb::RGB16) -> Self {
Color {
r: value.r,
g: value.g,
b: value.b,
}
}
}

impl Color {
/// Parses an X11 color (see `man xparsecolor`).
#[cfg(unix)]
pub(crate) fn parse_x11(input: &str) -> Option<Self> {
let raw_parts = input.strip_prefix("rgb:")?;
let mut parts = raw_parts.split('/');
let red = parse_channel(parts.next()?)?;
let green = parse_channel(parts.next()?)?;
let blue = parse_channel(parts.next()?)?;
Some(Color { red, green, blue })
let r = parse_channel(parts.next()?)?;
let g = parse_channel(parts.next()?)?;
let b = parse_channel(parts.next()?)?;
Some(Color { r, g, b })
}

#[cfg(windows)]
pub(crate) fn from_8bit(red: u8, green: u8, blue: u8) -> Color {
pub(crate) fn from_8bit(r: u8, g: u8, b: u8) -> Color {
Color {
red: (red as u16) << 8,
green: (green as u16) << 8,
blue: (blue as u16) << 8,
r: (r as u16) << 8,
g: (g as u16) << 8,
b: (b as u16) << 8,
}
}
}
Expand Down Expand Up @@ -67,9 +89,9 @@ fn srgb_to_lin(channel: f64) -> f64 {

// Luminance (Y)
fn luminance(color: &Color) -> f64 {
let r = color.red as f64 / u16::MAX as f64;
let g = color.green as f64 / u16::MAX as f64;
let b = color.blue as f64 / u16::MAX as f64;
let r = color.r as f64 / u16::MAX as f64;
let g = color.g as f64 / u16::MAX as f64;
let b = color.b as f64 / u16::MAX as f64;
0.2126 * srgb_to_lin(r) + 0.7152 * srgb_to_lin(g) + 0.0722 * srgb_to_lin(b)
}

Expand All @@ -95,9 +117,9 @@ mod tests {
#[test]
fn white_has_perceived_lightness_100() {
let black = Color {
red: u16::MAX,
green: u16::MAX,
blue: u16::MAX,
r: u16::MAX,
g: u16::MAX,
b: u16::MAX,
};
assert_eq!(100, black.perceived_lightness())
}
Expand Down
Loading