Coverage Report

Created: 2026-01-09 06:43

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/nu-ansi-term-0.49.0/src/ansi.rs
Line
Count
Source
1
#![allow(missing_docs)]
2
use crate::style::{Color, Style};
3
use crate::write::AnyWrite;
4
use std::fmt;
5
6
impl Style {
7
    /// Write any bytes that go *before* a piece of text to the given writer.
8
0
    fn write_prefix<W: AnyWrite + ?Sized>(&self, f: &mut W) -> Result<(), W::Error> {
9
        // If there are actually no styles here, then don’t write *any* codes
10
        // as the prefix. An empty ANSI code may not affect the terminal
11
        // output at all, but a user may just want a code-free string.
12
0
        if self.is_plain() {
13
0
            return Ok(());
14
0
        }
15
16
        // Prefix everything with reset characters if needed
17
0
        if self.prefix_with_reset {
18
0
            write!(f, "\x1B[0m")?
19
0
        }
20
21
        // Write the codes’ prefix, then write numbers, separated by
22
        // semicolons, for each text style we want to apply.
23
0
        write!(f, "\x1B[")?;
24
0
        let mut written_anything = false;
25
26
        {
27
0
            let mut write_char = |c| {
28
0
                if written_anything {
29
0
                    write!(f, ";")?;
30
0
                }
31
0
                written_anything = true;
32
                #[cfg(feature = "gnu_legacy")]
33
                write!(f, "0")?;
34
0
                write!(f, "{}", c)?;
35
0
                Ok(())
36
0
            };
37
38
0
            if self.is_bold {
39
0
                write_char('1')?
40
0
            }
41
0
            if self.is_dimmed {
42
0
                write_char('2')?
43
0
            }
44
0
            if self.is_italic {
45
0
                write_char('3')?
46
0
            }
47
0
            if self.is_underline {
48
0
                write_char('4')?
49
0
            }
50
0
            if self.is_blink {
51
0
                write_char('5')?
52
0
            }
53
0
            if self.is_reverse {
54
0
                write_char('7')?
55
0
            }
56
0
            if self.is_hidden {
57
0
                write_char('8')?
58
0
            }
59
0
            if self.is_strikethrough {
60
0
                write_char('9')?
61
0
            }
62
        }
63
64
        // The foreground and background colors, if specified, need to be
65
        // handled specially because the number codes are more complicated.
66
        // (see `write_background_code` and `write_foreground_code`)
67
0
        if let Some(bg) = self.background {
68
0
            if written_anything {
69
0
                write!(f, ";")?;
70
0
            }
71
0
            written_anything = true;
72
0
            bg.write_background_code(f)?;
73
0
        }
74
75
0
        if let Some(fg) = self.foreground {
76
0
            if written_anything {
77
0
                write!(f, ";")?;
78
0
            }
79
0
            fg.write_foreground_code(f)?;
80
0
        }
81
82
        // All the codes end with an `m`, because reasons.
83
0
        write!(f, "m")?;
84
85
0
        Ok(())
86
0
    }
87
88
    /// Write any bytes that go *after* a piece of text to the given writer.
89
0
    fn write_suffix<W: AnyWrite + ?Sized>(&self, f: &mut W) -> Result<(), W::Error> {
90
0
        if self.is_plain() {
91
0
            Ok(())
92
        } else {
93
0
            write!(f, "{}", RESET)
94
        }
95
0
    }
96
}
97
98
/// The code to send to reset all styles and return to `Style::default()`.
99
pub static RESET: &str = "\x1B[0m";
100
101
impl Color {
102
0
    fn write_foreground_code<W: AnyWrite + ?Sized>(&self, f: &mut W) -> Result<(), W::Error> {
103
0
        match self {
104
0
            Color::Black => write!(f, "30"),
105
0
            Color::Red => write!(f, "31"),
106
0
            Color::Green => write!(f, "32"),
107
0
            Color::Yellow => write!(f, "33"),
108
0
            Color::Blue => write!(f, "34"),
109
0
            Color::Purple => write!(f, "35"),
110
0
            Color::Magenta => write!(f, "35"),
111
0
            Color::Cyan => write!(f, "36"),
112
0
            Color::White => write!(f, "37"),
113
0
            Color::Fixed(num) => write!(f, "38;5;{}", num),
114
0
            Color::Rgb(r, g, b) => write!(f, "38;2;{};{};{}", r, g, b),
115
0
            Color::Default => write!(f, "39"),
116
0
            Color::DarkGray => write!(f, "90"),
117
0
            Color::LightRed => write!(f, "91"),
118
0
            Color::LightGreen => write!(f, "92"),
119
0
            Color::LightYellow => write!(f, "93"),
120
0
            Color::LightBlue => write!(f, "94"),
121
0
            Color::LightPurple => write!(f, "95"),
122
0
            Color::LightMagenta => write!(f, "95"),
123
0
            Color::LightCyan => write!(f, "96"),
124
0
            Color::LightGray => write!(f, "97"),
125
        }
126
0
    }
127
128
0
    fn write_background_code<W: AnyWrite + ?Sized>(&self, f: &mut W) -> Result<(), W::Error> {
129
0
        match self {
130
0
            Color::Black => write!(f, "40"),
131
0
            Color::Red => write!(f, "41"),
132
0
            Color::Green => write!(f, "42"),
133
0
            Color::Yellow => write!(f, "43"),
134
0
            Color::Blue => write!(f, "44"),
135
0
            Color::Purple => write!(f, "45"),
136
0
            Color::Magenta => write!(f, "45"),
137
0
            Color::Cyan => write!(f, "46"),
138
0
            Color::White => write!(f, "47"),
139
0
            Color::Fixed(num) => write!(f, "48;5;{}", num),
140
0
            Color::Rgb(r, g, b) => write!(f, "48;2;{};{};{}", r, g, b),
141
0
            Color::Default => write!(f, "49"),
142
0
            Color::DarkGray => write!(f, "100"),
143
0
            Color::LightRed => write!(f, "101"),
144
0
            Color::LightGreen => write!(f, "102"),
145
0
            Color::LightYellow => write!(f, "103"),
146
0
            Color::LightBlue => write!(f, "104"),
147
0
            Color::LightPurple => write!(f, "105"),
148
0
            Color::LightMagenta => write!(f, "105"),
149
0
            Color::LightCyan => write!(f, "106"),
150
0
            Color::LightGray => write!(f, "107"),
151
        }
152
0
    }
153
}
154
155
/// Like `AnsiString`, but only displays the style prefix.
156
///
157
/// This type implements the `Display` trait, meaning it can be written to a
158
/// `std::fmt` formatting without doing any extra allocation, and written to a
159
/// string with the `.to_string()` method. For examples, see
160
/// [`Style::prefix`](struct.Style.html#method.prefix).
161
#[derive(Clone, Copy, Debug)]
162
pub struct Prefix(Style);
163
164
/// Like `AnsiString`, but only displays the difference between two
165
/// styles.
166
///
167
/// This type implements the `Display` trait, meaning it can be written to a
168
/// `std::fmt` formatting without doing any extra allocation, and written to a
169
/// string with the `.to_string()` method. For examples, see
170
/// [`Style::infix`](struct.Style.html#method.infix).
171
#[derive(Clone, Copy, Debug)]
172
pub struct Infix(Style, Style);
173
174
/// Like `AnsiString`, but only displays the style suffix.
175
///
176
/// This type implements the `Display` trait, meaning it can be written to a
177
/// `std::fmt` formatting without doing any extra allocation, and written to a
178
/// string with the `.to_string()` method. For examples, see
179
/// [`Style::suffix`](struct.Style.html#method.suffix).
180
#[derive(Clone, Copy, Debug)]
181
pub struct Suffix(Style);
182
183
impl Style {
184
    /// The prefix bytes for this style. These are the bytes that tell the
185
    /// terminal to use a different color or font style.
186
    ///
187
    /// # Examples
188
    ///
189
    /// ```
190
    /// # #[cfg(not(feature = "gnu_legacy"))]
191
    /// # {
192
    /// use nu_ansi_term::{Style, Color::Blue};
193
    ///
194
    /// let style = Style::default().bold();
195
    /// assert_eq!("\x1b[1m",
196
    ///            style.prefix().to_string());
197
    ///
198
    /// let style = Blue.bold();
199
    /// assert_eq!("\x1b[1;34m",
200
    ///            style.prefix().to_string());
201
    ///
202
    /// let style = Style::default();
203
    /// assert_eq!("",
204
    ///            style.prefix().to_string());
205
    /// # }
206
    /// ```
207
    ///     
208
    /// # Examples with gnu_legacy feature enabled
209
    /// Styles like bold, underlined, etc. are two-digit now
210
    ///
211
    /// ```
212
    /// # #[cfg(feature = "gnu_legacy")]
213
    /// # {
214
    /// use nu_ansi_term::{Style, Color::Blue};
215
    ///
216
    /// let style = Style::default().bold();
217
    /// assert_eq!("\x1b[01m",
218
    ///            style.prefix().to_string());
219
    ///
220
    /// let style = Blue.bold();
221
    /// assert_eq!("\x1b[01;34m",
222
    ///            style.prefix().to_string());
223
    /// # }
224
    /// ```
225
0
    pub const fn prefix(self) -> Prefix {
226
0
        Prefix(self)
227
0
    }
228
229
    /// The infix bytes between this style and `next` style. These are the bytes
230
    /// that tell the terminal to change the style to `next`. These may include
231
    /// a reset followed by the next color and style, depending on the two styles.
232
    ///
233
    /// # Examples
234
    /// ```
235
    /// # #[cfg(not(feature = "gnu_legacy"))]
236
    /// # {
237
    /// use nu_ansi_term::{Style, Color::Green};
238
    ///
239
    /// let style = Style::default().bold();
240
    /// assert_eq!("\x1b[32m",
241
    ///            style.infix(Green.bold()).to_string());
242
    ///
243
    /// let style = Green.normal();
244
    /// assert_eq!("\x1b[1m",
245
    ///            style.infix(Green.bold()).to_string());
246
    ///
247
    /// let style = Style::default();
248
    /// assert_eq!("",
249
    ///            style.infix(style).to_string());
250
    /// # }
251
    /// ```
252
    /// # Examples with gnu_legacy feature enabled
253
    /// Styles like bold, underlined, etc. are two-digit now
254
    /// ```
255
    /// # #[cfg(feature = "gnu_legacy")]
256
    /// # {
257
    /// use nu_ansi_term::Color::Green;
258
    ///
259
    /// let style = Green.normal();
260
    /// assert_eq!("\x1b[01m",
261
    ///            style.infix(Green.bold()).to_string());
262
    /// # }
263
    /// ```
264
0
    pub const fn infix(self, next: Style) -> Infix {
265
0
        Infix(self, next)
266
0
    }
267
268
    /// The suffix for this style. These are the bytes that tell the terminal
269
    /// to reset back to its normal color and font style.
270
    ///
271
    /// # Examples
272
    ///
273
    /// ```
274
    /// use nu_ansi_term::{Style, Color::Green};
275
    ///
276
    /// let style = Style::default().bold();
277
    /// assert_eq!("\x1b[0m",
278
    ///            style.suffix().to_string());
279
    ///
280
    /// let style = Green.normal().bold();
281
    /// assert_eq!("\x1b[0m",
282
    ///            style.suffix().to_string());
283
    ///
284
    /// let style = Style::default();
285
    /// assert_eq!("",
286
    ///            style.suffix().to_string());
287
    /// ```
288
0
    pub const fn suffix(self) -> Suffix {
289
0
        Suffix(self)
290
0
    }
291
}
292
293
impl Color {
294
    /// The prefix bytes for this color as a `Style`. These are the bytes
295
    /// that tell the terminal to use a different color or font style.
296
    ///
297
    /// See also [`Style::prefix`](struct.Style.html#method.prefix).
298
    ///
299
    /// # Examples
300
    ///
301
    /// ```
302
    /// use nu_ansi_term::Color::Green;
303
    ///
304
    /// assert_eq!("\x1b[32m",
305
    ///            Green.prefix().to_string());
306
    /// ```
307
0
    pub fn prefix(self) -> Prefix {
308
0
        Prefix(self.normal())
309
0
    }
310
311
    /// The infix bytes between this color and `next` color. These are the bytes
312
    /// that tell the terminal to use the `next` color, or to do nothing if
313
    /// the two colors are equal.
314
    ///
315
    /// See also [`Style::infix`](struct.Style.html#method.infix).
316
    ///
317
    /// # Examples
318
    ///
319
    /// ```
320
    /// use nu_ansi_term::Color::{Red, Yellow};
321
    ///
322
    /// assert_eq!("\x1b[33m",
323
    ///            Red.infix(Yellow).to_string());
324
    /// ```
325
0
    pub fn infix(self, next: Color) -> Infix {
326
0
        Infix(self.normal(), next.normal())
327
0
    }
328
329
    /// The suffix for this color as a `Style`. These are the bytes that
330
    /// tell the terminal to reset back to its normal color and font style.
331
    ///
332
    /// See also [`Style::suffix`](struct.Style.html#method.suffix).
333
    ///
334
    /// # Examples
335
    ///
336
    /// ```
337
    /// use nu_ansi_term::Color::Purple;
338
    ///
339
    /// assert_eq!("\x1b[0m",
340
    ///            Purple.suffix().to_string());
341
    /// ```
342
0
    pub fn suffix(self) -> Suffix {
343
0
        Suffix(self.normal())
344
0
    }
345
}
346
347
impl fmt::Display for Prefix {
348
0
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
349
0
        let f: &mut dyn fmt::Write = f;
350
0
        self.0.write_prefix(f)
351
0
    }
352
}
353
354
impl fmt::Display for Infix {
355
0
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
356
        use crate::difference::Difference;
357
358
0
        match Difference::between(&self.0, &self.1) {
359
0
            Difference::ExtraStyles(style) => {
360
0
                let f: &mut dyn fmt::Write = f;
361
0
                style.write_prefix(f)
362
            }
363
            Difference::Reset => {
364
0
                let f: &mut dyn fmt::Write = f;
365
0
                write!(f, "{}{}", RESET, self.1.prefix())
366
            }
367
            Difference::Empty => {
368
0
                Ok(()) // nothing to write
369
            }
370
        }
371
0
    }
372
}
373
374
impl fmt::Display for Suffix {
375
0
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
376
0
        let f: &mut dyn fmt::Write = f;
377
0
        self.0.write_suffix(f)
378
0
    }
379
}
380
381
#[cfg(test)]
382
macro_rules! test {
383
    ($name: ident: $style: expr; $input: expr => $result: expr) => {
384
        #[test]
385
        fn $name() {
386
            assert_eq!($style.paint($input).to_string(), $result.to_string());
387
388
            let mut v = Vec::new();
389
            $style.paint($input.as_bytes()).write_to(&mut v).unwrap();
390
            assert_eq!(v.as_slice(), $result.as_bytes());
391
        }
392
    };
393
}
394
395
#[cfg(test)]
396
#[cfg(not(feature = "gnu_legacy"))]
397
mod test {
398
    use crate::style::Color::*;
399
    use crate::style::Style;
400
401
    test!(plain:                 Style::default();                  "text/plain" => "text/plain");
402
    test!(red:                   Red;                               "hi" => "\x1B[31mhi\x1B[0m");
403
    test!(black:                 Black.normal();                    "hi" => "\x1B[30mhi\x1B[0m");
404
    test!(yellow_bold:           Yellow.bold();                     "hi" => "\x1B[1;33mhi\x1B[0m");
405
    test!(yellow_bold_2:         Yellow.normal().bold();            "hi" => "\x1B[1;33mhi\x1B[0m");
406
    test!(blue_underline:        Blue.underline();                  "hi" => "\x1B[4;34mhi\x1B[0m");
407
    test!(green_bold_ul:         Green.bold().underline();          "hi" => "\x1B[1;4;32mhi\x1B[0m");
408
    test!(green_bold_ul_2:       Green.underline().bold();          "hi" => "\x1B[1;4;32mhi\x1B[0m");
409
    test!(purple_on_white:       Purple.on(White);                  "hi" => "\x1B[47;35mhi\x1B[0m");
410
    test!(purple_on_white_2:     Purple.normal().on(White);         "hi" => "\x1B[47;35mhi\x1B[0m");
411
    test!(yellow_on_blue:        Style::new().on(Blue).fg(Yellow);  "hi" => "\x1B[44;33mhi\x1B[0m");
412
    test!(magenta_on_white:      Magenta.on(White);                  "hi" => "\x1B[47;35mhi\x1B[0m");
413
    test!(magenta_on_white_2:    Magenta.normal().on(White);         "hi" => "\x1B[47;35mhi\x1B[0m");
414
    test!(yellow_on_blue_2:      Cyan.on(Blue).fg(Yellow);          "hi" => "\x1B[44;33mhi\x1B[0m");
415
    test!(yellow_on_blue_reset:  Cyan.on(Blue).reset_before_style().fg(Yellow); "hi" => "\x1B[0m\x1B[44;33mhi\x1B[0m");
416
    test!(yellow_on_blue_reset_2: Cyan.on(Blue).fg(Yellow).reset_before_style(); "hi" => "\x1B[0m\x1B[44;33mhi\x1B[0m");
417
    test!(cyan_bold_on_white:    Cyan.bold().on(White);             "hi" => "\x1B[1;47;36mhi\x1B[0m");
418
    test!(cyan_ul_on_white:      Cyan.underline().on(White);        "hi" => "\x1B[4;47;36mhi\x1B[0m");
419
    test!(cyan_bold_ul_on_white: Cyan.bold().underline().on(White); "hi" => "\x1B[1;4;47;36mhi\x1B[0m");
420
    test!(cyan_ul_bold_on_white: Cyan.underline().bold().on(White); "hi" => "\x1B[1;4;47;36mhi\x1B[0m");
421
    test!(fixed:                 Fixed(100);                        "hi" => "\x1B[38;5;100mhi\x1B[0m");
422
    test!(fixed_on_purple:       Fixed(100).on(Purple);             "hi" => "\x1B[45;38;5;100mhi\x1B[0m");
423
    test!(fixed_on_fixed:        Fixed(100).on(Fixed(200));         "hi" => "\x1B[48;5;200;38;5;100mhi\x1B[0m");
424
    test!(rgb:                   Rgb(70,130,180);                   "hi" => "\x1B[38;2;70;130;180mhi\x1B[0m");
425
    test!(rgb_on_blue:           Rgb(70,130,180).on(Blue);          "hi" => "\x1B[44;38;2;70;130;180mhi\x1B[0m");
426
    test!(blue_on_rgb:           Blue.on(Rgb(70,130,180));          "hi" => "\x1B[48;2;70;130;180;34mhi\x1B[0m");
427
    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");
428
    test!(bold:                  Style::new().bold();               "hi" => "\x1B[1mhi\x1B[0m");
429
    test!(bold_with_reset:       Style::new().reset_before_style().bold(); "hi" => "\x1B[0m\x1B[1mhi\x1B[0m");
430
    test!(bold_with_reset_2:     Style::new().bold().reset_before_style(); "hi" => "\x1B[0m\x1B[1mhi\x1B[0m");
431
    test!(underline:             Style::new().underline();          "hi" => "\x1B[4mhi\x1B[0m");
432
    test!(bunderline:            Style::new().bold().underline();   "hi" => "\x1B[1;4mhi\x1B[0m");
433
    test!(dimmed:                Style::new().dimmed();             "hi" => "\x1B[2mhi\x1B[0m");
434
    test!(italic:                Style::new().italic();             "hi" => "\x1B[3mhi\x1B[0m");
435
    test!(blink:                 Style::new().blink();              "hi" => "\x1B[5mhi\x1B[0m");
436
    test!(reverse:               Style::new().reverse();            "hi" => "\x1B[7mhi\x1B[0m");
437
    test!(hidden:                Style::new().hidden();             "hi" => "\x1B[8mhi\x1B[0m");
438
    test!(stricken:              Style::new().strikethrough();      "hi" => "\x1B[9mhi\x1B[0m");
439
    test!(lr_on_lr:              LightRed.on(LightRed);             "hi" => "\x1B[101;91mhi\x1B[0m");
440
441
    #[test]
442
    fn test_infix() {
443
        assert_eq!(
444
            Style::new().dimmed().infix(Style::new()).to_string(),
445
            "\x1B[0m"
446
        );
447
        assert_eq!(
448
            White.dimmed().infix(White.normal()).to_string(),
449
            "\x1B[0m\x1B[37m"
450
        );
451
        assert_eq!(White.normal().infix(White.bold()).to_string(), "\x1B[1m");
452
        assert_eq!(White.normal().infix(Blue.normal()).to_string(), "\x1B[34m");
453
        assert_eq!(Blue.bold().infix(Blue.bold()).to_string(), "");
454
    }
455
}
456
457
#[cfg(test)]
458
#[cfg(feature = "gnu_legacy")]
459
mod gnu_legacy_test {
460
    use crate::style::Color::*;
461
    use crate::style::Style;
462
463
    test!(plain:                 Style::default();                  "text/plain" => "text/plain");
464
    test!(red:                   Red;                               "hi" => "\x1B[31mhi\x1B[0m");
465
    test!(black:                 Black.normal();                    "hi" => "\x1B[30mhi\x1B[0m");
466
    test!(yellow_bold:           Yellow.bold();                     "hi" => "\x1B[01;33mhi\x1B[0m");
467
    test!(yellow_bold_2:         Yellow.normal().bold();            "hi" => "\x1B[01;33mhi\x1B[0m");
468
    test!(blue_underline:        Blue.underline();                  "hi" => "\x1B[04;34mhi\x1B[0m");
469
    test!(green_bold_ul:         Green.bold().underline();          "hi" => "\x1B[01;04;32mhi\x1B[0m");
470
    test!(green_bold_ul_2:       Green.underline().bold();          "hi" => "\x1B[01;04;32mhi\x1B[0m");
471
    test!(purple_on_white:       Purple.on(White);                  "hi" => "\x1B[47;35mhi\x1B[0m");
472
    test!(purple_on_white_2:     Purple.normal().on(White);         "hi" => "\x1B[47;35mhi\x1B[0m");
473
    test!(yellow_on_blue:        Style::new().on(Blue).fg(Yellow);  "hi" => "\x1B[44;33mhi\x1B[0m");
474
    test!(yellow_on_blue_reset:  Cyan.on(Blue).reset_before_style().fg(Yellow); "hi" => "\x1B[0m\x1B[44;33mhi\x1B[0m");
475
    test!(yellow_on_blue_reset_2: Cyan.on(Blue).fg(Yellow).reset_before_style(); "hi" => "\x1B[0m\x1B[44;33mhi\x1B[0m");
476
    test!(magenta_on_white:      Magenta.on(White);                  "hi" => "\x1B[47;35mhi\x1B[0m");
477
    test!(magenta_on_white_2:    Magenta.normal().on(White);         "hi" => "\x1B[47;35mhi\x1B[0m");
478
    test!(yellow_on_blue_2:      Cyan.on(Blue).fg(Yellow);          "hi" => "\x1B[44;33mhi\x1B[0m");
479
    test!(cyan_bold_on_white:    Cyan.bold().on(White);             "hi" => "\x1B[01;47;36mhi\x1B[0m");
480
    test!(cyan_ul_on_white:      Cyan.underline().on(White);        "hi" => "\x1B[04;47;36mhi\x1B[0m");
481
    test!(cyan_bold_ul_on_white: Cyan.bold().underline().on(White); "hi" => "\x1B[01;04;47;36mhi\x1B[0m");
482
    test!(cyan_ul_bold_on_white: Cyan.underline().bold().on(White); "hi" => "\x1B[01;04;47;36mhi\x1B[0m");
483
    test!(fixed:                 Fixed(100);                        "hi" => "\x1B[38;5;100mhi\x1B[0m");
484
    test!(fixed_on_purple:       Fixed(100).on(Purple);             "hi" => "\x1B[45;38;5;100mhi\x1B[0m");
485
    test!(fixed_on_fixed:        Fixed(100).on(Fixed(200));         "hi" => "\x1B[48;5;200;38;5;100mhi\x1B[0m");
486
    test!(rgb:                   Rgb(70,130,180);                   "hi" => "\x1B[38;2;70;130;180mhi\x1B[0m");
487
    test!(rgb_on_blue:           Rgb(70,130,180).on(Blue);          "hi" => "\x1B[44;38;2;70;130;180mhi\x1B[0m");
488
    test!(blue_on_rgb:           Blue.on(Rgb(70,130,180));          "hi" => "\x1B[48;2;70;130;180;34mhi\x1B[0m");
489
    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");
490
    test!(bold:                  Style::new().bold();               "hi" => "\x1B[01mhi\x1B[0m");
491
    test!(bold_with_reset:       Style::new().reset_before_style().bold(); "hi" => "\x1B[0m\x1B[01mhi\x1B[0m");
492
    test!(bold_with_reset_2:     Style::new().bold().reset_before_style(); "hi" => "\x1B[0m\x1B[01mhi\x1B[0m");
493
    test!(underline:             Style::new().underline();          "hi" => "\x1B[04mhi\x1B[0m");
494
    test!(bunderline:            Style::new().bold().underline();   "hi" => "\x1B[01;04mhi\x1B[0m");
495
    test!(dimmed:                Style::new().dimmed();             "hi" => "\x1B[02mhi\x1B[0m");
496
    test!(italic:                Style::new().italic();             "hi" => "\x1B[03mhi\x1B[0m");
497
    test!(blink:                 Style::new().blink();              "hi" => "\x1B[05mhi\x1B[0m");
498
    test!(reverse:               Style::new().reverse();            "hi" => "\x1B[07mhi\x1B[0m");
499
    test!(hidden:                Style::new().hidden();             "hi" => "\x1B[08mhi\x1B[0m");
500
    test!(stricken:              Style::new().strikethrough();      "hi" => "\x1B[09mhi\x1B[0m");
501
    test!(lr_on_lr:              LightRed.on(LightRed);             "hi" => "\x1B[101;91mhi\x1B[0m");
502
}