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        }
532
533        if format_effect {
534            if s.bold {
535                if semicolon {
536                    f.write_str(";")?;
537                }
538
539                f.write_str("1")?;
540
541                semicolon = true;
542            }
543
544            macro_rules! text_effect_fmt {
545                ($style:ident, $formatter:ident, $semicolon:ident, $(($attr:ident, $value:literal)),* $(,)?) => {
546                    $(
547                        if $style.style_flags.$attr() {
548                            if $semicolon {
549                                $formatter.write_str(";")?;
550                            }
551                            $formatter.write_str($value)?;
552
553                            $semicolon = true;
554                        }
555                    )+
556                }
557            }
558
559            if format_less_important_effects {
560                text_effect_fmt! {
561                    s, f, semicolon,
562                    (dimmed,        "2"),
563                    (italic,        "3"),
564                    (underline,     "4"),
565                    (blink,         "5"),
566                    (blink_fast,    "6"),
567                    (reversed,      "7"),
568                    (hidden,        "8"),
569                    (strikethrough, "9"),
570                }
571            }
572        }
573
574        if format_any {
575            f.write_str("m")?;
576        }
577        Ok(())
578    }
579
580    /// Applies the ANSI-suffix for this style to the given formatter
581    #[inline]
582    pub fn fmt_suffix(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
583        if !self.is_plain() {
584            f.write_str("\x1b[0m")?;
585        }
586        Ok(())
587    }
588}
589
590/// Formatter for the prefix of a [`Style`].
591///
592/// This is used to get the ANSI escape codes for the style without
593/// the suffix, which is useful for formatting the prefix separately.
594#[derive(Debug, Clone, Copy, PartialEq)]
595#[must_use = "this formatter does nothing unless displayed"]
596pub struct StylePrefixFormatter(Style);
597
598impl fmt::Display for StylePrefixFormatter {
599    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
600        self.0.fmt_prefix(f)
601    }
602}
603
604/// Formatter for the suffix of a [`Style`].
605///
606/// This is used to get the ANSI escape codes for the style without
607/// the prefix, which is useful for formatting the suffix separately.
608#[derive(Debug, Clone, Copy, PartialEq)]
609#[must_use = "this formatter does nothing unless displayed"]
610pub struct StyleSuffixFormatter(Style);
611
612impl fmt::Display for StyleSuffixFormatter {
613    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
614        self.0.fmt_suffix(f)
615    }
616}
617
618impl Default for Style {
619    fn default() -> Self {
620        Self::new()
621    }
622}
623
624/// Helper to create [`Style`]s more ergonomically
625pub const fn style() -> Style {
626    Style::new()
627}
628
629impl<T> Styled<T> {
630    /// Returns a reference to the inner value to be styled
631    pub const fn inner(&self) -> &T {
632        &self.target
633    }
634
635    /// Returns a mutable reference to the inner value to be styled.
636    ///
637    /// *This method is const on Rust 1.83+.*
638    #[cfg(const_mut_refs)]
639    pub const fn inner_mut(&mut self) -> &mut T {
640        &mut self.target
641    }
642
643    /// Returns a mutable reference to the inner value to be styled.
644    ///
645    /// *This method is const on Rust 1.83+.*
646    #[cfg(not(const_mut_refs))]
647    pub fn inner_mut(&mut self) -> &mut T {
648        &mut self.target
649    }
650}
651
652macro_rules! impl_fmt {
653    ($($trait:path),* $(,)?) => {
654        $(
655            impl<T: $trait> $trait for Styled<T> {
656                #[allow(unused_assignments)]
657                fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
658                    self.style.fmt_prefix(f)?;
659                    <T as $trait>::fmt(&self.target, f)?;
660                    self.style.fmt_suffix(f)
661                }
662            }
663        )*
664    };
665}
666
667impl_fmt! {
668    fmt::Display,
669    fmt::Debug,
670    fmt::UpperHex,
671    fmt::LowerHex,
672    fmt::Binary,
673    fmt::UpperExp,
674    fmt::LowerExp,
675    fmt::Octal,
676    fmt::Pointer,
677}
678
679#[cfg(test)]
680mod tests {
681    use super::*;
682    use crate::{AnsiColors, OwoColorize};
683
684    #[test]
685    fn size_of() {
686        let size = std::mem::size_of::<Style>();
687        assert_eq!(size, 10, "size of Style should be 10 bytes");
688    }
689
690    #[test]
691    fn test_it() {
692        let style = Style::new()
693            .bright_white()
694            .on_blue()
695            .bold()
696            .dimmed()
697            .italic()
698            .underline()
699            .blink()
700            //.blink_fast()
701            //.reversed()
702            //.hidden()
703            .strikethrough();
704        let s = style.style("TEST");
705        let s2 = format!("{}", &s);
706        println!("{}", &s2);
707        assert_eq!(&s2, "\u{1b}[97;44;1;2;3;4;5;9mTEST\u{1b}[0m");
708
709        let prefix = format!("{}", style.prefix_formatter());
710        assert_eq!(&prefix, "\u{1b}[97;44;1;2;3;4;5;9m");
711
712        let suffix = format!("{}", style.suffix_formatter());
713        assert_eq!(&suffix, "\u{1b}[0m");
714    }
715
716    #[test]
717    fn test_effects() {
718        use Effect::*;
719        let style = Style::new().effects(&[Strikethrough, Underline]);
720
721        let s = style.style("TEST");
722        let s2 = format!("{}", &s);
723        println!("{}", &s2);
724        assert_eq!(&s2, "\u{1b}[4;9mTEST\u{1b}[0m");
725    }
726
727    #[test]
728    fn test_color() {
729        let style = Style::new()
730            .color(AnsiColors::White)
731            .on_color(AnsiColors::Black);
732
733        let s = style.style("TEST");
734        let s2 = format!("{}", &s);
735        println!("{}", &s2);
736        assert_eq!(&s2, "\u{1b}[37;40mTEST\u{1b}[0m");
737    }
738
739    #[test]
740    fn test_truecolor() {
741        let style = Style::new().truecolor(255, 255, 255).on_truecolor(0, 0, 0);
742
743        let s = style.style("TEST");
744        let s2 = format!("{}", &s);
745        println!("{}", &s2);
746        assert_eq!(&s2, "\u{1b}[38;2;255;255;255;48;2;0;0;0mTEST\u{1b}[0m");
747    }
748
749    #[test]
750    fn test_string_reference() {
751        let style = Style::new().truecolor(255, 255, 255).on_truecolor(0, 0, 0);
752
753        let string = String::from("TEST");
754        let s = style.style(&string);
755        let s2 = format!("{}", &s);
756        println!("{}", &s2);
757        assert_eq!(&s2, "\u{1b}[38;2;255;255;255;48;2;0;0;0mTEST\u{1b}[0m");
758    }
759
760    #[test]
761    fn test_owocolorize() {
762        let style = Style::new().bright_white().on_blue();
763
764        let s = "TEST".style(style);
765        let s2 = format!("{}", &s);
766        println!("{}", &s2);
767        assert_eq!(&s2, "\u{1b}[97;44mTEST\u{1b}[0m");
768    }
769
770    #[test]
771    fn test_is_plain() {
772        let style = Style::new().bright_white().on_blue();
773
774        assert!(!style.is_plain());
775        assert!(Style::default().is_plain());
776
777        let string = String::from("TEST");
778        let s = Style::default().style(&string);
779        let s2 = format!("{}", &s);
780
781        assert_eq!(string, s2)
782    }
783
784    #[test]
785    fn test_inner() {
786        let style = Style::default();
787
788        let mut s = "TEST".style(style);
789
790        assert_eq!(&&"TEST", s.inner());
791
792        *s.inner_mut() = &"changed";
793        assert_eq!(&&"changed", s.inner());
794        assert_eq!("changed", format!("{}", s));
795    }
796}