1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
use {
std::io::{self, Read, Write},
};
#[derive(thiserror::Error, Debug)]
pub enum TlError {
#[error("IO error: {0}")]
IO(#[from] std::io::Error),
#[error("UTF8 error: {0}")]
Utf8(#[from] std::str::Utf8Error),
#[error("Parse Int error: {0}")]
ParseInt(#[from] std::num::ParseIntError),
#[error("Wrong answer format: {0}")]
WrongFormat(String)
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Rgb {
pub r: u16,
pub g: u16,
pub b: u16,
}
impl Rgb {
pub fn new(r: u16, g: u16, b: u16) -> Self {
Self { r, g, b }
}
pub fn rp(self) -> f32 {
self.r as f32 / 65536f32
}
pub fn gp(self) -> f32 {
self.g as f32 / 65536f32
}
pub fn bp(self) -> f32 {
self.b as f32 / 65536f32
}
pub fn luma(self) -> f32 {
0.2627 * self.rp() + 0.6780 * self.gp() + 0.0593 * self.bp()
}
}
fn query_bg_color() -> Result<Rgb, TlError> {
let query = "\x1b]11;?\x07";
let stdin = io::stdin();
let mut stdin = stdin.lock();
let stdout = io::stdout();
let mut stdout = stdout.lock();
write!(stdout, "{}", query)?;
stdout.flush()?;
let mut buffer = [0;50];
let n = stdin.read(&mut buffer[..])?;
let s = std::str::from_utf8(&buffer[..n])?;
match s.strip_prefix("\x1b]11;rgb:") {
Some(raw_color) if raw_color.len() >= 14 => {
Ok(Rgb::new(
u16::from_str_radix(&raw_color[0..4], 16)?,
u16::from_str_radix(&raw_color[5..9], 16)?,
u16::from_str_radix(&raw_color[10..14], 16)?,
))
}
_ => Err(TlError::WrongFormat(s.to_string()))
}
}
pub fn bg_color() -> Result<Rgb, TlError> {
crossterm::terminal::enable_raw_mode()?;
let bg_color = query_bg_color();
crossterm::terminal::disable_raw_mode()?;
bg_color
}
pub fn luma() -> Result<f32, TlError> {
crossterm::terminal::enable_raw_mode()?;
let bg_color = query_bg_color();
crossterm::terminal::disable_raw_mode()?;
bg_color.map(|c| c.luma())
}