1 use style
::{Colour, Style}
;
8 // ---- generating ANSI codes ----
12 /// Write any bytes that go *before* a piece of text to the given writer.
13 fn write_prefix
<W
: AnyWrite
+ ?Sized
>(&self, f
: &mut W
) -> Result
<(), W
::Error
> {
15 // If there are actually no styles here, then don’t write *any* codes
16 // as the prefix. An empty ANSI code may not affect the terminal
17 // output at all, but a user may just want a code-free string.
22 // Write the codes’ prefix, then write numbers, separated by
23 // semicolons, for each text style we want to apply.
25 let mut written_anything
= false;
28 let mut write_char
= |c
| {
29 if written_anything { write!(f, ";")?; }
30 written_anything
= true;
35 if self.is_bold { write_char('1')? }
36 if self.is_dimmed { write_char('2')? }
37 if self.is_italic { write_char('3')? }
38 if self.is_underline { write_char('4')? }
39 if self.is_blink { write_char('5')? }
40 if self.is_reverse { write_char('7')? }
41 if self.is_hidden { write_char('8')? }
42 if self.is_strikethrough { write_char('9')? }
45 // The foreground and background colours, if specified, need to be
46 // handled specially because the number codes are more complicated.
47 // (see `write_background_code` and `write_foreground_code`)
48 if let Some(bg
) = self.background
{
49 if written_anything { write!(f, ";")?; }
50 written_anything
= true;
51 bg
.write_background_code(f
)?
;
54 if let Some(fg
) = self.foreground
{
55 if written_anything { write!(f, ";")?; }
56 fg
.write_foreground_code(f
)?
;
59 // All the codes end with an `m`, because reasons.
65 /// Write any bytes that go *after* a piece of text to the given writer.
66 fn write_suffix
<W
: AnyWrite
+ ?Sized
>(&self, f
: &mut W
) -> Result
<(), W
::Error
> {
71 write
!(f
, "{}", RESET
)
77 /// The code to send to reset all styles and return to `Style::default()`.
78 pub static RESET
: &str = "\x1B[0m";
83 fn write_foreground_code
<W
: AnyWrite
+ ?Sized
>(&self, f
: &mut W
) -> Result
<(), W
::Error
> {
85 Colour
::Black
=> write
!(f
, "30"),
86 Colour
::Red
=> write
!(f
, "31"),
87 Colour
::Green
=> write
!(f
, "32"),
88 Colour
::Yellow
=> write
!(f
, "33"),
89 Colour
::Blue
=> write
!(f
, "34"),
90 Colour
::Purple
=> write
!(f
, "35"),
91 Colour
::Cyan
=> write
!(f
, "36"),
92 Colour
::White
=> write
!(f
, "37"),
93 Colour
::Fixed(num
) => write
!(f
, "38;5;{}", &num
),
94 Colour
::RGB(r
,g
,b
) => write
!(f
, "38;2;{};{};{}", &r
, &g
, &b
),
98 fn write_background_code
<W
: AnyWrite
+ ?Sized
>(&self, f
: &mut W
) -> Result
<(), W
::Error
> {
100 Colour
::Black
=> write
!(f
, "40"),
101 Colour
::Red
=> write
!(f
, "41"),
102 Colour
::Green
=> write
!(f
, "42"),
103 Colour
::Yellow
=> write
!(f
, "43"),
104 Colour
::Blue
=> write
!(f
, "44"),
105 Colour
::Purple
=> write
!(f
, "45"),
106 Colour
::Cyan
=> write
!(f
, "46"),
107 Colour
::White
=> write
!(f
, "47"),
108 Colour
::Fixed(num
) => write
!(f
, "48;5;{}", &num
),
109 Colour
::RGB(r
,g
,b
) => write
!(f
, "48;2;{};{};{}", &r
, &g
, &b
),
115 /// Like `ANSIString`, but only displays the style prefix.
117 /// This type implements the `Display` trait, meaning it can be written to a
118 /// `std::fmt` formatting without doing any extra allocation, and written to a
119 /// string with the `.to_string()` method. For examples, see
120 /// [`Style::prefix`](struct.Style.html#method.prefix).
121 #[derive(Clone, Copy, Debug)]
122 pub struct Prefix(Style
);
124 /// Like `ANSIString`, but only displays the difference between two
127 /// This type implements the `Display` trait, meaning it can be written to a
128 /// `std::fmt` formatting without doing any extra allocation, and written to a
129 /// string with the `.to_string()` method. For examples, see
130 /// [`Style::infix`](struct.Style.html#method.infix).
131 #[derive(Clone, Copy, Debug)]
132 pub struct Infix(Style
, Style
);
134 /// Like `ANSIString`, but only displays the style suffix.
136 /// This type implements the `Display` trait, meaning it can be written to a
137 /// `std::fmt` formatting without doing any extra allocation, and written to a
138 /// string with the `.to_string()` method. For examples, see
139 /// [`Style::suffix`](struct.Style.html#method.suffix).
140 #[derive(Clone, Copy, Debug)]
141 pub struct Suffix(Style
);
146 /// The prefix bytes for this style. These are the bytes that tell the
147 /// terminal to use a different colour or font style.
152 /// use ansi_term::{Style, Colour::Blue};
154 /// let style = Style::default().bold();
155 /// assert_eq!("\x1b[1m",
156 /// style.prefix().to_string());
158 /// let style = Blue.bold();
159 /// assert_eq!("\x1b[1;34m",
160 /// style.prefix().to_string());
162 /// let style = Style::default();
164 /// style.prefix().to_string());
166 pub fn prefix(self) -> Prefix
{
170 /// The infix bytes between this style and `next` style. These are the bytes
171 /// that tell the terminal to change the style to `next`. These may include
172 /// a reset followed by the next colour and style, depending on the two styles.
177 /// use ansi_term::{Style, Colour::Green};
179 /// let style = Style::default().bold();
180 /// assert_eq!("\x1b[32m",
181 /// style.infix(Green.bold()).to_string());
183 /// let style = Green.normal();
184 /// assert_eq!("\x1b[1m",
185 /// style.infix(Green.bold()).to_string());
187 /// let style = Style::default();
189 /// style.infix(style).to_string());
191 pub fn infix(self, next
: Style
) -> Infix
{
195 /// The suffix for this style. These are the bytes that tell the terminal
196 /// to reset back to its normal colour and font style.
201 /// use ansi_term::{Style, Colour::Green};
203 /// let style = Style::default().bold();
204 /// assert_eq!("\x1b[0m",
205 /// style.suffix().to_string());
207 /// let style = Green.normal().bold();
208 /// assert_eq!("\x1b[0m",
209 /// style.suffix().to_string());
211 /// let style = Style::default();
213 /// style.suffix().to_string());
215 pub fn suffix(self) -> Suffix
{
223 /// The prefix bytes for this colour as a `Style`. These are the bytes
224 /// that tell the terminal to use a different colour or font style.
226 /// See also [`Style::prefix`](struct.Style.html#method.prefix).
231 /// use ansi_term::Colour::Green;
233 /// assert_eq!("\x1b[0m",
234 /// Green.suffix().to_string());
236 pub fn prefix(self) -> Prefix
{
237 Prefix(self.normal())
240 /// The infix bytes between this colour and `next` colour. These are the bytes
241 /// that tell the terminal to use the `next` colour, or to do nothing if
242 /// the two colours are equal.
244 /// See also [`Style::infix`](struct.Style.html#method.infix).
249 /// use ansi_term::Colour::{Red, Yellow};
251 /// assert_eq!("\x1b[33m",
252 /// Red.infix(Yellow).to_string());
254 pub fn infix(self, next
: Colour
) -> Infix
{
255 Infix(self.normal(), next
.normal())
258 /// The suffix for this colour as a `Style`. These are the bytes that
259 /// tell the terminal to reset back to its normal colour and font style.
261 /// See also [`Style::suffix`](struct.Style.html#method.suffix).
266 /// use ansi_term::Colour::Purple;
268 /// assert_eq!("\x1b[0m",
269 /// Purple.suffix().to_string());
271 pub fn suffix(self) -> Suffix
{
272 Suffix(self.normal())
277 impl fmt
::Display
for Prefix
{
278 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
279 let f
: &mut fmt
::Write
= f
;
280 self.0.write_prefix(f
)
285 impl fmt
::Display
for Infix
{
286 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
287 use difference
::Difference
;
289 match Difference
::between(&self.0, &self.1) {
290 Difference
::ExtraStyles(style
) => {
291 let f
: &mut fmt
::Write
= f
;
292 style
.write_prefix(f
)
294 Difference
::Reset
=> {
295 let f
: &mut fmt
::Write
= f
;
296 write
!(f
, "{}{}", RESET
, self.1.prefix())
298 Difference
::NoDifference
=> {
299 Ok(()) // nothing to write
306 impl fmt
::Display
for Suffix
{
307 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
308 let f
: &mut fmt
::Write
= f
;
309 self.0.write_suffix(f
)
318 use style
::Colour
::*;
321 ($name
: ident
: $style
: expr
; $input
: expr
=> $result
: expr
) => {
324 assert_eq
!($style
.paint($input
).to_string(), $result
.to_string());
326 let mut v
= Vec
::new();
327 $style
.paint($input
.as_bytes()).write_to(&mut v
).unwrap();
328 assert_eq
!(v
.as_slice(), $result
.as_bytes());
333 test
!(plain
: Style
::default(); "text/plain" => "text/plain");
334 test
!(red
: Red
; "hi" => "\x1B[31mhi\x1B[0m");
335 test
!(black
: Black
.normal(); "hi" => "\x1B[30mhi\x1B[0m");
336 test
!(yellow_bold
: Yellow
.bold(); "hi" => "\x1B[1;33mhi\x1B[0m");
337 test
!(yellow_bold_2
: Yellow
.normal().bold(); "hi" => "\x1B[1;33mhi\x1B[0m");
338 test
!(blue_underline
: Blue
.underline(); "hi" => "\x1B[4;34mhi\x1B[0m");
339 test
!(green_bold_ul
: Green
.bold().underline(); "hi" => "\x1B[1;4;32mhi\x1B[0m");
340 test
!(green_bold_ul_2
: Green
.underline().bold(); "hi" => "\x1B[1;4;32mhi\x1B[0m");
341 test
!(purple_on_white
: Purple
.on(White
); "hi" => "\x1B[47;35mhi\x1B[0m");
342 test
!(purple_on_white_2
: Purple
.normal().on(White
); "hi" => "\x1B[47;35mhi\x1B[0m");
343 test
!(yellow_on_blue
: Style
::new().on(Blue
).fg(Yellow
); "hi" => "\x1B[44;33mhi\x1B[0m");
344 test
!(yellow_on_blue_2
: Cyan
.on(Blue
).fg(Yellow
); "hi" => "\x1B[44;33mhi\x1B[0m");
345 test
!(cyan_bold_on_white
: Cyan
.bold().on(White
); "hi" => "\x1B[1;47;36mhi\x1B[0m");
346 test
!(cyan_ul_on_white
: Cyan
.underline().on(White
); "hi" => "\x1B[4;47;36mhi\x1B[0m");
347 test
!(cyan_bold_ul_on_white
: Cyan
.bold().underline().on(White
); "hi" => "\x1B[1;4;47;36mhi\x1B[0m");
348 test
!(cyan_ul_bold_on_white
: Cyan
.underline().bold().on(White
); "hi" => "\x1B[1;4;47;36mhi\x1B[0m");
349 test
!(fixed
: Fixed(100); "hi" => "\x1B[38;5;100mhi\x1B[0m");
350 test
!(fixed_on_purple
: Fixed(100).on(Purple
); "hi" => "\x1B[45;38;5;100mhi\x1B[0m");
351 test
!(fixed_on_fixed
: Fixed(100).on(Fixed(200)); "hi" => "\x1B[48;5;200;38;5;100mhi\x1B[0m");
352 test
!(rgb
: RGB(70,130,180); "hi" => "\x1B[38;2;70;130;180mhi\x1B[0m");
353 test
!(rgb_on_blue
: RGB(70,130,180).on(Blue
); "hi" => "\x1B[44;38;2;70;130;180mhi\x1B[0m");
354 test
!(blue_on_rgb
: Blue
.on(RGB(70,130,180)); "hi" => "\x1B[48;2;70;130;180;34mhi\x1B[0m");
355 test
!(rgb_on_rgb
: RGB(70,130,180).on(RGB(5,10,15)); "hi" => "\x1B[48;2;5;10;15;38;2;70;130;180mhi\x1B[0m");
356 test
!(bold
: Style
::new().bold(); "hi" => "\x1B[1mhi\x1B[0m");
357 test
!(underline
: Style
::new().underline(); "hi" => "\x1B[4mhi\x1B[0m");
358 test
!(bunderline
: Style
::new().bold().underline(); "hi" => "\x1B[1;4mhi\x1B[0m");
359 test
!(dimmed
: Style
::new().dimmed(); "hi" => "\x1B[2mhi\x1B[0m");
360 test
!(italic
: Style
::new().italic(); "hi" => "\x1B[3mhi\x1B[0m");
361 test
!(blink
: Style
::new().blink(); "hi" => "\x1B[5mhi\x1B[0m");
362 test
!(reverse
: Style
::new().reverse(); "hi" => "\x1B[7mhi\x1B[0m");
363 test
!(hidden
: Style
::new().hidden(); "hi" => "\x1B[8mhi\x1B[0m");
364 test
!(stricken
: Style
::new().strikethrough(); "hi" => "\x1B[9mhi\x1B[0m");
368 assert_eq
!(Style
::new().dimmed().infix(Style
::new()).to_string(), "\x1B[0m");
369 assert_eq
!(White
.dimmed().infix(White
.normal()).to_string(), "\x1B[0m\x1B[37m");
370 assert_eq
!(White
.normal().infix(White
.bold()).to_string(), "\x1B[1m");
371 assert_eq
!(White
.normal().infix(Blue
.normal()).to_string(), "\x1B[34m");
372 assert_eq
!(Blue
.bold().infix(Blue
.bold()).to_string(), "");