crossterm/style/types/
attribute.rs

1use std::fmt::Display;
2
3#[cfg(feature = "serde")]
4use serde::{Deserialize, Serialize};
5
6use super::super::SetAttribute;
7
8// This macro generates the Attribute enum, its iterator
9// function, and the static array containing the sgr code
10// of each attribute
11macro_rules! Attribute {
12    (
13        $(
14            $(#[$inner:ident $($args:tt)*])*
15            $name:ident = $sgr:expr,
16        )*
17    ) => {
18        /// Represents an attribute.
19        ///
20        /// # Platform-specific Notes
21        ///
22        /// * Only UNIX and Windows 10 terminals do support text attributes.
23        /// * Keep in mind that not all terminals support all attributes.
24        /// * Crossterm implements almost all attributes listed in the
25        ///   [SGR parameters](https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_parameters).
26        ///
27        /// | Attribute | Windows | UNIX | Notes |
28        /// | :-- | :--: | :--: | :-- |
29        /// | `Reset` | ✓ | ✓ | |
30        /// | `Bold` | ✓ | ✓ | |
31        /// | `Dim` | ✓ | ✓ | |
32        /// | `Italic` | ? | ? | Not widely supported, sometimes treated as inverse. |
33        /// | `Underlined` | ✓ | ✓ | |
34        /// | `SlowBlink` | ? | ? | Not widely supported, sometimes treated as inverse. |
35        /// | `RapidBlink` | ? | ? | Not widely supported. MS-DOS ANSI.SYS; 150+ per minute. |
36        /// | `Reverse` | ✓ | ✓ | |
37        /// | `Hidden` | ✓ | ✓ | Also known as Conceal. |
38        /// | `Fraktur` | ✗ | ✓ | Legible characters, but marked for deletion. |
39        /// | `DefaultForegroundColor` | ? | ? | Implementation specific (according to standard). |
40        /// | `DefaultBackgroundColor` | ? | ? | Implementation specific (according to standard). |
41        /// | `Framed` | ? | ? | Not widely supported. |
42        /// | `Encircled` | ? | ? | This should turn on the encircled attribute. |
43        /// | `OverLined` | ? | ? | This should draw a line at the top of the text. |
44        ///
45        /// # Examples
46        ///
47        /// Basic usage:
48        ///
49        /// ```no_run
50        /// use crossterm::style::Attribute;
51        ///
52        /// println!(
53        ///     "{} Underlined {} No Underline",
54        ///     Attribute::Underlined,
55        ///     Attribute::NoUnderline
56        /// );
57        /// ```
58        ///
59        /// Style existing text:
60        ///
61        /// ```no_run
62        /// use crossterm::style::Stylize;
63        ///
64        /// println!("{}", "Bold text".bold());
65        /// println!("{}", "Underlined text".underlined());
66        /// println!("{}", "Negative text".negative());
67        /// ```
68        #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
69        #[derive(Copy, Clone, Debug, PartialEq, Eq, Ord, PartialOrd, Hash)]
70        #[non_exhaustive]
71        pub enum Attribute {
72            $(
73                $(#[$inner $($args)*])*
74                $name,
75            )*
76        }
77
78        pub static SGR: &'static[i16] = &[
79            $($sgr,)*
80        ];
81
82        impl Attribute {
83            /// Iterates over all the variants of the Attribute enum.
84            pub fn iterator() -> impl Iterator<Item = Attribute> {
85                use self::Attribute::*;
86                [ $($name,)* ].iter().copied()
87            }
88        }
89    }
90}
91
92Attribute! {
93    /// Resets all the attributes.
94    Reset = 0,
95    /// Increases the text intensity.
96    Bold = 1,
97    /// Decreases the text intensity.
98    Dim = 2,
99    /// Emphasises the text.
100    Italic = 3,
101    /// Underlines the text.
102    Underlined = 4,
103
104    // Other types of underlining
105    /// Double underlines the text.
106    DoubleUnderlined = 2,
107    /// Undercurls the text.
108    Undercurled = 3,
109    /// Underdots the text.
110    Underdotted = 4,
111    /// Underdashes the text.
112    Underdashed = 5,
113
114    /// Makes the text blinking (< 150 per minute).
115    SlowBlink = 5,
116    /// Makes the text blinking (>= 150 per minute).
117    RapidBlink = 6,
118    /// Swaps foreground and background colors.
119    Reverse = 7,
120    /// Hides the text (also known as Conceal).
121    Hidden = 8,
122    /// Crosses the text.
123    CrossedOut = 9,
124    /// Sets the [Fraktur](https://en.wikipedia.org/wiki/Fraktur) typeface.
125    ///
126    /// Mostly used for [mathematical alphanumeric symbols](https://en.wikipedia.org/wiki/Mathematical_Alphanumeric_Symbols).
127    Fraktur = 20,
128    /// Turns off the `Bold` attribute. - Inconsistent - Prefer to use NormalIntensity
129    NoBold = 21,
130    /// Switches the text back to normal intensity (no bold, italic).
131    NormalIntensity = 22,
132    /// Turns off the `Italic` attribute.
133    NoItalic = 23,
134    /// Turns off the `Underlined` attribute.
135    NoUnderline = 24,
136    /// Turns off the text blinking (`SlowBlink` or `RapidBlink`).
137    NoBlink = 25,
138    /// Turns off the `Reverse` attribute.
139    NoReverse = 27,
140    /// Turns off the `Hidden` attribute.
141    NoHidden = 28,
142    /// Turns off the `CrossedOut` attribute.
143    NotCrossedOut = 29,
144    /// Makes the text framed.
145    Framed = 51,
146    /// Makes the text encircled.
147    Encircled = 52,
148    /// Draws a line at the top of the text.
149    OverLined = 53,
150    /// Turns off the `Frame` and `Encircled` attributes.
151    NotFramedOrEncircled = 54,
152    /// Turns off the `OverLined` attribute.
153    NotOverLined = 55,
154}
155
156impl Display for Attribute {
157    fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> std::fmt::Result {
158        write!(f, "{}", SetAttribute(*self))?;
159        Ok(())
160    }
161}
162
163impl Attribute {
164    /// Returns a u32 with one bit set, which is the
165    /// signature of this attribute in the Attributes
166    /// bitset.
167    ///
168    /// The +1 enables storing Reset (whose index is 0)
169    ///  in the bitset Attributes.
170    #[inline(always)]
171    pub const fn bytes(self) -> u32 {
172        1 << ((self as u32) + 1)
173    }
174    /// Returns the SGR attribute value.
175    ///
176    /// See <https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_parameters>
177    pub fn sgr(self) -> String {
178        if (self as usize) > 4 && (self as usize) < 9 {
179            return "4:".to_string() + SGR[self as usize].to_string().as_str();
180        }
181        SGR[self as usize].to_string()
182    }
183}