yansi/
macros.rs

1macro_rules! set_enum {
2    ($T:ident { $($v:ident),+ $(,)? }) => {
3        impl $T {
4            pub(crate) const fn bit_mask(self) -> u16 {
5                1 << self as u16
6            }
7
8            pub(crate) const fn from_bit_mask(value: u16) -> Option<Self> {
9                $(if (value == $T::$v.bit_mask()) { return Some($T::$v); })+
10                None
11            }
12        }
13
14        impl crate::set::Set<$T> {
15            #[must_use]
16            pub const fn insert(mut self, value: $T) -> Self {
17                self.1 |= value.bit_mask();
18                self
19            }
20        }
21
22        impl crate::set::SetMember for $T {
23            const MAX_VALUE: u8 = { $($T::$v as u8);+ };
24            fn bit_mask(self) -> u16 { <$T>::bit_mask(self) }
25            fn from_bit_mask(v: u16) -> Option<Self> { <$T>::from_bit_mask(v) }
26        }
27    };
28}
29
30macro_rules! constructor {
31    (
32        [$($q:tt)*] $r:ty, $R:ty, $p:ident,
33        $(#[$pattr:meta])* $prop:ident => $V:path $([$($a:ident : $T:ty),+])?
34    ) => {
35        /// Returns `self` with the
36        #[doc = concat!("[`", stringify!($p), "()`](Self::", stringify!($p), "())")]
37        /// set to
38        #[doc = concat!("[`", stringify!($V), "`].")]
39        ///
40        /// # Example
41        ///
42        /// ```rust
43        #[doc = concat!(
44            "# let value = yansi::Painted::new(0);",
45            $($("\n# let ", stringify!($a), " = 0;"),+)?
46        )]
47        #[doc = concat!(
48            "println!(\"{}\", value.", stringify!($prop), "(", $(stringify!($($a),+),)? "));"
49        )]
50        /// ```
51        #[inline]
52        $(#[$pattr])*
53        $($q)* fn $prop(self: $r $($(,$a: $T)+)?) -> $R {
54            let v = $V $(($($a),*))?;
55            self.apply(crate::style::Application::$p(v))
56        }
57    };
58
59    ([$($q:tt)*] $(#[$attr:meta])* $r:ty, $R:ty, $kind:ident ($A:ty)) => {
60        $(#[$attr])*
61        #[inline]
62        $($q)* fn $kind(self: $r, value: $A) -> $R {
63            self.apply(crate::style::Application::$kind(value))
64        }
65    };
66}
67
68macro_rules! signature {
69    (
70        [$($q:tt)*] $r:ty, $R:ty, $p:ident,
71        $(#[$pattr:meta])* $prop:ident => $V:path $([$($a:ident : $T:ty),+])?
72    ) => {
73        /// Returns `self` with the
74        #[doc = concat!("[`", stringify!($p), "()`](Self::", stringify!($p), "())")]
75        /// set to
76        #[doc = concat!("[`", stringify!($V), "`].")]
77        ///
78        /// # Example
79        ///
80        /// ```rust
81        #[doc = concat!(
82            "# let value = yansi::Painted::new(0);",
83            $($("\n# let ", stringify!($a), " = 0;"),+)?
84        )]
85        #[doc = concat!(
86            "println!(\"{}\", value.", stringify!($prop), "(", $(stringify!($($a),+),)? "));"
87        )]
88        /// ```
89        $(#[$pattr])*
90        $($q)* fn $prop(self: $r $($(,$a: $T)+)?) -> $R;
91    };
92
93    ([$($q:tt)*] $(#[$attr:meta])* $r:ty, $R:ty, $kind:ident ($A:ty)) => {
94        $(#[$attr])*
95        $($q)* fn $kind(self: $r, value: $A) -> $R;
96    };
97}
98
99macro_rules! define_property {
100    ([$d:tt] $(#[$attr:meta])* $kind:ident ($A:ty) {
101        $($(#[$pattr:meta])* $prop:ident => $V:path $([$($a:tt)*])?),* $(,)?
102    }) => {
103        macro_rules! $kind {
104            ($d ([$d ($qual:tt)*])? $cont:ident ($r:ty) -> $R:ty) => (
105                $cont!([$d ($d ($qual)*)?] $(#[$attr])* $r, $R, $kind($A));
106
107                $(
108                    $cont!(
109                        [$d ($d ($qual)*)?]
110                        $r, $R, $kind, $(#[$pattr])* $prop => $V $([$($a)*] )?
111                    );
112                )*
113            )
114        }
115    };
116
117    ($(#[$attr:meta])* $kind:ident ($A:ty)) => {
118        define_property!([$] $(#[$attr])* $kind ($A) {});
119    };
120
121    ($($t:tt)*) => { define_property!([$] $($t)*); }
122}
123
124// Check that every variant of a property is covered.
125macro_rules! check_property_exhaustiveness {
126    ($A:ident $({ $($(#[$pattr:meta])* $p:ident => $V:path $([ $($a:tt)* ])?),* $(,)? })? ) => {
127        const _: () = {$(
128            use crate::*;
129            fn _check() {
130                #[allow(unreachable_code)]
131                match { let _v: $A = todo!(); _v } {
132                    $($V { .. } => { },)*
133                }
134            }
135        )?};
136    }
137}
138
139macro_rules! define_properties {
140    ($($(#[$attr:meta])* $kind:ident ($A:ident) $({ $($t:tt)* })?),* $(,)?) => {
141        $(define_property!($(#[$attr])* $kind($A) $({ $($t)* })?);)*
142        $(check_property_exhaustiveness!($A $({ $($t)* })?);)*
143    }
144}
145
146macro_rules! properties {
147    ($([$($qual:tt)*])? $cont:ident ($r:ty) -> $R:ty) => (
148        fg!($([$($qual)*])? $cont ($r) -> $R);
149        bg!($([$($qual)*])? $cont ($r) -> $R);
150        attr!($([$($qual)*])? $cont ($r) -> $R);
151        quirk!($([$($qual)*])? $cont ($r) -> $R);
152        whenever!($([$($qual)*])? $cont ($r) -> $R);
153    )
154}
155
156define_properties! {
157    /// Returns a styled value derived from `self` with the foreground set to
158    /// `value`.
159    ///
160    /// This method should be used rarely. Instead, prefer to use color-specific
161    /// builder methods like [`red()`](Self::red()) and
162    /// [`green()`](Self::green()), which have the same functionality but are
163    /// pithier.
164    ///
165    /// # Example
166    ///
167    /// Set foreground color to white using `fg()`:
168    ///
169    /// ```rust
170    /// use yansi::{Paint, Color};
171    ///
172    /// # let painted = ();
173    /// painted.fg(Color::White);
174    /// ```
175    ///
176    /// Set foreground color to white using [`white()`](Self::white()).
177    ///
178    /// ```rust
179    /// use yansi::Paint;
180    ///
181    /// # let painted = ();
182    /// painted.white();
183    /// ```
184    fg(Color) {
185        primary => Color::Primary,
186        fixed => Color::Fixed[color: u8],
187        rgb => Color::Rgb[r: u8, g: u8, b: u8],
188        black => Color::Black,
189        red => Color::Red,
190        green => Color::Green,
191        yellow => Color::Yellow,
192        blue => Color::Blue,
193        magenta => Color::Magenta,
194        cyan => Color::Cyan,
195        white => Color::White,
196        bright_black => Color::BrightBlack,
197        bright_red => Color::BrightRed,
198        bright_green => Color::BrightGreen,
199        bright_yellow => Color::BrightYellow,
200        bright_blue => Color::BrightBlue,
201        bright_magenta => Color::BrightMagenta,
202        bright_cyan => Color::BrightCyan,
203        bright_white => Color::BrightWhite,
204    },
205
206    /// Returns a styled value derived from `self` with the background set to
207    /// `value`.
208    ///
209    /// This method should be used rarely. Instead, prefer to use color-specific
210    /// builder methods like [`on_red()`](Self::on_red()) and
211    /// [`on_green()`](Self::on_green()), which have the same functionality but
212    /// are pithier.
213    ///
214    /// # Example
215    ///
216    /// Set background color to red using `fg()`:
217    ///
218    /// ```rust
219    /// use yansi::{Paint, Color};
220    ///
221    /// # let painted = ();
222    /// painted.bg(Color::Red);
223    /// ```
224    ///
225    /// Set background color to red using [`on_red()`](Self::on_red()).
226    ///
227    /// ```rust
228    /// use yansi::Paint;
229    ///
230    /// # let painted = ();
231    /// painted.on_red();
232    /// ```
233    bg(Color) {
234        on_primary => Color::Primary,
235        on_fixed => Color::Fixed[color: u8],
236        on_rgb => Color::Rgb[r: u8, g: u8, b: u8],
237        on_black => Color::Black,
238        on_red => Color::Red,
239        on_green => Color::Green,
240        on_yellow => Color::Yellow,
241        on_blue => Color::Blue,
242        on_magenta => Color::Magenta,
243        on_cyan => Color::Cyan,
244        on_white => Color::White,
245        on_bright_black => Color::BrightBlack,
246        on_bright_red => Color::BrightRed,
247        on_bright_green => Color::BrightGreen,
248        on_bright_yellow => Color::BrightYellow,
249        on_bright_blue => Color::BrightBlue,
250        on_bright_magenta => Color::BrightMagenta,
251        on_bright_cyan => Color::BrightCyan,
252        on_bright_white => Color::BrightWhite,
253    },
254
255    /// Enables the styling [`Attribute`] `value`.
256    ///
257    /// This method should be used rarely. Instead, prefer to use
258    /// attribute-specific builder methods like [`bold()`](Self::bold()) and
259    /// [`underline()`](Self::underline()), which have the same functionality
260    /// but are pithier.
261    ///
262    /// # Example
263    ///
264    /// Make text bold using `attr()`:
265    ///
266    /// ```rust
267    /// use yansi::{Paint, Attribute};
268    ///
269    /// # let painted = ();
270    /// painted.attr(Attribute::Bold);
271    /// ```
272    ///
273    /// Make text bold using using [`bold()`](Self::bold()).
274    ///
275    /// ```rust
276    /// use yansi::Paint;
277    ///
278    /// # let painted = ();
279    /// painted.bold();
280    /// ```
281    attr(Attribute) {
282        bold => Attribute::Bold,
283        dim => Attribute::Dim,
284        italic => Attribute::Italic,
285        underline => Attribute::Underline,
286        blink => Attribute::Blink,
287        rapid_blink => Attribute::RapidBlink,
288        invert => Attribute::Invert,
289        conceal => Attribute::Conceal,
290        strike => Attribute::Strike,
291    },
292
293    /// Enables the `yansi` [`Quirk`] `value`.
294    ///
295    /// This method should be used rarely. Instead, prefer to use quirk-specific
296    /// builder methods like [`mask()`](Self::mask()) and
297    /// [`wrap()`](Self::wrap()), which have the same functionality but are
298    /// pithier.
299    ///
300    /// # Example
301    ///
302    /// Enable wrapping using `.quirk()`:
303    ///
304    /// ```rust
305    /// use yansi::{Paint, Quirk};
306    ///
307    /// # let painted = ();
308    /// painted.quirk(Quirk::Wrap);
309    /// ```
310    ///
311    /// Enable wrapping using [`wrap()`](Self::wrap()).
312    ///
313    /// ```rust
314    /// use yansi::Paint;
315    ///
316    /// # let painted = ();
317    /// painted.wrap();
318    /// ```
319    quirk(Quirk) {
320        mask => Quirk::Mask,
321        wrap => Quirk::Wrap,
322        linger => Quirk::Linger,
323        #[deprecated(
324            since = "1.0.1",
325            note = "renamed to `resetting()` due to conflicts with `Vec::clear()`.\n\
326                The `clear()` method will be removed in a future release."
327        )]
328        clear => Quirk::Clear,
329        resetting => Quirk::Resetting,
330        bright => Quirk::Bright,
331        on_bright => Quirk::OnBright,
332    },
333
334    /// Conditionally enable styling based on whether the [`Condition`] `value`
335    /// applies. Replaces any previous condition.
336    ///
337    /// See the [crate level docs](crate#per-style) for more details.
338    ///
339    /// # Example
340    ///
341    /// Enable styling `painted` only when both `stdout` and `stderr` are TTYs:
342    ///
343    /// ```rust
344    /// # #[cfg(feature = "detect-tty")] {
345    /// use yansi::{Paint, Condition};
346    ///
347    /// # let painted = ();
348    /// painted.red().on_yellow().whenever(Condition::STDOUTERR_ARE_TTY);
349    /// # }
350    /// ```
351    whenever(Condition),
352}
353
354macro_rules! impl_fmt_trait {
355    ($F:path, $f:literal <$G:ident> $T:ty => $s:ident.$v:ident ($V:ty)) => {
356        impl<$G: $F> $F for $T {
357            fn fmt(&$s, f: &mut core::fmt::Formatter) -> core::fmt::Result {
358                $s.fmt_args(&<$V>::fmt, f, format_args!($f, $s.$v))
359            }
360        }
361    };
362}
363
364macro_rules! impl_fmt_traits {
365    ($($t:tt)*) => {
366        impl_fmt_trait!(core::fmt::Display, "{}" $($t)*);
367        impl_fmt_trait!(core::fmt::Debug, "{:?}" $($t)*);
368        impl_fmt_trait!(core::fmt::Octal, "{:o}" $($t)*);
369        impl_fmt_trait!(core::fmt::LowerHex, "{:x}" $($t)*);
370        impl_fmt_trait!(core::fmt::UpperHex, "{:X}" $($t)*);
371        impl_fmt_trait!(core::fmt::Pointer, "{:p}" $($t)*);
372        impl_fmt_trait!(core::fmt::Binary, "{:b}" $($t)*);
373        impl_fmt_trait!(core::fmt::LowerExp, "{:e}" $($t)*);
374        impl_fmt_trait!(core::fmt::UpperExp, "{:E}" $($t)*);
375    };
376}