yansi/
attr_quirk.rs

1use crate::Style;
2
3/// Enum representing text attributes, largely for text formatting.
4///
5/// Text attributes are typically applied to a [`Style`], [`Color`], or
6/// [`Painted`] struct via the corresponding chainable builder methods such as
7/// [`bold()`] or [`italic()`]. The returned value will apply the attribute(s)
8/// when rendered or printed.
9///
10/// Attributes are idempotent, so applying an attribute more than once has no
11/// more affect than applying it once.
12///
13/// # Terminal Support
14///
15/// Whether an applied attribute actually has an effect on how text is rendered
16/// in a terminal depends on the terminal's support for the attribute as well as
17/// the terminal's configuration. Common attributes, such as `bold`, `dim`,
18/// `italic`, `underline`, and `strike` typically have good support and are
19/// largely reliable. Less commonly supported attributes like `conceal` and
20/// `invert` will _usually_ be supported by "modern" terminals. Rarely supported
21/// attributes, such as  `blink` and `rapid blink`, will typically have no
22/// effect when applied.
23///
24/// # Example
25///
26/// ```rust
27/// use yansi::{Style, Color::Red};
28///
29/// /// A style with red foreground and every "common" attribute applied.
30/// static MAD: Style = Red.bold().dim().italic().underline().strike();
31/// ```
32///
33/// [`Style`]: crate::Style
34/// [`Painted`]: crate::Painted
35/// [`Color`]: crate::Painted
36/// [`bold()`]: crate::Style::bold()
37/// [`italic()`]: crate::Style::italic()
38#[derive(Debug, PartialEq, Eq, Copy, Clone, PartialOrd, Ord, Hash)]
39pub enum Attribute {
40    /// Makes text <b>bold</b>.
41    ///
42    /// Typically used via the [`bold()`](crate::Style::bold()) builder method.
43    Bold,
44    /// Makes text <span style="opacity: 50%">dim</span>.
45    ///
46    /// Typically used via the [`dim()`](crate::Style::dim()) builder method.
47    Dim,
48    /// Display text in <i>italics</i>.
49    ///
50    /// Typically used via the [`italic()`](crate::Style::italic()) builder
51    /// method.
52    Italic,
53    /// <u>Underline</u> text.
54    ///
55    /// Typically used via the [`underline()`](crate::Style::underline())
56    /// builder method.
57    Underline,
58    /// <style>@keyframes blinker { 50% { opacity: 0; } }</style>
59    /// <span style="animation: blinker 1s linear infinite;">Blink.</span>
60    ///
61    /// Typically used via the [`blink()`](crate::Style::blink()) builder
62    /// method.
63    Blink,
64    /// <style>@keyframes blinker { 50% { opacity: 0; } }</style>
65    /// <span style="animation: blinker 0.5s linear infinite;">Blink rapidly.</span>
66    ///
67    /// Typically used via the [`rapid_blink()`](crate::Style::rapid_blink())
68    /// builder method.
69    RapidBlink,
70    /// <span style="background: black; color: white;">Invert</span>
71    /// (flip) the foreground and background colors.
72    ///
73    /// Typically used via the [`invert()`](crate::Style::invert()) builder
74    /// method.
75    Invert,
76    /// <span style="color: #333; background: #000;">Conceal</span> text.
77    ///
78    /// Typically used via the [`conceal()`](crate::Style::conceal()) builder
79    /// method.
80    Conceal,
81    /// Display text with a <s>strike</s> through it.
82    ///
83    /// Typically used via the [`strike()`](crate::Style::strike()) builder
84    /// method.
85    Strike,
86}
87
88/// Enum representing a `yansi` quirk.
89///
90/// See the [crate level docs](crate#quirks) for details.
91#[derive(Debug, PartialEq, Eq, Copy, Clone, PartialOrd, Ord, Hash)]
92pub enum Quirk {
93    /// Mask: omit when painting is disabled.
94    ///
95    /// Typically applied via the [`mask()`](crate::Painted::mask()) builder
96    /// method.
97    ///
98    /// See the [crate level docs](crate#masking) for details.
99    Mask,
100    /// Wrap the value: replace resets with the wrapped styling.
101    ///
102    /// Typically applied via the [`wrap()`](crate::Painted::wrap()) builder
103    /// method.
104    ///
105    /// See the [crate level docs](crate#wrapping) for details.
106    Wrap,
107    /// Linger: do not reset the style after it is applied.
108    ///
109    /// Typically applied via the [`linger()`](crate::Painted::linger()) builder
110    /// method.
111    ///
112    /// See the [crate level docs](crate#lingering) for details.
113    Linger,
114    /// **Deprecated:** Use [`Quirk::Resetting`] instead.
115    #[deprecated(
116        since = "1.0.1",
117        note = "renamed to `Resetting` due to builder method conflicts with `Vec::clear()`.\n\
118            `Quirk::Clear` will be removed in a future release."
119    )]
120    Clear,
121    /// Always reset styling afterwards, even if no actual styling was applied.
122    ///
123    /// Overrides the [`Linger`](Quirk::Linger) quirk if present.
124    ///
125    /// Typically applied via the [`resetting()`](crate::Painted::resetting())
126    /// builder method.
127    Resetting,
128    /// Brighten the foreground color if it is not already bright.
129    ///
130    /// Typically applied via the [`bright()`](crate::Painted::bright()) builder
131    /// method.
132    ///
133    /// See the [crate level docs](crate#brightening) for details.
134    Bright,
135    /// Brighten the background color if it is not already bright.
136    ///
137    /// Typically applied via the [`on_bright()`](crate::Painted::on_bright())
138    /// builder
139    /// method.
140    ///
141    /// See the [crate level docs](crate#brightening) for details.
142    OnBright,
143}
144
145set_enum! {
146    Attribute { Bold, Dim, Italic, Underline, Blink, RapidBlink, Invert, Conceal, Strike }
147}
148
149set_enum! {
150    Quirk { Mask, Wrap, Linger, Clear, Resetting, Bright, OnBright }
151}
152
153impl Attribute {
154    pub(crate) fn fmt(&self, f: &mut dyn core::fmt::Write) -> core::fmt::Result {
155        write!(f, "{}", match self {
156            Attribute::Bold => 1,
157            Attribute::Dim => 2,
158            Attribute::Italic => 3,
159            Attribute::Underline => 4,
160            Attribute::Blink => 5,
161            Attribute::RapidBlink => 6,
162            Attribute::Invert => 7,
163            Attribute::Conceal => 8,
164            Attribute::Strike => 9,
165        })
166    }
167
168    /// Returns a `Style` with the attribute `self` enabled.
169    ///
170    /// # Example
171    ///
172    /// ```rust
173    /// use yansi::{Style, Attribute::Bold};
174    ///
175    /// static EMBOLDEN: Style = Bold.style();
176    /// ```
177    pub const fn style(self) -> Style {
178        Style::new().attr(self)
179    }
180}
181
182impl Quirk {
183    /// Returns a `Style` with the quirk `self` enabled.
184    ///
185    /// # Example
186    ///
187    /// ```rust
188    /// use yansi::{Style, Quirk::Mask};
189    ///
190    /// static MASKED: Style = Mask.style();
191    /// ```
192    pub const fn style(self) -> Style {
193        Style::new().quirk(self)
194    }
195}
196
197impl From<Attribute> for crate::Style {
198    fn from(attr: Attribute) -> Self {
199        attr.style()
200    }
201}
202
203impl From<Quirk> for crate::Style {
204    fn from(quirk: Quirk) -> Self {
205        quirk.style()
206    }
207}