Skip to content

Commit

Permalink
Implement color_scheme on unix
Browse files Browse the repository at this point in the history
  • Loading branch information
bash committed Jan 20, 2024
1 parent 64258a3 commit 5d64d8e
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 20 deletions.
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.red >> 8, fg.green >> 8, fg.blue >> 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.red >> 8, fg.green >> 8, fg.blue >> 8);
Ok(())
}
53 changes: 33 additions & 20 deletions src/xterm.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::os::poll_read;
use crate::terminal::TerminalKind;
use crate::{Color, Error, QueryOptions, Result};
use crate::{Color, ColorScheme, Error, QueryOptions, Result};
use std::cmp::{max, min};
use std::str::from_utf8;
use std::time::{Duration, Instant};
Expand All @@ -9,30 +9,39 @@ use terminal_trx::{terminal, Transceive};
const MIN_TIMEOUT: Duration = Duration::from_millis(100);

pub(crate) fn foreground_color(options: QueryOptions) -> Result<Color> {
query_color(
"\x1b]10;?\x07",
"\x1b]10;",
options,
TerminalKind::from_env(),
)
execute_query(options, TerminalKind::from_env(), query_foreground_color)
}

pub(crate) fn background_color(options: QueryOptions) -> Result<Color> {
query_color(
"\x1b]11;?\x07",
"\x1b]11;",
options,
TerminalKind::from_env(),
)
execute_query(options, TerminalKind::from_env(), query_background_color)
}

pub(crate) fn color_scheme(options: QueryOptions) -> Result<ColorScheme> {
execute_query(options, TerminalKind::from_env(), |tty, timeout| {
let foreground = query_foreground_color(tty, timeout)?;
let background = query_background_color(tty, timeout)?;
Ok(ColorScheme {
foreground,
background,
})
})
}

fn query_foreground_color(tty: &mut dyn Transceive, timeout: Duration) -> Result<Color> {
query_color(tty, timeout, "\x1b]10;?\x07", "\x1b]10;")
}

fn query_background_color(tty: &mut dyn Transceive, timeout: Duration) -> Result<Color> {
query_color(tty, timeout, "\x1b]11;?\x07", "\x1b]11;")
}

fn query_color(
query: &str,
tty: &mut dyn Transceive,
timeout: Duration,
q: &str,
response_prefix: &str,
options: QueryOptions,
terminal: TerminalKind,
) -> Result<Color> {
query_color_raw(query, options, terminal).and_then(|r| parse_response(r, response_prefix))
query(tty, q, timeout).and_then(|(r, _)| parse_response(r, response_prefix))
}

fn parse_response(response: String, prefix: &str) -> Result<Color> {
Expand All @@ -47,7 +56,11 @@ fn parse_response(response: String, prefix: &str) -> Result<Color> {
.ok_or_else(|| Error::Parse(response))
}

fn query_color_raw(q: &str, options: QueryOptions, kind: TerminalKind) -> Result<String> {
fn execute_query<T>(
options: QueryOptions,
kind: TerminalKind,
f: impl FnOnce(&mut dyn Transceive, Duration) -> Result<T>,
) -> Result<T> {
if let TerminalKind::Unsupported = kind {
return Err(Error::UnsupportedTerminal);
}
Expand All @@ -58,14 +71,14 @@ fn query_color_raw(q: &str, options: QueryOptions, kind: TerminalKind) -> Result

match kind {
TerminalKind::Unsupported => unreachable!(),
TerminalKind::Supported => Ok(query(&mut tty, q, options.max_timeout)?.0),
TerminalKind::Supported => f(&mut tty, options.max_timeout),
TerminalKind::Unknown => {
// We use a well-supported sequence such as CSI C to measure the latency.
// this is to avoid mixing up the case where the terminal is slow to respond
// (e.g. because we're connected via SSH and have a slow connection)
// with the case where the terminal does not support querying for colors.
let timeout = estimate_timeout(&mut tty, options.max_timeout)?;
Ok(query(&mut tty, q, timeout)?.0)
f(&mut tty, timeout)
}
}
}
Expand Down

0 comments on commit 5d64d8e

Please sign in to comment.