fluent_ansi/
styled.rs

1use core::fmt::{Display, Formatter, Result};
2
3use crate::{
4    Effect, GetEffects, Style, UnderlineEffect,
5    impl_macros::{
6        additive_styling::impl_additive_styling_methods,
7        composed_styling::impl_composed_styling_methods,
8    },
9    prelude::Color,
10};
11
12/// A value that associates some content with a specific style.
13#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
14pub struct Styled<C: Display> {
15    content: C,
16    style: Style,
17}
18
19impl<C: Display> Styled<C> {
20    /// Creates a new `Styled<C>` value with the given content and empty style.
21    #[must_use]
22    pub const fn new(content: C) -> Self {
23        Self {
24            content,
25            style: Style::new(),
26        }
27    }
28
29    /// Gets a reference to the enclosed content.
30    #[must_use]
31    pub const fn get_content(&self) -> &C {
32        &self.content
33    }
34
35    /// Returns a new `Styled<C2>` value with the same style and the given content.
36    #[must_use]
37    pub const fn with_content<C2: Display>(&self, content: C2) -> Styled<C2> {
38        Styled {
39            content,
40            style: self.style,
41        }
42    }
43
44    /// Consumes the `Styled<C>` value and returns the enclosed content.
45    #[must_use]
46    pub fn into_content(self) -> C {
47        self.content
48    }
49
50    /// Gets the current style.
51    #[must_use]
52    pub const fn get_style(&self) -> Style {
53        self.style
54    }
55
56    /// Returns a new `Styled<C>` value with the same content and the given style.
57    #[must_use]
58    pub fn with_style(self, style: Style) -> Styled<C> {
59        Self { style, ..self }
60    }
61
62    impl_additive_styling_methods! {
63        type ComposedStyling = Styled<C>;
64        args: [self];
65        to_composed_styling: { self }
66    }
67
68    impl_composed_styling_methods! {
69        args: [self, effect, underline_effect, target, color, value];
70        example_variable: r"styled";
71
72        set_effect: {
73            self.modify_style(|style| style.set_effect(effect, value))
74        }
75
76        get_effect: {
77            self.style.get_effect(effect)
78        }
79
80        get_effects: {
81            self.style.get_effects()
82        }
83
84        set_underline_effect: {
85            self.modify_style(|style| style.set_underline_effect(underline_effect))
86        }
87
88        get_underline_effect: {
89            self.style.get_underline_effect()
90        }
91
92        set_color: {
93            self.modify_style(|style| style.set_color(target, color))
94        }
95
96        get_color: {
97            self.style.get_color(target)
98        }
99    }
100
101    #[must_use]
102    fn modify_style(self, f: impl FnOnce(Style) -> Style) -> Self {
103        let style = f(self.style);
104        Self { style, ..self }
105    }
106}
107
108impl<C: Display> Display for Styled<C> {
109    fn fmt(&self, f: &mut Formatter<'_>) -> Result {
110        if self.style == Style::default() {
111            write!(f, "{}", self.content)
112        } else {
113            let start = self.style;
114            let end = Style::default();
115            write!(f, "{start}{}{end}", self.content)
116        }
117    }
118}