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}
184