minicrossterm/src/style/styled_content.rs

180 lines
6.0 KiB
Rust
Raw Normal View History

2019-10-28 07:07:09 +11:00
//! This module contains the logic to style some content.
2019-11-19 07:50:57 +11:00
use std::{
fmt::{self, Display, Formatter},
result,
};
2019-11-19 07:50:57 +11:00
use crate::{
queue,
style::{
Attribute, Color, Colorize, ContentStyle, ResetColor, SetAttribute, SetBackgroundColor,
SetForegroundColor, Styler,
},
2019-11-01 07:02:04 +11:00
};
/// The style with the content to be styled.
///
/// # Examples
///
/// ```rust
2019-11-01 07:02:04 +11:00
/// use crossterm::style::{style, Color, Attribute};
///
/// let styled = style("Hello there")
/// .with(Color::Yellow)
/// .on(Color::Blue)
2019-10-28 07:07:09 +11:00
/// .attribute(Attribute::Bold);
///
/// println!("{}", styled);
/// ```
#[derive(Clone)]
2019-10-28 07:07:09 +11:00
pub struct StyledContent<D: Display + Clone> {
/// The style (colors, content attributes).
style: ContentStyle,
/// A content to apply the style on.
content: D,
}
2019-10-28 07:07:09 +11:00
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.
2019-10-28 07:07:09 +11:00
pub fn with(mut self, foreground_color: Color) -> StyledContent<D> {
self.style = self.style.foreground(foreground_color);
self
}
/// Sets the background color.
2019-10-28 07:07:09 +11:00
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.
2019-10-28 07:07:09 +11:00
pub fn attribute(mut self, attr: Attribute) -> StyledContent<D> {
self.style = self.style.attribute(attr);
self
}
2019-10-28 07:07:09 +11:00
/// Returns the content.
pub fn content(&self) -> &D {
&self.content
}
/// Returns the style.
pub fn style(&self) -> &ContentStyle {
&self.style
}
}
2019-10-28 07:07:09 +11:00
impl<D: Display + Clone> Display for StyledContent<D> {
2019-10-24 00:02:20 +11:00
fn fmt(&self, f: &mut Formatter<'_>) -> result::Result<(), fmt::Error> {
let mut reset = false;
2019-11-01 07:02:04 +11:00
if let Some(bg) = self.style.background_color {
queue!(f, SetBackgroundColor(bg)).map_err(|_| fmt::Error)?;
reset = true;
}
2019-11-01 07:02:04 +11:00
if let Some(fg) = self.style.foreground_color {
queue!(f, SetForegroundColor(fg)).map_err(|_| fmt::Error)?;
reset = true;
}
2019-11-01 07:02:04 +11:00
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(())
}
}
2019-10-28 07:07:09 +11:00
impl<D: Display + Clone> Colorize<D> for StyledContent<D> {
// foreground colors
2019-11-01 07:02:04 +11:00
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
2019-11-01 07:02:04 +11:00
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);
}
2019-10-28 07:07:09 +11:00
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 {
2019-10-28 07:07:09 +11:00
use super::{Attribute, Color, ContentStyle};
#[test]
fn test_set_fg_bg_add_attr() {
2019-10-28 07:07:09 +11:00
let style = ContentStyle::new()
.foreground(Color::Blue)
.background(Color::Red)
.attribute(Attribute::Reset);
2019-10-28 07:07:09 +11:00
let mut styled_content = style.apply("test");
2019-10-28 07:07:09 +11:00
styled_content = styled_content
.with(Color::Green)
.on(Color::Magenta)
2019-10-28 07:07:09 +11:00
.attribute(Attribute::NoItalic);
2019-11-01 07:02:04 +11:00
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);
}
}