]>
git.proxmox.com Git - rustc.git/blob - vendor/termion/src/color.rs
1 //! Color managemement.
6 //! use termion::color;
9 //! println!("{}Red", color::Fg(color::Red));
10 //! println!("{}Blue", color::Fg(color::Blue));
11 //! println!("{}Back again", color::Fg(color::Reset));
16 use raw
::CONTROL_SEQUENCE_TIMEOUT
;
17 use std
::io
::{self, Write, Read}
;
18 use std
::time
::{SystemTime, Duration}
;
19 use async
::async_stdin
;
24 /// Write the foreground version of this color.
25 fn write_fg(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
;
26 /// Write the background version of this color.
27 fn write_bg(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
;
30 macro_rules
! derive_color
{
31 ($doc
:expr
, $name
:ident
, $value
:expr
) => {
33 #[derive(Copy, Clone, Debug)]
36 impl Color
for $name
{
38 fn write_fg(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
39 write
!(f
, csi
!("38;5;", $value
, "m"))
43 fn write_bg(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
44 write
!(f
, csi
!("48;5;", $value
, "m"))
50 derive_color
!("Black.", Black
, "0");
51 derive_color
!("Red.", Red
, "1");
52 derive_color
!("Green.", Green
, "2");
53 derive_color
!("Yellow.", Yellow
, "3");
54 derive_color
!("Blue.", Blue
, "4");
55 derive_color
!("Magenta.", Magenta
, "5");
56 derive_color
!("Cyan.", Cyan
, "6");
57 derive_color
!("White.", White
, "7");
58 derive_color
!("High-intensity light black.", LightBlack
, "8");
59 derive_color
!("High-intensity light red.", LightRed
, "9");
60 derive_color
!("High-intensity light green.", LightGreen
, "10");
61 derive_color
!("High-intensity light yellow.", LightYellow
, "11");
62 derive_color
!("High-intensity light blue.", LightBlue
, "12");
63 derive_color
!("High-intensity light magenta.", LightMagenta
, "13");
64 derive_color
!("High-intensity light cyan.", LightCyan
, "14");
65 derive_color
!("High-intensity light white.", LightWhite
, "15");
67 impl<'a
> Color
for &'a Color
{
69 fn write_fg(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
74 fn write_bg(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
79 /// An arbitrary ANSI color value.
80 #[derive(Clone, Copy, Debug)]
81 pub struct AnsiValue(pub u8);
84 /// 216-color (r, g, b ≤ 5) RGB.
85 pub fn rgb(r
: u8, g
: u8, b
: u8) -> AnsiValue
{
87 "Red color fragment (r = {}) is out of bound. Make sure r ≤ 5.",
90 "Green color fragment (g = {}) is out of bound. Make sure g ≤ 5.",
93 "Blue color fragment (b = {}) is out of bound. Make sure b ≤ 5.",
96 AnsiValue(16 + 36 * r
+ 6 * g
+ b
)
101 /// There are 24 shades of gray.
102 pub fn grayscale(shade
: u8) -> AnsiValue
{
103 // Unfortunately, there are a little less than fifty shades.
104 debug_assert
!(shade
< 24,
105 "Grayscale out of bound (shade = {}). There are only 24 shades of \
109 AnsiValue(0xE8 + shade
)
113 impl Color
for AnsiValue
{
115 fn write_fg(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
116 write
!(f
, csi
!("38;5;{}m"), self.0)
120 fn write_bg(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
121 write
!(f
, csi
!("48;5;{}m"), self.0)
126 #[derive(Debug, Clone, Copy, PartialEq)]
127 pub struct Rgb(pub u8, pub u8, pub u8);
131 fn write_fg(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
132 write
!(f
, csi
!("38;2;{};{};{}m"), self.0, self.1, self.2)
136 fn write_bg(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
137 write
!(f
, csi
!("48;2;{};{};{}m"), self.0, self.1, self.2)
141 /// Reset colors to defaults.
142 #[derive(Debug, Clone, Copy)]
145 impl Color
for Reset
{
147 fn write_fg(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
148 write
!(f
, csi
!("39m"))
152 fn write_bg(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
153 write
!(f
, csi
!("49m"))
157 /// A foreground color.
158 #[derive(Debug, Clone, Copy)]
159 pub struct Fg
<C
: Color
>(pub C
);
161 impl<C
: Color
> fmt
::Display
for Fg
<C
> {
162 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
167 /// A background color.
168 #[derive(Debug, Clone, Copy)]
169 pub struct Bg
<C
: Color
>(pub C
);
171 impl<C
: Color
> fmt
::Display
for Bg
<C
> {
172 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
177 /// Types that allow detection of the colors they support.
178 pub trait DetectColors
{
179 /// How many ANSI colors are supported (from 8 to 256)?
181 /// Beware: the information given isn't authoritative, it's infered through escape codes or the
182 /// value of `TERM`, more colors may be available.
183 fn available_colors(&mut self) -> io
::Result
<u16>;
186 impl<W
: Write
> DetectColors
for W
{
187 fn available_colors(&mut self) -> io
::Result
<u16> {
188 let mut stdin
= async_stdin();
190 if detect_color(self, &mut stdin
, 0)?
{
191 // OSC 4 is supported, detect how many colors there are.
192 // Do a binary search of the last supported color.
196 while min
+ 1 < max
{
198 if detect_color(self, &mut stdin
, i
)?
{
206 // OSC 4 is not supported, trust TERM contents.
207 Ok(match env
::var_os("TERM") {
209 if val
.to_str().unwrap_or("").contains("256color") {
221 /// Detect a color using OSC 4.
222 fn detect_color(stdout
: &mut Write
, stdin
: &mut Read
, color
: u16) -> io
::Result
<bool
> {
223 // Is the color available?
224 // Use `ESC ] 4 ; color ; ? BEL`.
225 write
!(stdout
, "\x1B]4;{};?\x07", color
)?
;
228 let mut buf
: [u8; 1] = [0];
229 let mut total_read
= 0;
231 let timeout
= Duration
::from_millis(CONTROL_SEQUENCE_TIMEOUT
);
232 let now
= SystemTime
::now();
235 // Either consume all data up to bell or wait for a timeout.
236 while buf
[0] != bell
&& now
.elapsed().unwrap() < timeout
{
237 total_read
+= stdin
.read(&mut buf
)?
;
240 // If there was a response, the color is supported.