owo_colors/
styles.rs

1//! Different display styles (strikethrough, bold, etc.)
2use core::fmt;
3
4#[allow(unused_imports)]
5use crate::OwoColorize;
6use crate::{Style, Styled};
7
8macro_rules! impl_fmt_for_style {
9    ($(($ty:ident, $trait:path, $ansi:literal)),* $(,)?) => {
10        $(
11            impl<'a, T: ?Sized + $trait> $trait for $ty<'a, T> {
12                fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
13                    f.write_str($ansi)?;
14                    <_ as $trait>::fmt(&self.0, f)?;
15                    f.write_str("\x1b[0m")
16                }
17            }
18        )*
19    };
20}
21
22/// Transparent wrapper around a type which implements all the formatters the wrapped type does,
23/// with the addition of boldening it. Recommended to be constructed using
24/// [`OwoColorize`](OwoColorize::bold).
25#[repr(transparent)]
26pub struct BoldDisplay<'a, T: ?Sized>(pub &'a T);
27
28impl<'a, T: ?Sized> BoldDisplay<'a, T> {
29    /// Convert self to a generic [`Styled`].
30    ///
31    /// This method erases color-related type parameters, and can be
32    /// used to unify types across branches.
33    ///
34    /// # Example
35    ///
36    /// ```rust
37    /// use owo_colors::OwoColorize;
38    ///
39    /// fn is_bold() -> bool {
40    ///     // ...
41    ///     # true
42    /// }
43    ///
44    /// let styled_str = if is_bold() {
45    ///     "hello".bold().into_styled()
46    /// } else {
47    ///     "hello".dimmed().into_styled()
48    /// };
49    ///
50    /// println!("{}", styled_str);
51    /// # assert_eq!(styled_str.to_string(), "\x1b[1mhello\x1b[0m");
52    /// ```
53    pub const fn into_styled(self) -> Styled<&'a T> {
54        let style = Style::new().bold();
55        Styled {
56            style,
57            target: self.0,
58        }
59    }
60}
61
62/// Transparent wrapper around a type which implements all the formatters the wrapped type does,
63/// with the addition of dimming it. Recommended to be constructed using
64/// [`OwoColorize`](OwoColorize::dimmed).
65#[repr(transparent)]
66pub struct DimDisplay<'a, T: ?Sized>(pub &'a T);
67
68impl<'a, T: ?Sized> DimDisplay<'a, T> {
69    /// Convert self to a generic [`Styled`].
70    ///
71    /// This method erases color-related type parameters, and can be
72    /// used to unify types across branches.
73    ///
74    /// # Example
75    ///
76    /// ```rust
77    /// use owo_colors::OwoColorize;
78    ///
79    /// fn is_dimmed() -> bool {
80    ///     // ...
81    ///     # true
82    /// }
83    ///
84    /// let styled_str = if is_dimmed() {
85    ///     "hello".dimmed().into_styled()
86    /// } else {
87    ///     "hello".bold().into_styled()
88    /// };
89    ///
90    /// println!("{}", styled_str);
91    /// # assert_eq!(styled_str.to_string(), "\x1b[2mhello\x1b[0m");
92    /// ```
93    pub const fn into_styled(self) -> Styled<&'a T> {
94        let style = Style::new().dimmed();
95        Styled {
96            style,
97            target: self.0,
98        }
99    }
100}
101
102/// Transparent wrapper around a type which implements all the formatters the wrapped type does,
103/// with the addition of italics. Recommended to be constructed using
104/// [`OwoColorize`](OwoColorize::italic).
105#[repr(transparent)]
106pub struct ItalicDisplay<'a, T: ?Sized>(pub &'a T);
107
108impl<'a, T: ?Sized> ItalicDisplay<'a, T> {
109    /// Convert self to a generic [`Styled`].
110    ///
111    /// This method erases color-related type parameters, and can be
112    /// used to unify types across branches.
113    ///
114    /// # Example
115    ///
116    /// ```rust
117    /// use owo_colors::OwoColorize;
118    ///
119    /// fn is_italic() -> bool {
120    ///     // ...
121    ///     # true
122    /// }
123    ///
124    /// let styled_str = if is_italic() {
125    ///     "hello".italic().into_styled()
126    /// } else {
127    ///     "hello".underline().into_styled()
128    /// };
129    ///
130    /// println!("{}", styled_str);
131    /// # assert_eq!(styled_str.to_string(), "\x1b[3mhello\x1b[0m");
132    /// ```
133    pub const fn into_styled(self) -> Styled<&'a T> {
134        let style = Style::new().italic();
135        Styled {
136            style,
137            target: self.0,
138        }
139    }
140}
141
142/// Transparent wrapper around a type which implements all the formatters the wrapped type does,
143/// while underlining it. Recommended to be constructed using
144/// [`OwoColorize`](OwoColorize::underline).
145#[repr(transparent)]
146pub struct UnderlineDisplay<'a, T: ?Sized>(pub &'a T);
147
148impl<'a, T: ?Sized> UnderlineDisplay<'a, T> {
149    /// Convert self to a generic [`Styled`].
150    ///
151    /// This method erases color-related type parameters, and can be
152    /// used to unify types across branches.
153    ///
154    /// # Example
155    ///
156    /// ```rust
157    /// use owo_colors::OwoColorize;
158    ///
159    /// fn is_underline() -> bool {
160    ///     // ...
161    ///     # true
162    /// }
163    ///
164    /// let styled_str = if is_underline() {
165    ///     "hello".underline().into_styled()
166    /// } else {
167    ///     "hello".italic().into_styled()
168    /// };
169    ///
170    /// println!("{}", styled_str);
171    /// # assert_eq!(styled_str.to_string(), "\x1b[4mhello\x1b[0m");
172    /// ```
173    pub const fn into_styled(self) -> Styled<&'a T> {
174        let style = Style::new().underline();
175        Styled {
176            style,
177            target: self.0,
178        }
179    }
180}
181
182/// Transparent wrapper around a type which implements all the formatters the wrapped type does,
183/// while blinking. Recommended to be constructed using
184/// [`OwoColorize`](OwoColorize::blink).
185#[repr(transparent)]
186pub struct BlinkDisplay<'a, T: ?Sized>(pub &'a T);
187
188impl<'a, T: ?Sized> BlinkDisplay<'a, T> {
189    /// Convert self to a generic [`Styled`].
190    ///
191    /// This method erases color-related type parameters, and can be
192    /// used to unify types across branches.
193    ///
194    /// # Example
195    ///
196    /// ```rust
197    /// use owo_colors::OwoColorize;
198    ///
199    /// fn is_blink() -> bool {
200    ///     // ...
201    ///     # true
202    /// }
203    ///
204    /// let styled_str = if is_blink() {
205    ///     "hello".blink().into_styled()
206    /// } else {
207    ///     "hello".hidden().into_styled()
208    /// };
209    ///
210    /// println!("{}", styled_str);
211    /// # assert_eq!(styled_str.to_string(), "\x1b[5mhello\x1b[0m");
212    /// ```
213    pub const fn into_styled(self) -> Styled<&'a T> {
214        let style = Style::new().blink();
215        Styled {
216            style,
217            target: self.0,
218        }
219    }
220}
221
222/// Transparent wrapper around a type which implements all the formatters the wrapped type does,
223/// with the addition of making it blink fast. Use [`OwoColorize`](OwoColorize::blink_fast)
224#[repr(transparent)]
225pub struct BlinkFastDisplay<'a, T: ?Sized>(pub &'a T);
226
227impl<'a, T: ?Sized> BlinkFastDisplay<'a, T> {
228    /// Convert self to a generic [`Styled`].
229    ///
230    /// This method erases color-related type parameters, and can be
231    /// used to unify types across branches.
232    ///
233    /// # Example
234    ///
235    /// ```rust
236    /// use owo_colors::OwoColorize;
237    ///
238    /// fn is_blink_fast() -> bool {
239    ///     // ...
240    ///     # true
241    /// }
242    ///
243    /// let styled_str = if is_blink_fast() {
244    ///     "hello".blink_fast().into_styled()
245    /// } else {
246    ///     "hello".reversed().into_styled()
247    /// };
248    ///
249    /// println!("{}", styled_str);
250    /// # assert_eq!(styled_str.to_string(), "\x1b[6mhello\x1b[0m");
251    /// ```
252    pub const fn into_styled(self) -> Styled<&'a T> {
253        let style = Style::new().blink_fast();
254        Styled {
255            style,
256            target: self.0,
257        }
258    }
259}
260
261/// Transparent wrapper around a type which implements all the formatters the wrapped type does,
262/// with the addition of swapping fg and bg colors. Use [`OwoColorize`](OwoColorize::reversed)
263#[repr(transparent)]
264pub struct ReversedDisplay<'a, T: ?Sized>(pub &'a T);
265
266impl<'a, T: ?Sized> ReversedDisplay<'a, T> {
267    /// Convert self to a generic [`Styled`].
268    ///
269    /// This method erases color-related type parameters, and can be
270    /// used to unify types across branches.
271    ///
272    /// # Example
273    ///
274    /// ```rust
275    /// use owo_colors::OwoColorize;
276    ///
277    /// fn is_reversed() -> bool {
278    ///     // ...
279    ///     # true
280    /// }
281    ///
282    /// let styled_str = if is_reversed() {
283    ///     "hello".reversed().into_styled()
284    /// } else {
285    ///     "hello".blink_fast().into_styled()
286    /// };
287    ///
288    /// println!("{}", styled_str);
289    /// # assert_eq!(styled_str.to_string(), "\x1b[7mhello\x1b[0m");
290    /// ```
291    pub const fn into_styled(self) -> Styled<&'a T> {
292        let style = Style::new().reversed();
293        Styled {
294            style,
295            target: self.0,
296        }
297    }
298}
299
300/// Transparent wrapper around a type which implements all the formatters the wrapped type does,
301/// with the addition of hiding the text. Use [`OwoColorize`](OwoColorize::hidden).
302#[repr(transparent)]
303pub struct HiddenDisplay<'a, T: ?Sized>(pub &'a T);
304
305impl<'a, T: ?Sized> HiddenDisplay<'a, T> {
306    /// Convert self to a generic [`Styled`].
307    ///
308    /// This method erases color-related type parameters, and can be
309    /// used to unify types across branches.
310    ///
311    /// # Example
312    ///
313    /// ```rust
314    /// use owo_colors::OwoColorize;
315    ///
316    /// fn is_hidden() -> bool {
317    ///     // ...
318    ///     # true
319    /// }
320    ///
321    /// let styled_str = if is_hidden() {
322    ///     "hello".hidden().into_styled()
323    /// } else {
324    ///     "hello".blink().into_styled()
325    /// };
326    ///
327    /// println!("{}", styled_str);
328    /// # assert_eq!(styled_str.to_string(), "\x1b[8mhello\x1b[0m");
329    /// ```
330    pub const fn into_styled(self) -> Styled<&'a T> {
331        let style = Style::new().hidden();
332        Styled {
333            style,
334            target: self.0,
335        }
336    }
337}
338
339/// Transparent wrapper around a type which implements all the formatters the wrapped type does,
340/// crossed out. Recommended to be constructed using
341/// [`OwoColorize`](OwoColorize::strikethrough).
342#[repr(transparent)]
343pub struct StrikeThroughDisplay<'a, T: ?Sized>(pub &'a T);
344
345impl<'a, T: ?Sized> StrikeThroughDisplay<'a, T> {
346    /// Convert self to a generic [`Styled`].
347    ///
348    /// This method erases color-related type parameters, and can be
349    /// used to unify types across branches.
350    ///
351    /// # Example
352    ///
353    /// ```rust
354    /// use owo_colors::OwoColorize;
355    ///
356    /// fn is_strike_through() -> bool {
357    ///     // ...
358    ///     # true
359    /// }
360    ///
361    /// let styled_str = if is_strike_through() {
362    ///     "hello".strikethrough().into_styled()
363    /// } else {
364    ///     "hello".hidden().into_styled()
365    /// };
366    ///
367    /// println!("{}", styled_str);
368    /// # assert_eq!(styled_str.to_string(), "\x1b[9mhello\x1b[0m");
369    /// ```
370    pub const fn into_styled(self) -> Styled<&'a T> {
371        let style = Style::new().strikethrough();
372        Styled {
373            style,
374            target: self.0,
375        }
376    }
377}
378
379impl_fmt_for_style! {
380    // Bold
381    (BoldDisplay, fmt::Display,  "\x1b[1m"),
382    (BoldDisplay, fmt::Debug,    "\x1b[1m"),
383    (BoldDisplay, fmt::UpperHex, "\x1b[1m"),
384    (BoldDisplay, fmt::LowerHex, "\x1b[1m"),
385    (BoldDisplay, fmt::Binary,   "\x1b[1m"),
386    (BoldDisplay, fmt::UpperExp, "\x1b[1m"),
387    (BoldDisplay, fmt::LowerExp, "\x1b[1m"),
388    (BoldDisplay, fmt::Octal,    "\x1b[1m"),
389    (BoldDisplay, fmt::Pointer,  "\x1b[1m"),
390
391    // Dim
392    (DimDisplay, fmt::Display,  "\x1b[2m"),
393    (DimDisplay, fmt::Debug,    "\x1b[2m"),
394    (DimDisplay, fmt::UpperHex, "\x1b[2m"),
395    (DimDisplay, fmt::LowerHex, "\x1b[2m"),
396    (DimDisplay, fmt::Binary,   "\x1b[2m"),
397    (DimDisplay, fmt::UpperExp, "\x1b[2m"),
398    (DimDisplay, fmt::LowerExp, "\x1b[2m"),
399    (DimDisplay, fmt::Octal,    "\x1b[2m"),
400    (DimDisplay, fmt::Pointer,  "\x1b[2m"),
401
402    // Italic
403    (ItalicDisplay, fmt::Display,  "\x1b[3m"),
404    (ItalicDisplay, fmt::Debug,    "\x1b[3m"),
405    (ItalicDisplay, fmt::UpperHex, "\x1b[3m"),
406    (ItalicDisplay, fmt::LowerHex, "\x1b[3m"),
407    (ItalicDisplay, fmt::Binary,   "\x1b[3m"),
408    (ItalicDisplay, fmt::UpperExp, "\x1b[3m"),
409    (ItalicDisplay, fmt::LowerExp, "\x1b[3m"),
410    (ItalicDisplay, fmt::Octal,    "\x1b[3m"),
411    (ItalicDisplay, fmt::Pointer,  "\x1b[3m"),
412
413    // Underline
414    (UnderlineDisplay, fmt::Display,  "\x1b[4m"),
415    (UnderlineDisplay, fmt::Debug,    "\x1b[4m"),
416    (UnderlineDisplay, fmt::UpperHex, "\x1b[4m"),
417    (UnderlineDisplay, fmt::LowerHex, "\x1b[4m"),
418    (UnderlineDisplay, fmt::Binary,   "\x1b[4m"),
419    (UnderlineDisplay, fmt::UpperExp, "\x1b[4m"),
420    (UnderlineDisplay, fmt::LowerExp, "\x1b[4m"),
421    (UnderlineDisplay, fmt::Octal,    "\x1b[4m"),
422    (UnderlineDisplay, fmt::Pointer,  "\x1b[4m"),
423
424    // Blink
425    (BlinkDisplay, fmt::Display,  "\x1b[5m"),
426    (BlinkDisplay, fmt::Debug,    "\x1b[5m"),
427    (BlinkDisplay, fmt::UpperHex, "\x1b[5m"),
428    (BlinkDisplay, fmt::LowerHex, "\x1b[5m"),
429    (BlinkDisplay, fmt::Binary,   "\x1b[5m"),
430    (BlinkDisplay, fmt::UpperExp, "\x1b[5m"),
431    (BlinkDisplay, fmt::LowerExp, "\x1b[5m"),
432    (BlinkDisplay, fmt::Octal,    "\x1b[5m"),
433    (BlinkDisplay, fmt::Pointer,  "\x1b[5m"),
434
435    // Blink fast
436    (BlinkFastDisplay, fmt::Display,  "\x1b[6m"),
437    (BlinkFastDisplay, fmt::Debug,    "\x1b[6m"),
438    (BlinkFastDisplay, fmt::UpperHex, "\x1b[6m"),
439    (BlinkFastDisplay, fmt::LowerHex, "\x1b[6m"),
440    (BlinkFastDisplay, fmt::Binary,   "\x1b[6m"),
441    (BlinkFastDisplay, fmt::UpperExp, "\x1b[6m"),
442    (BlinkFastDisplay, fmt::LowerExp, "\x1b[6m"),
443    (BlinkFastDisplay, fmt::Octal,    "\x1b[6m"),
444    (BlinkFastDisplay, fmt::Pointer,  "\x1b[6m"),
445
446    // Reverse video
447    (ReversedDisplay, fmt::Display,  "\x1b[7m"),
448    (ReversedDisplay, fmt::Debug,    "\x1b[7m"),
449    (ReversedDisplay, fmt::UpperHex, "\x1b[7m"),
450    (ReversedDisplay, fmt::LowerHex, "\x1b[7m"),
451    (ReversedDisplay, fmt::Binary,   "\x1b[7m"),
452    (ReversedDisplay, fmt::UpperExp, "\x1b[7m"),
453    (ReversedDisplay, fmt::LowerExp, "\x1b[7m"),
454    (ReversedDisplay, fmt::Octal,    "\x1b[7m"),
455    (ReversedDisplay, fmt::Pointer,  "\x1b[7m"),
456
457    // Hide the text
458    (HiddenDisplay, fmt::Display,  "\x1b[8m"),
459    (HiddenDisplay, fmt::Debug,    "\x1b[8m"),
460    (HiddenDisplay, fmt::UpperHex, "\x1b[8m"),
461    (HiddenDisplay, fmt::LowerHex, "\x1b[8m"),
462    (HiddenDisplay, fmt::Binary,   "\x1b[8m"),
463    (HiddenDisplay, fmt::UpperExp, "\x1b[8m"),
464    (HiddenDisplay, fmt::LowerExp, "\x1b[8m"),
465    (HiddenDisplay, fmt::Octal,    "\x1b[8m"),
466    (HiddenDisplay, fmt::Pointer,  "\x1b[8m"),
467
468    // StrikeThrough
469    (StrikeThroughDisplay, fmt::Display,  "\x1b[9m"),
470    (StrikeThroughDisplay, fmt::Debug,    "\x1b[9m"),
471    (StrikeThroughDisplay, fmt::UpperHex, "\x1b[9m"),
472    (StrikeThroughDisplay, fmt::LowerHex, "\x1b[9m"),
473    (StrikeThroughDisplay, fmt::Binary,   "\x1b[9m"),
474    (StrikeThroughDisplay, fmt::UpperExp, "\x1b[9m"),
475    (StrikeThroughDisplay, fmt::LowerExp, "\x1b[9m"),
476    (StrikeThroughDisplay, fmt::Octal,    "\x1b[9m"),
477    (StrikeThroughDisplay, fmt::Pointer,  "\x1b[9m"),
478}