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}