crossterm_style/
lib.rs

1#![deny(unused_imports, unused_must_use)]
2
3//! # Style
4//!
5//! **The `crossterm_style` crate is deprecated and no longer maintained. The GitHub repository will
6//! be archived soon. All the code is being moved to the `crossterm`
7//! [crate](https://github.com/crossterm-rs/crossterm). You can learn more in
8//! the [Merge sub-crates to the crossterm crate](https://github.com/crossterm-rs/crossterm/issues/265)
9//! issue.**
10//!
11//! The `crossterm_style` crate provides a functionality to apply attributes and colors on your text.
12//!
13//! This documentation does not contain a lot of examples. The reason is that it's fairly
14//! obvious how to use this crate. Although, we do provide
15//! [examples](https://github.com/crossterm-rs/examples) repository
16//! to demonstrate the capabilities.
17//!
18//! ## Platform-specific Notes
19//!
20//! Not all features are supported on all terminals/platforms. You should always consult
21//! platform-specific notes of the following types:
22//!
23//! * [Color](enum.Color.html#platform-specific-notes)
24//! * [Attribute](enum.Attribute.html#platform-specific-notes)
25//!
26//! ## Examples
27//!
28//! ### Colors
29//!
30//! The command API:
31//!
32//! ```no_run
33//! use std::io::{stdout, Write};
34//!
35//! use crossterm_utils::{execute, Result, Output};
36//! use crossterm_style::{SetBg, SetFg, ResetColor, Color, Attribute};
37//!
38//! fn main() -> Result<()> {
39//!     execute!(
40//!         stdout(),
41//!         // Blue foreground
42//!         SetFg(Color::Blue),
43//!         // Red background
44//!         SetBg(Color::Red),
45//!         Output("Styled text here.".to_string()),
46//!         // Reset to default colors
47//!         ResetColor
48//!     )
49//! }
50//! ```
51//!
52//! The [`Colored`](enum.Colored.html) & [`Color`](enum.Color.html) enums:
53//!
54//! ```no_run
55//! use crossterm_style::{Colored, Color};
56//!
57//! println!("{} Red foreground", Colored::Fg(Color::Red));
58//! println!("{} Blue background", Colored::Bg(Color::Blue));
59//! ```
60//!
61//! The [`Colorize`](trait.Colorize.html) trait:
62//!
63//! ```no_run
64//! use crossterm_style::Colorize;
65//!
66//! println!("{}", "Red foreground color & blue background.".red().on_blue());
67//! ```
68//!
69//! ### Attributes
70//!
71//! The command API:
72//!
73//! ```no_run
74//! use std::io::{stdout, Write};
75//!
76//! use crossterm_utils::{execute, Result, Output};
77//! use crossterm_style::{SetAttr, Attribute};
78//!
79//! fn main() -> Result<()> {
80//!     execute!(
81//!         stdout(),
82//!         // Set to bold
83//!         SetAttr(Attribute::Bold),
84//!         Output("Styled text here.".to_string()),
85//!         // Reset all attributes
86//!         SetAttr(Attribute::Reset)
87//!     )
88//! }
89//! ```
90//!
91//! The [`Styler`](trait.Styler.html) trait:
92//!
93//! ```no_run
94//! use crossterm_style::Styler;
95//!
96//! println!("{}", "Bold".bold());
97//! println!("{}", "Underlined".underlined());
98//! println!("{}", "Negative".negative());
99//! ```
100//!
101//! The [`Attribute`](enum.Attribute.html) enum:
102//!
103//! ```no_run
104//! use crossterm_style::Attribute;
105//!
106//! println!(
107//!     "{} Underlined {} No Underline",
108//!     Attribute::Underlined,
109//!     Attribute::NoUnderline
110//! );
111//! ```
112
113use std::env;
114use std::fmt::Display;
115
116#[cfg(windows)]
117use crossterm_utils::supports_ansi;
118#[doc(no_inline)]
119pub use crossterm_utils::{
120    execute, impl_display, queue, Command, ExecutableCommand, QueueableCommand, Result,
121};
122
123use style::ansi::{self, AnsiColor};
124#[cfg(windows)]
125use style::winapi::WinApiColor;
126use style::Style;
127
128pub use self::enums::{Attribute, Color, Colored};
129pub use self::objectstyle::ObjectStyle;
130pub use self::styledobject::StyledObject;
131pub use self::traits::{Colorize, Styler};
132
133#[macro_use]
134mod macros;
135mod enums;
136mod objectstyle;
137mod style;
138mod styledobject;
139mod traits;
140
141/// Creates a `StyledObject`.
142///
143/// This could be used to style any type that implements `Display` with colors and text attributes.
144///
145/// See [`StyledObject`](struct.StyledObject.html) for more info.
146///
147/// # Examples
148///
149/// ```no_run
150/// use crossterm_style::{style, Color};
151///
152/// let styled_object = style("Blue colored text on yellow background")
153///     .with(Color::Blue)
154///     .on(Color::Yellow);
155///
156/// println!("{}", styled_object);
157/// ```
158pub fn style<'a, D: 'a>(val: D) -> StyledObject<D>
159where
160    D: Display + Clone,
161{
162    ObjectStyle::new().apply_to(val)
163}
164
165impl Colorize<&'static str> for &'static str {
166    // foreground colors
167    def_str_color!(fg_color: black => Color::Black);
168    def_str_color!(fg_color: dark_grey => Color::DarkGrey);
169    def_str_color!(fg_color: red => Color::Red);
170    def_str_color!(fg_color: dark_red => Color::DarkRed);
171    def_str_color!(fg_color: green => Color::Green);
172    def_str_color!(fg_color: dark_green => Color::DarkGreen);
173    def_str_color!(fg_color: yellow => Color::Yellow);
174    def_str_color!(fg_color: dark_yellow => Color::DarkYellow);
175    def_str_color!(fg_color: blue => Color::Blue);
176    def_str_color!(fg_color: dark_blue => Color::DarkBlue);
177    def_str_color!(fg_color: magenta => Color::Magenta);
178    def_str_color!(fg_color: dark_magenta => Color::DarkMagenta);
179    def_str_color!(fg_color: cyan => Color::Cyan);
180    def_str_color!(fg_color: dark_cyan => Color::DarkCyan);
181    def_str_color!(fg_color: white => Color::White);
182    def_str_color!(fg_color: grey => Color::Grey);
183
184    // background colors
185    def_str_color!(bg_color: on_black => Color::Black);
186    def_str_color!(bg_color: on_dark_grey => Color::DarkGrey);
187    def_str_color!(bg_color: on_red => Color::Red);
188    def_str_color!(bg_color: on_dark_red => Color::DarkRed);
189    def_str_color!(bg_color: on_green => Color::Green);
190    def_str_color!(bg_color: on_dark_green => Color::DarkGreen);
191    def_str_color!(bg_color: on_yellow => Color::Yellow);
192    def_str_color!(bg_color: on_dark_yellow => Color::DarkYellow);
193    def_str_color!(bg_color: on_blue => Color::Blue);
194    def_str_color!(bg_color: on_dark_blue => Color::DarkBlue);
195    def_str_color!(bg_color: on_magenta => Color::Magenta);
196    def_str_color!(bg_color: on_dark_magenta => Color::DarkMagenta);
197    def_str_color!(bg_color: on_cyan => Color::Cyan);
198    def_str_color!(bg_color: on_dark_cyan => Color::DarkCyan);
199    def_str_color!(bg_color: on_white => Color::White);
200    def_str_color!(bg_color: on_grey => Color::Grey);
201}
202
203impl Styler<&'static str> for &'static str {
204    def_str_attr!(reset => Attribute::Reset);
205    def_str_attr!(bold => Attribute::Bold);
206    def_str_attr!(underlined => Attribute::Underlined);
207    def_str_attr!(reverse => Attribute::Reverse);
208    def_str_attr!(dim => Attribute::Dim);
209    def_str_attr!(italic => Attribute::Italic);
210    def_str_attr!(negative => Attribute::Reverse);
211    def_str_attr!(slow_blink => Attribute::SlowBlink);
212    def_str_attr!(rapid_blink => Attribute::RapidBlink);
213    def_str_attr!(hidden => Attribute::Hidden);
214    def_str_attr!(crossed_out => Attribute::CrossedOut);
215}
216
217/// A terminal color.
218///
219/// # Examples
220///
221/// Basic usage:
222///
223/// ```no_run
224/// // You can replace the following line with `use crossterm::TerminalColor;`
225/// // if you're using the `crossterm` crate with the `style` feature enabled.
226/// use crossterm_style::{Result, TerminalColor, Color};
227///
228/// fn main() -> Result<()> {
229///     let color = TerminalColor::new();
230///     // Set foreground color
231///     color.set_fg(Color::Blue)?;
232///     // Set background color
233///     color.set_bg(Color::Red)?;
234///     // Reset to the default colors
235///     color.reset()
236/// }
237/// ```
238pub struct TerminalColor {
239    #[cfg(windows)]
240    color: Box<(dyn Style + Sync + Send)>,
241    #[cfg(unix)]
242    color: AnsiColor,
243}
244
245impl TerminalColor {
246    /// Creates a new `TerminalColor`.
247    pub fn new() -> TerminalColor {
248        #[cfg(windows)]
249        let color = if supports_ansi() {
250            Box::from(AnsiColor::new()) as Box<(dyn Style + Sync + Send)>
251        } else {
252            WinApiColor::new() as Box<(dyn Style + Sync + Send)>
253        };
254
255        #[cfg(unix)]
256        let color = AnsiColor::new();
257
258        TerminalColor { color }
259    }
260
261    /// Sets the foreground color.
262    pub fn set_fg(&self, color: Color) -> Result<()> {
263        self.color.set_fg(color)
264    }
265
266    /// Sets the background color.
267    pub fn set_bg(&self, color: Color) -> Result<()> {
268        self.color.set_bg(color)
269    }
270
271    /// Resets the terminal colors and attributes to the default ones.
272    pub fn reset(&self) -> Result<()> {
273        self.color.reset()
274    }
275
276    /// Returns available color count.
277    ///
278    /// # Notes
279    ///
280    /// This does not always provide a good result.
281    pub fn available_color_count(&self) -> u16 {
282        env::var("TERM")
283            .map(|x| if x.contains("256color") { 256 } else { 8 })
284            .unwrap_or(8)
285    }
286}
287
288/// Creates a new `TerminalColor`.
289///
290/// # Examples
291///
292/// Basic usage:
293///
294/// ```no_run
295/// use crossterm_style::{color, Color, Result};
296///
297/// fn main() -> Result<()> {
298///     let color = color();
299///     // Set foreground color
300///     color.set_fg(Color::Blue)?;
301///     // Set background color
302///     color.set_bg(Color::Red)?;
303///     // Reset to the default colors
304///     color.reset()
305/// }
306/// ```
307pub fn color() -> TerminalColor {
308    TerminalColor::new()
309}
310
311/// A command to set the foreground color.
312///
313/// See [`Color`](enum.Color.html) for more info.
314///
315/// # Notes
316///
317/// Commands must be executed/queued for execution otherwise they do nothing.
318pub struct SetFg(pub Color);
319
320impl Command for SetFg {
321    type AnsiType = String;
322
323    fn ansi_code(&self) -> Self::AnsiType {
324        ansi::set_fg_csi_sequence(self.0)
325    }
326
327    #[cfg(windows)]
328    fn execute_winapi(&self) -> Result<()> {
329        WinApiColor::new().set_fg(self.0)
330    }
331}
332
333/// A command to set the background color.
334///
335/// See [`Color`](enum.Color.html) for more info.
336///
337/// # Notes
338///
339/// Commands must be executed/queued for execution otherwise they do nothing.
340pub struct SetBg(pub Color);
341
342impl Command for SetBg {
343    type AnsiType = String;
344
345    fn ansi_code(&self) -> Self::AnsiType {
346        ansi::set_bg_csi_sequence(self.0)
347    }
348
349    #[cfg(windows)]
350    fn execute_winapi(&self) -> Result<()> {
351        WinApiColor::new().set_bg(self.0)
352    }
353}
354
355/// A command to set the text attribute.
356///
357/// See [`Attribute`](enum.Attribute.html) for more info.
358///
359/// # Notes
360///
361/// Commands must be executed/queued for execution otherwise they do nothing.
362pub struct SetAttr(pub Attribute);
363
364impl Command for SetAttr {
365    type AnsiType = String;
366
367    fn ansi_code(&self) -> Self::AnsiType {
368        ansi::set_attr_csi_sequence(self.0)
369    }
370
371    #[cfg(windows)]
372    fn execute_winapi(&self) -> Result<()> {
373        // attributes are not supported by WinAPI.
374        Ok(())
375    }
376}
377
378/// A command to print the styled object.
379///
380/// See [`StyledObject`](struct.StyledObject.html) for more info.
381///
382/// # Notes
383///
384/// Commands must be executed/queued for execution otherwise they do nothing.
385pub struct PrintStyledFont<D: Display + Clone>(pub StyledObject<D>);
386
387impl<D> Command for PrintStyledFont<D>
388where
389    D: Display + Clone,
390{
391    type AnsiType = StyledObject<D>;
392
393    fn ansi_code(&self) -> Self::AnsiType {
394        self.0.clone()
395    }
396
397    #[cfg(windows)]
398    fn execute_winapi(&self) -> Result<()> {
399        Ok(())
400    }
401}
402
403/// A command to reset the colors back to default ones.
404///
405/// # Notes
406///
407/// Commands must be executed/queued for execution otherwise they do nothing.
408pub struct ResetColor;
409
410impl Command for ResetColor {
411    type AnsiType = String;
412
413    fn ansi_code(&self) -> Self::AnsiType {
414        ansi::RESET_CSI_SEQUENCE.to_string()
415    }
416
417    #[cfg(windows)]
418    fn execute_winapi(&self) -> Result<()> {
419        WinApiColor::new().reset()
420    }
421}
422
423impl_display!(for SetFg);
424impl_display!(for SetBg);
425impl_display!(for SetAttr);
426impl_display!(for PrintStyledFont<String>);
427impl_display!(for PrintStyledFont<&'static str>);
428impl_display!(for ResetColor);