owo_colors/
dyn_styles.rs

1use crate::{AnsiColors, Color, DynColor, DynColors};
2use core::fmt;
3
4#[cfg(doc)]
5use crate::OwoColorize;
6
7/// A runtime-configurable text effect for use with [`Style`]
8#[allow(missing_docs)]
9#[derive(Debug, Copy, Clone)]
10pub enum Effect {
11    Bold,
12    Dimmed,
13    Italic,
14    Underline,
15    Blink,
16    BlinkFast,
17    Reversed,
18    Hidden,
19    Strikethrough,
20}
21
22macro_rules! color_methods {
23    ($(
24        #[$fg_meta:meta] #[$bg_meta:meta] $color:ident $fg_method:ident $bg_method:ident
25    ),* $(,)?) => {
26        $(
27            #[$fg_meta]
28            #[must_use]
29            pub const fn $fg_method(mut self) -> Self {
30                self.fg = Some(DynColors::Ansi(AnsiColors::$color));
31                self
32            }
33
34            #[$fg_meta]
35            #[must_use]
36            pub const fn $bg_method(mut self) -> Self {
37                self.bg = Some(DynColors::Ansi(AnsiColors::$color));
38                self
39            }
40         )*
41    };
42}
43
44macro_rules! style_methods {
45    ($(#[$meta:meta] ($name:ident, $set_name:ident)),* $(,)?) => {
46        $(
47            #[$meta]
48            #[must_use]
49            pub const fn $name(mut self) -> Self {
50                self.style_flags = self.style_flags.$set_name(true);
51                self
52            }
53        )*
54    };
55}
56
57const _: () = (); // workaround for syntax highlighting bug
58
59/// A wrapper type which applies a [`Style`] when displaying the inner type
60pub struct Styled<T> {
61    /// The target value to be styled
62    pub(crate) target: T,
63    /// The style to apply to target
64    pub style: Style,
65}
66
67/// A pre-computed style that can be applied to a struct using [`OwoColorize::style`].
68///
69/// Its interface mimics that of [`OwoColorize`], but instead of chaining methods on your
70/// object, you instead chain them on the `Style` object before applying it.
71///
72/// ```rust
73/// use owo_colors::{OwoColorize, Style};
74///
75/// let my_style = Style::new()
76///     .red()
77///     .on_white()
78///     .strikethrough();
79///
80/// println!("{}", "red text, white background, struck through".style(my_style));
81/// ```
82#[derive(Debug, Copy, Clone, PartialEq)]
83pub struct Style {
84    pub(crate) fg: Option<DynColors>,
85    pub(crate) bg: Option<DynColors>,
86    pub(crate) bold: bool,
87    pub(crate) style_flags: StyleFlags,
88}
89
90#[repr(transparent)]
91#[derive(Debug, Copy, Clone, PartialEq)]
92pub(crate) struct StyleFlags(pub(crate) u8);
93
94impl StyleFlags {
95    #[must_use]
96    #[inline]
97    const fn is_plain(&self) -> bool {
98        self.0 == 0
99    }
100}
101
102const DIMMED_SHIFT: u8 = 0;
103const ITALIC_SHIFT: u8 = 1;
104const UNDERLINE_SHIFT: u8 = 2;
105const BLINK_SHIFT: u8 = 3;
106const BLINK_FAST_SHIFT: u8 = 4;
107const REVERSED_SHIFT: u8 = 5;
108const HIDDEN_SHIFT: u8 = 6;
109const STRIKETHROUGH_SHIFT: u8 = 7;
110
111macro_rules! style_flags_methods {
112    ($(($shift:ident, $name:ident, $set_name:ident)),* $(,)?) => {
113        $(
114            #[must_use]
115            const fn $name(&self) -> bool {
116                ((self.0 >> $shift) & 1) != 0
117            }
118
119            #[must_use]
120            const fn $set_name(mut self, $name: bool) -> Self {
121                self.0 = (self.0 & !(1 << $shift)) | (($name as u8) << $shift);
122                self
123            }
124        )*
125    };
126}
127
128impl StyleFlags {
129    const fn new() -> Self {
130        Self(0)
131    }
132
133    style_flags_methods! {
134        (DIMMED_SHIFT, dimmed, set_dimmed),
135        (ITALIC_SHIFT, italic, set_italic),
136        (UNDERLINE_SHIFT, underline, set_underline),
137        (BLINK_SHIFT, blink, set_blink),
138        (BLINK_FAST_SHIFT, blink_fast, set_blink_fast),
139        (REVERSED_SHIFT, reversed, set_reversed),
140        (HIDDEN_SHIFT, hidden, set_hidden),
141        (STRIKETHROUGH_SHIFT, strikethrough, set_strikethrough),
142    }
143}
144
145impl Default for StyleFlags {
146    fn default() -> Self {
147        Self::new()
148    }
149}
150
151impl Style {
152    /// Create a new style to be applied later
153    #[must_use]
154    pub const fn new() -> Self {
155        Self {
156            fg: None,
157            bg: None,
158            bold: false,
159            style_flags: StyleFlags::new(),
160        }
161    }
162
163    /// Apply the style to a given struct to output.
164    ///
165    /// # Example
166    ///
167    /// Usage in const contexts:
168    ///
169    /// ```rust
170    /// use owo_colors::{OwoColorize, Style, Styled};
171    ///
172    /// const STYLED_TEXT: Styled<&'static str> = Style::new().bold().italic().style("bold and italic text");
173    ///
174    /// println!("{}", STYLED_TEXT);
175    /// # assert_eq!(format!("{}", STYLED_TEXT), "\u{1b}[1;3mbold and italic text\u{1b}[0m");
176    /// ```
177    pub const fn style<T>(&self, target: T) -> Styled<T> {
178        Styled {
179            target,
180            style: *self,
181        }
182    }
183
184    /// Set the foreground color generically
185    ///
186    /// ```rust
187    /// use owo_colors::{OwoColorize, colors::*};
188    ///
189    /// println!("{}", "red foreground".fg::<Red>());
190    /// ```
191    #[must_use]
192    pub const fn fg<C: Color>(mut self) -> Self {
193        self.fg = Some(C::DYN_COLORS_EQUIVALENT);
194        self
195    }
196
197    /// Set the background color generically.
198    ///
199    /// ```rust
200    /// use owo_colors::{OwoColorize, colors::*};
201    ///
202    /// println!("{}", "black background".bg::<Black>());
203    /// ```
204    #[must_use]
205    pub const fn bg<C: Color>(mut self) -> Self {
206        self.bg = Some(C::DYN_COLORS_EQUIVALENT);
207        self
208    }
209
210    /// Removes the foreground color from the style. Note that this does not apply
211    /// the default color, but rather represents not changing the current terminal color.
212    ///
213    /// If you wish to actively change the terminal color back to the default, see
214    /// [`Style::default_color`].
215    #[must_use]
216    pub const fn remove_fg(mut self) -> Self {
217        self.fg = None;
218        self
219    }
220
221    /// Removes the background color from the style. Note that this does not apply
222    /// the default color, but rather represents not changing the current terminal color.
223    ///
224    /// If you wish to actively change the terminal color back to the default, see
225    /// [`Style::on_default_color`].
226    #[must_use]
227    pub const fn remove_bg(mut self) -> Self {
228        self.bg = None;
229        self
230    }
231
232    color_methods! {
233        /// Change the foreground color to black
234        /// Change the background color to black
235        Black    black    on_black,
236        /// Change the foreground color to red
237        /// Change the background color to red
238        Red      red      on_red,
239        /// Change the foreground color to green
240        /// Change the background color to green
241        Green    green    on_green,
242        /// Change the foreground color to yellow
243        /// Change the background color to yellow
244        Yellow   yellow   on_yellow,
245        /// Change the foreground color to blue
246        /// Change the background color to blue
247        Blue     blue     on_blue,
248        /// Change the foreground color to magenta
249        /// Change the background color to magenta
250        Magenta  magenta  on_magenta,
251        /// Change the foreground color to purple
252        /// Change the background color to purple
253        Magenta  purple   on_purple,
254        /// Change the foreground color to cyan
255        /// Change the background color to cyan
256        Cyan     cyan     on_cyan,
257        /// Change the foreground color to white
258        /// Change the background color to white
259        White    white    on_white,
260
261        /// Change the foreground color to the terminal default
262        /// Change the background color to the terminal default
263        Default default_color on_default_color,
264
265        /// Change the foreground color to bright black
266        /// Change the background color to bright black
267        BrightBlack    bright_black    on_bright_black,
268        /// Change the foreground color to bright red
269        /// Change the background color to bright red
270        BrightRed      bright_red      on_bright_red,
271        /// Change the foreground color to bright green
272        /// Change the background color to bright green
273        BrightGreen    bright_green    on_bright_green,
274        /// Change the foreground color to bright yellow
275        /// Change the background color to bright yellow
276        BrightYellow   bright_yellow   on_bright_yellow,
277        /// Change the foreground color to bright blue
278        /// Change the background color to bright blue
279        BrightBlue     bright_blue     on_bright_blue,
280        /// Change the foreground color to bright magenta
281        /// Change the background color to bright magenta
282        BrightMagenta  bright_magenta  on_bright_magenta,
283        /// Change the foreground color to bright purple
284        /// Change the background color to bright purple
285        BrightMagenta  bright_purple   on_bright_purple,
286        /// Change the foreground color to bright cyan
287        /// Change the background color to bright cyan
288        BrightCyan     bright_cyan     on_bright_cyan,
289        /// Change the foreground color to bright white
290        /// Change the background color to bright white
291        BrightWhite    bright_white    on_bright_white,
292    }
293
294    /// Make the text bold
295    #[must_use]
296    pub const fn bold(mut self) -> Self {
297        self.bold = true;
298        self
299    }
300
301    style_methods! {
302        /// Make the text dim
303        (dimmed, set_dimmed),
304        /// Make the text italicized
305        (italic, set_italic),
306        /// Make the text underlined
307        (underline, set_underline),
308        /// Make the text blink
309        (blink, set_blink),
310        /// Make the text blink (but fast!)
311        (blink_fast, set_blink_fast),
312        /// Swap the foreground and background colors
313        (reversed, set_reversed),
314        /// Hide the text
315        (hidden, set_hidden),
316        /// Cross out the text
317        (strikethrough, set_strikethrough),
318    }
319
320    #[must_use]
321    const fn set_effect(mut self, effect: Effect, to: bool) -> Self {
322        use Effect::*;
323        match effect {
324            Bold => {
325                self.bold = to;
326            }
327            Dimmed => {
328                // This somewhat contorted construction is required because const fns can't take
329                // mutable refs as of Rust 1.81.
330                self.style_flags = self.style_flags.set_dimmed(to);
331            }
332            Italic => {
333                self.style_flags = self.style_flags.set_italic(to);
334            }
335            Underline => {
336                self.style_flags = self.style_flags.set_underline(to);
337            }
338            Blink => {
339                self.style_flags = self.style_flags.set_blink(to);
340            }
341            BlinkFast => {
342                self.style_flags = self.style_flags.set_blink_fast(to);
343            }
344            Reversed => {
345                self.style_flags = self.style_flags.set_reversed(to);
346            }
347            Hidden => {
348                self.style_flags = self.style_flags.set_hidden(to);
349            }
350            Strikethrough => {
351                self.style_flags = self.style_flags.set_strikethrough(to);
352            }
353        }
354        self
355    }
356
357    #[must_use]
358    const fn set_effects(mut self, mut effects: &[Effect], to: bool) -> Self {
359        // This is basically a for loop that also works in const contexts.
360        while let [first, rest @ ..] = effects {
361            self = self.set_effect(*first, to);
362            effects = rest;
363        }
364        self
365    }
366
367    /// Apply a given effect from the style
368    #[must_use]
369    pub const fn effect(self, effect: Effect) -> Self {
370        self.set_effect(effect, true)
371    }
372
373    /// Remove a given effect from the style
374    #[must_use]
375    pub const fn remove_effect(self, effect: Effect) -> Self {
376        self.set_effect(effect, false)
377    }
378
379    /// Apply a given set of effects to the style
380    #[must_use]
381    pub const fn effects(self, effects: &[Effect]) -> Self {
382        self.set_effects(effects, true)
383    }
384
385    /// Remove a given set of effects from the style
386    #[must_use]
387    pub const fn remove_effects(self, effects: &[Effect]) -> Self {
388        self.set_effects(effects, false)
389    }
390
391    /// Disables all the given effects from the style
392    #[must_use]
393    pub const fn remove_all_effects(mut self) -> Self {
394        self.bold = false;
395        self.style_flags = StyleFlags::new();
396        self
397    }
398
399    /// Set the foreground color at runtime. Only use if you do not know which color will be used at
400    /// compile-time. If the color is constant, use either [`OwoColorize::fg`](crate::OwoColorize::fg) or
401    /// a color-specific method, such as [`OwoColorize::green`](crate::OwoColorize::green),
402    ///
403    /// ```rust
404    /// use owo_colors::{OwoColorize, AnsiColors};
405    ///
406    /// println!("{}", "green".color(AnsiColors::Green));
407    /// ```
408    #[must_use]
409    pub fn color<Color: DynColor>(mut self, color: Color) -> Self {
410        // Can't be const because `get_dyncolors_fg` is a trait method.
411        self.fg = Some(color.get_dyncolors_fg());
412        self
413    }
414
415    /// Set the background color at runtime. Only use if you do not know what color to use at
416    /// compile-time. If the color is constant, use either [`OwoColorize::bg`](crate::OwoColorize::bg) or
417    /// a color-specific method, such as [`OwoColorize::on_yellow`](crate::OwoColorize::on_yellow),
418    ///
419    /// ```rust
420    /// use owo_colors::{OwoColorize, AnsiColors};
421    ///
422    /// println!("{}", "yellow background".on_color(AnsiColors::BrightYellow));
423    /// ```
424    #[must_use]
425    pub fn on_color<Color: DynColor>(mut self, color: Color) -> Self {
426        // Can't be const because `get_dyncolors_bg` is a trait method.
427        self.bg = Some(color.get_dyncolors_bg());
428        self
429    }
430
431    /// Set the foreground color to a specific RGB value.
432    #[must_use]
433    pub const fn fg_rgb<const R: u8, const G: u8, const B: u8>(mut self) -> Self {
434        self.fg = Some(DynColors::Rgb(R, G, B));
435
436        self
437    }
438
439    /// Set the background color to a specific RGB value.
440    #[must_use]
441    pub const fn bg_rgb<const R: u8, const G: u8, const B: u8>(mut self) -> Self {
442        self.bg = Some(DynColors::Rgb(R, G, B));
443
444        self
445    }
446
447    /// Sets the foreground color to an RGB value.
448    #[must_use]
449    pub const fn truecolor(mut self, r: u8, g: u8, b: u8) -> Self {
450        self.fg = Some(DynColors::Rgb(r, g, b));
451        self
452    }
453
454    /// Sets the background color to an RGB value.
455    #[must_use]
456    pub const fn on_truecolor(mut self, r: u8, g: u8, b: u8) -> Self {
457        self.bg = Some(DynColors::Rgb(r, g, b));
458        self
459    }
460
461    /// Returns true if the style does not apply any formatting.
462    #[must_use]
463    #[inline]
464    pub const fn is_plain(&self) -> bool {
465        let s = &self;
466        !(s.fg.is_some() || s.bg.is_some() || s.bold) && s.style_flags.is_plain()
467    }
468
469    /// Returns a formatter for the style's ANSI prefix.
470    ///
471    /// This can be used to separate out the prefix and suffix of a style.
472    ///
473    /// # Example
474    ///
475    /// ```
476    /// use owo_colors::Style;
477    /// use std::fmt::Write;
478    ///
479    /// let style = Style::new().red().on_blue();
480    /// let prefix = style.prefix_formatter();
481    /// let suffix = style.suffix_formatter();
482    ///
483    /// // Write the prefix and suffix separately.
484    /// let mut output = String::new();
485    /// write!(output, "{}", prefix);
486    /// output.push_str("Hello");
487    /// write!(output, "{}", suffix);
488    ///
489    /// assert_eq!(output, "\x1b[31;44mHello\x1b[0m");
490    /// ```
491    pub const fn prefix_formatter(&self) -> StylePrefixFormatter {
492        StylePrefixFormatter(*self)
493    }
494
495    /// Returns a formatter for the style's ANSI suffix.
496    ///
497    /// This can be used to separate out the prefix and suffix of a style.
498    ///
499    /// # Example
500    ///
501    /// See [`Style::prefix_formatter`].
502    pub const fn suffix_formatter(&self) -> StyleSuffixFormatter {
503        StyleSuffixFormatter(*self)
504    }
505
506    /// Applies the ANSI-prefix for this style to the given formatter
507    #[inline]
508    #[allow(unused_assignments)]
509    pub fn fmt_prefix(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
510        let s = self;
511        let format_less_important_effects = s.style_flags != StyleFlags::default();
512        let format_effect = s.bold || format_less_important_effects;
513        let format_any = !self.is_plain();
514
515        let mut semicolon = false;
516
517        if format_any {
518            f.write_str("\x1b[")?;
519        }
520
521        if let Some(fg) = s.fg {
522            <DynColors as DynColor>::fmt_raw_ansi_fg(&fg, f)?;
523            semicolon = true;
524        }
525
526        if let Some(bg) = s.bg {
527            if s.fg.is_some() {
528                f.write_str(";")?;
529            }
530            <DynColors as DynColor>::fmt_raw_ansi_bg(&bg, f)?;
531            semicolon = true;
532        }
533
534        if format_effect {
535            if s.bold {
536                if semicolon {
537                    f.write_str(";")?;
538                }
539
540                f.write_str("1")?;
541
542                semicolon = true;
543            }
544
545            macro_rules! text_effect_fmt {
546                ($style:ident, $formatter:ident, $semicolon:ident, $(($attr:ident, $value:literal)),* $(,)?) => {
547                    $(
548                        if $style.style_flags.$attr() {
549                            if $semicolon {
550                                $formatter.write_str(";")?;
551                            }
552                            $formatter.write_str($value)?;
553
554                            $semicolon = true;
555                        }
556                    )+
557                }
558            }
559
560            if format_less_important_effects {
561                text_effect_fmt! {
562                    s, f, semicolon,
563                    (dimmed,        "2"),
564                    (italic,        "3"),
565                    (underline,     "4"),
566                    (blink,         "5"),
567                    (blink_fast,    "6"),
568                    (reversed,      "7"),
569                    (hidden,        "8"),
570                    (strikethrough, "9"),
571                }
572            }
573        }
574
575        if format_any {
576            f.write_str("m")?;
577        }
578        Ok(())
579    }
580
581    /// Applies the ANSI-suffix for this style to the given formatter
582    #[inline]
583    pub fn fmt_suffix(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
584        if !self.is_plain() {
585            f.write_str("\x1b[0m")?;
586        }
587        Ok(())
588    }
589}
590
591/// Formatter for the prefix of a [`Style`].
592///
593/// This is used to get the ANSI escape codes for the style without
594/// the suffix, which is useful for formatting the prefix separately.
595#[derive(Debug, Clone, Copy, PartialEq)]
596#[must_use = "this formatter does nothing unless displayed"]
597pub struct StylePrefixFormatter(Style);
598
599impl fmt::Display for StylePrefixFormatter {
600    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
601        self.0.fmt_prefix(f)
602    }
603}
604
605/// Formatter for the suffix of a [`Style`].
606///
607/// This is used to get the ANSI escape codes for the style without
608/// the prefix, which is useful for formatting the suffix separately.
609#[derive(Debug, Clone, Copy, PartialEq)]
610#[must_use = "this formatter does nothing unless displayed"]
611pub struct StyleSuffixFormatter(Style);
612
613impl fmt::Display for StyleSuffixFormatter {
614    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
615        self.0.fmt_suffix(f)
616    }
617}
618
619impl Default for Style {
620    fn default() -> Self {
621        Self::new()
622    }
623}
624
625/// Helper to create [`Style`]s more ergonomically
626pub const fn style() -> Style {
627    Style::new()
628}
629
630impl<T> Styled<T> {
631    /// Returns a reference to the inner value to be styled
632    pub const fn inner(&self) -> &T {
633        &self.target
634    }
635
636    /// Returns a mutable reference to the inner value to be styled.
637    ///
638    /// *This method is const on Rust 1.83+.*
639    #[cfg(const_mut_refs)]
640    pub const fn inner_mut(&mut self) -> &mut T {
641        &mut self.target
642    }
643
644    /// Returns a mutable reference to the inner value to be styled.
645    ///
646    /// *This method is const on Rust 1.83+.*
647    #[cfg(not(const_mut_refs))]
648    pub fn inner_mut(&mut self) -> &mut T {
649        &mut self.target
650    }
651}
652
653macro_rules! impl_fmt {
654    ($($trait:path),* $(,)?) => {
655        $(
656            impl<T: $trait> $trait for Styled<T> {
657                #[allow(unused_assignments)]
658                fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
659                    self.style.fmt_prefix(f)?;
660                    <T as $trait>::fmt(&self.target, f)?;
661                    self.style.fmt_suffix(f)
662                }
663            }
664        )*
665    };
666}
667
668impl_fmt! {
669    fmt::Display,
670    fmt::Debug,
671    fmt::UpperHex,
672    fmt::LowerHex,
673    fmt::Binary,
674    fmt::UpperExp,
675    fmt::LowerExp,
676    fmt::Octal,
677    fmt::Pointer,
678}
679
680#[cfg(test)]
681mod tests {
682    use super::*;
683    use crate::{AnsiColors, OwoColorize};
684
685    #[test]
686    fn size_of() {
687        let size = std::mem::size_of::<Style>();
688        assert_eq!(size, 10, "size of Style should be 10 bytes");
689    }
690
691    #[test]
692    fn test_it() {
693        let style = Style::new()
694            .bright_white()
695            .on_blue()
696            .bold()
697            .dimmed()
698            .italic()
699            .underline()
700            .blink()
701            //.blink_fast()
702            //.reversed()
703            //.hidden()
704            .strikethrough();
705        let s = style.style("TEST");
706        let s2 = format!("{}", &s);
707        println!("{}", &s2);
708        assert_eq!(&s2, "\u{1b}[97;44;1;2;3;4;5;9mTEST\u{1b}[0m");
709
710        let prefix = format!("{}", style.prefix_formatter());
711        assert_eq!(&prefix, "\u{1b}[97;44;1;2;3;4;5;9m");
712
713        let suffix = format!("{}", style.suffix_formatter());
714        assert_eq!(&suffix, "\u{1b}[0m");
715    }
716
717    #[test]
718    fn test_effects() {
719        use Effect::*;
720        let style = Style::new().effects(&[Strikethrough, Underline]);
721
722        let s = style.style("TEST");
723        let s2 = format!("{}", &s);
724        println!("{}", &s2);
725        assert_eq!(&s2, "\u{1b}[4;9mTEST\u{1b}[0m");
726    }
727
728    #[test]
729    fn test_color() {
730        let style = Style::new()
731            .color(AnsiColors::White)
732            .on_color(AnsiColors::Black);
733
734        let s = style.style("TEST");
735        let s2 = format!("{}", &s);
736        println!("{}", &s2);
737        assert_eq!(&s2, "\u{1b}[37;40mTEST\u{1b}[0m");
738    }
739
740    #[test]
741    fn test_truecolor() {
742        let style = Style::new().truecolor(255, 255, 255).on_truecolor(0, 0, 0);
743
744        let s = style.style("TEST");
745        let s2 = format!("{}", &s);
746        println!("{}", &s2);
747        assert_eq!(&s2, "\u{1b}[38;2;255;255;255;48;2;0;0;0mTEST\u{1b}[0m");
748    }
749
750    #[test]
751    fn test_string_reference() {
752        let style = Style::new().truecolor(255, 255, 255).on_truecolor(0, 0, 0);
753
754        let string = String::from("TEST");
755        let s = style.style(&string);
756        let s2 = format!("{}", &s);
757        println!("{}", &s2);
758        assert_eq!(&s2, "\u{1b}[38;2;255;255;255;48;2;0;0;0mTEST\u{1b}[0m");
759    }
760
761    #[test]
762    fn test_owocolorize() {
763        let style = Style::new().bright_white().on_blue();
764
765        let s = "TEST".style(style);
766        let s2 = format!("{}", &s);
767        println!("{}", &s2);
768        assert_eq!(&s2, "\u{1b}[97;44mTEST\u{1b}[0m");
769    }
770
771    #[test]
772    fn test_is_plain() {
773        let style = Style::new().bright_white().on_blue();
774
775        assert!(!style.is_plain());
776        assert!(Style::default().is_plain());
777
778        let string = String::from("TEST");
779        let s = Style::default().style(&string);
780        let s2 = format!("{}", &s);
781
782        assert_eq!(string, s2)
783    }
784
785    #[test]
786    fn test_inner() {
787        let style = Style::default();
788
789        let mut s = "TEST".style(style);
790
791        assert_eq!(&&"TEST", s.inner());
792
793        *s.inner_mut() = &"changed";
794        assert_eq!(&&"changed", s.inner());
795        assert_eq!("changed", format!("{}", s));
796    }
797}