peter/
lib.rs

1//! Peter builds on the [`ansi_term`] crate to allow styling of anything
2//! implementing [`Display`] and makes colorizing text less verbose to use by
3//! providing the [`Stylize`] trait.
4//!
5//! # Examples
6//!
7//! ```rust
8//! use peter::Stylize;
9//!
10//! println!("This is in red: {}", "a red string".red());
11//!
12//! println!("How about some {}?", "bold and underline".bold().underline());
13//! ```
14
15#![no_std]
16
17use core::fmt;
18use core::fmt::Display;
19use core::ops::{Deref, DerefMut};
20
21use ansi_term::Style;
22
23/// See [`ansi_term::Color`].
24///
25pub use ansi_term::Color;
26
27/// Wraps something in a [`Style`].
28#[derive(Debug, Clone, Copy, PartialEq)]
29pub struct Styled<T> {
30    inner: T,
31    style: Style,
32}
33
34macro_rules! meth_color {
35    ($meth:ident, $color:ident) => {
36        pub fn $meth(self) -> Self {
37            self.fg(Color::$color)
38        }
39    };
40    ($meth:ident, $color:ident($($arg:ident),+)) => {
41        pub fn $meth(self, $($arg: u8),+) -> Self {
42            self.fg(Color::$color($($arg),+))
43        }
44    };
45}
46
47macro_rules! meth_style {
48    ($meth:ident) => {
49        pub fn $meth(self) -> Self {
50            let Self { inner, style } = self;
51            Self {
52                inner,
53                style: style.$meth(),
54            }
55        }
56    };
57    ($meth:ident, $color:ident) => {
58        pub fn $meth(self, $color: Color) -> Self {
59            let Self { inner, style } = self;
60            Self {
61                inner,
62                style: style.$meth($color),
63            }
64        }
65    };
66}
67
68impl<T> Styled<T> {
69    /// Construct a new `Styled`.
70    fn new(inner: T) -> Self {
71        Self {
72            inner,
73            style: Style::new(),
74        }
75    }
76
77    // different styles
78    meth_style!(bold);
79    meth_style!(dimmed);
80    meth_style!(italic);
81    meth_style!(underline);
82    meth_style!(blink);
83    meth_style!(reverse);
84    meth_style!(hidden);
85    meth_style!(strikethrough);
86    meth_style!(fg, color);
87    meth_style!(on, color);
88
89    // different colors
90    meth_color!(black, Black);
91    meth_color!(red, Red);
92    meth_color!(green, Green);
93    meth_color!(yellow, Yellow);
94    meth_color!(blue, Blue);
95    meth_color!(magenta, Purple);
96    meth_color!(cyan, Cyan);
97    meth_color!(white, White);
98    meth_color!(fixed, Fixed(n));
99    meth_color!(rgb, RGB(r, g, b));
100}
101
102impl<T> Deref for Styled<T> {
103    type Target = T;
104
105    fn deref(&self) -> &Self::Target {
106        &self.inner
107    }
108}
109
110impl<T> DerefMut for Styled<T> {
111    fn deref_mut(&mut self) -> &mut Self::Target {
112        &mut self.inner
113    }
114}
115
116impl<T: Display> Display for Styled<T> {
117    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
118        write!(f, "{}", self.style.prefix())?;
119        Display::fmt(&self.inner, f)?;
120        write!(f, "{}", self.style.suffix())?;
121        Ok(())
122    }
123}
124
125macro_rules! meth_color {
126    ($meth:ident, $color:ident) => {
127        fn $meth(&self) -> Styled<&Self> {
128            self.fg(Color::$color)
129        }
130    };
131    ($meth:ident, $color:ident($($arg:ident),+)) => {
132        fn $meth(&self, $($arg: u8),+) -> Styled<&Self> {
133            self.fg(Color::$color($($arg),+))
134        }
135    };
136}
137
138macro_rules! meth_style {
139    ($meth:ident) => {
140        fn $meth(&self) -> Styled<&Self> {
141            Styled::new(self).$meth()
142        }
143    };
144    ($meth:ident, $color:ident) => {
145        fn $meth(&self, $color: Color) -> Styled<&Self> {
146            Styled::new(self).$meth($color)
147        }
148    };
149}
150
151/// Allows anything implementing [`Display`] to be styled.
152pub trait Stylize<T>: Sized {
153    // different styles
154    meth_style!(bold);
155    meth_style!(dimmed);
156    meth_style!(italic);
157    meth_style!(underline);
158    meth_style!(blink);
159    meth_style!(reverse);
160    meth_style!(hidden);
161    meth_style!(strikethrough);
162    meth_style!(fg, color);
163    meth_style!(on, color);
164
165    // different colors
166    meth_color!(black, Black);
167    meth_color!(red, Red);
168    meth_color!(green, Green);
169    meth_color!(yellow, Yellow);
170    meth_color!(blue, Blue);
171    meth_color!(magenta, Purple);
172    meth_color!(cyan, Cyan);
173    meth_color!(white, White);
174    meth_color!(fixed, Fixed(n));
175    meth_color!(rgb, RGB(r, g, b));
176}
177
178/// Blanket implementation for everything that implements [`Display`].
179impl<T> Stylize<T> for T where T: Display {}