180 lines
6.0 KiB
Rust
180 lines
6.0 KiB
Rust
//! This module contains the logic to style some content.
|
|
|
|
use std::{
|
|
fmt::{self, Display, Formatter},
|
|
result,
|
|
};
|
|
|
|
use crate::{
|
|
queue,
|
|
style::{
|
|
Attribute, Color, Colorize, ContentStyle, ResetColor, SetAttribute, SetBackgroundColor,
|
|
SetForegroundColor, Styler,
|
|
},
|
|
};
|
|
|
|
/// The style with the content to be styled.
|
|
///
|
|
/// # Examples
|
|
///
|
|
/// ```rust
|
|
/// use crossterm::style::{style, Color, Attribute};
|
|
///
|
|
/// let styled = style("Hello there")
|
|
/// .with(Color::Yellow)
|
|
/// .on(Color::Blue)
|
|
/// .attribute(Attribute::Bold);
|
|
///
|
|
/// println!("{}", styled);
|
|
/// ```
|
|
#[derive(Clone)]
|
|
pub struct StyledContent<D: Display + Clone> {
|
|
/// The style (colors, content attributes).
|
|
style: ContentStyle,
|
|
/// A content to apply the style on.
|
|
content: D,
|
|
}
|
|
|
|
impl<'a, D: Display + 'a + Clone> StyledContent<D> {
|
|
/// Creates a new `StyledContent`.
|
|
pub fn new(style: ContentStyle, content: D) -> StyledContent<D> {
|
|
StyledContent { style, content }
|
|
}
|
|
|
|
/// Sets the foreground color.
|
|
pub fn with(mut self, foreground_color: Color) -> StyledContent<D> {
|
|
self.style = self.style.foreground(foreground_color);
|
|
self
|
|
}
|
|
|
|
/// Sets the background color.
|
|
pub fn on(mut self, background_color: Color) -> StyledContent<D> {
|
|
self.style = self.style.background(background_color);
|
|
self
|
|
}
|
|
|
|
/// Adds the attribute.
|
|
///
|
|
/// You can add more attributes by calling this method multiple times.
|
|
pub fn attribute(mut self, attr: Attribute) -> StyledContent<D> {
|
|
self.style = self.style.attribute(attr);
|
|
self
|
|
}
|
|
|
|
/// Returns the content.
|
|
pub fn content(&self) -> &D {
|
|
&self.content
|
|
}
|
|
|
|
/// Returns the style.
|
|
pub fn style(&self) -> &ContentStyle {
|
|
&self.style
|
|
}
|
|
}
|
|
|
|
impl<D: Display + Clone> Display for StyledContent<D> {
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> result::Result<(), fmt::Error> {
|
|
let mut reset = false;
|
|
|
|
if let Some(bg) = self.style.background_color {
|
|
queue!(f, SetBackgroundColor(bg)).map_err(|_| fmt::Error)?;
|
|
reset = true;
|
|
}
|
|
if let Some(fg) = self.style.foreground_color {
|
|
queue!(f, SetForegroundColor(fg)).map_err(|_| fmt::Error)?;
|
|
reset = true;
|
|
}
|
|
|
|
for attr in self.style.attributes.iter() {
|
|
queue!(f, SetAttribute(*attr)).map_err(|_| fmt::Error)?;
|
|
reset = true;
|
|
}
|
|
|
|
fmt::Display::fmt(&self.content, f)?;
|
|
|
|
if reset {
|
|
queue!(f, ResetColor).map_err(|_| fmt::Error)?;
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
impl<D: Display + Clone> Colorize<D> for StyledContent<D> {
|
|
// foreground colors
|
|
def_color!(foreground_color: black => Color::Black);
|
|
def_color!(foreground_color: dark_grey => Color::DarkGrey);
|
|
def_color!(foreground_color: red => Color::Red);
|
|
def_color!(foreground_color: dark_red => Color::DarkRed);
|
|
def_color!(foreground_color: green => Color::Green);
|
|
def_color!(foreground_color: dark_green => Color::DarkGreen);
|
|
def_color!(foreground_color: yellow => Color::Yellow);
|
|
def_color!(foreground_color: dark_yellow => Color::DarkYellow);
|
|
def_color!(foreground_color: blue => Color::Blue);
|
|
def_color!(foreground_color: dark_blue => Color::DarkBlue);
|
|
def_color!(foreground_color: magenta => Color::Magenta);
|
|
def_color!(foreground_color: dark_magenta => Color::DarkMagenta);
|
|
def_color!(foreground_color: cyan => Color::Cyan);
|
|
def_color!(foreground_color: dark_cyan => Color::DarkCyan);
|
|
def_color!(foreground_color: white => Color::White);
|
|
def_color!(foreground_color: grey => Color::Grey);
|
|
|
|
// background colors
|
|
def_color!(background_color: on_black => Color::Black);
|
|
def_color!(background_color: on_dark_grey => Color::DarkGrey);
|
|
def_color!(background_color: on_red => Color::Red);
|
|
def_color!(background_color: on_dark_red => Color::DarkRed);
|
|
def_color!(background_color: on_green => Color::Green);
|
|
def_color!(background_color: on_dark_green => Color::DarkGreen);
|
|
def_color!(background_color: on_yellow => Color::Yellow);
|
|
def_color!(background_color: on_dark_yellow => Color::DarkYellow);
|
|
def_color!(background_color: on_blue => Color::Blue);
|
|
def_color!(background_color: on_dark_blue => Color::DarkBlue);
|
|
def_color!(background_color: on_magenta => Color::Magenta);
|
|
def_color!(background_color: on_dark_magenta => Color::DarkMagenta);
|
|
def_color!(background_color: on_cyan => Color::Cyan);
|
|
def_color!(background_color: on_dark_cyan => Color::DarkCyan);
|
|
def_color!(background_color: on_white => Color::White);
|
|
def_color!(background_color: on_grey => Color::Grey);
|
|
}
|
|
|
|
impl<D: Display + Clone> Styler<D> for StyledContent<D> {
|
|
def_attr!(reset => Attribute::Reset);
|
|
def_attr!(bold => Attribute::Bold);
|
|
def_attr!(underlined => Attribute::Underlined);
|
|
def_attr!(reverse => Attribute::Reverse);
|
|
def_attr!(dim => Attribute::Dim);
|
|
def_attr!(italic => Attribute::Italic);
|
|
def_attr!(negative => Attribute::Reverse);
|
|
def_attr!(slow_blink => Attribute::SlowBlink);
|
|
def_attr!(rapid_blink => Attribute::RapidBlink);
|
|
def_attr!(hidden => Attribute::Hidden);
|
|
def_attr!(crossed_out => Attribute::CrossedOut);
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::{Attribute, Color, ContentStyle};
|
|
|
|
#[test]
|
|
fn test_set_fg_bg_add_attr() {
|
|
let style = ContentStyle::new()
|
|
.foreground(Color::Blue)
|
|
.background(Color::Red)
|
|
.attribute(Attribute::Reset);
|
|
|
|
let mut styled_content = style.apply("test");
|
|
|
|
styled_content = styled_content
|
|
.with(Color::Green)
|
|
.on(Color::Magenta)
|
|
.attribute(Attribute::NoItalic);
|
|
|
|
assert_eq!(styled_content.style.foreground_color, Some(Color::Green));
|
|
assert_eq!(styled_content.style.background_color, Some(Color::Magenta));
|
|
assert_eq!(styled_content.style.attributes.len(), 2);
|
|
assert_eq!(styled_content.style.attributes[0], Attribute::Reset);
|
|
assert_eq!(styled_content.style.attributes[1], Attribute::NoItalic);
|
|
}
|
|
}
|