chant 0.1.1

Shell glamour - beautiful prompts and output for scripts 🪄
Documentation
//! Style text command.

use glyphs::{style, Color};
use lacquer::{Border, Position, Style as LacquerStyle};

/// Style text with glyphs.
pub fn style_text(text: impl Into<String>) -> StyleCmd {
    StyleCmd::new(text)
}

/// Style command builder.
pub struct StyleCmd {
    text: String,
    foreground: Option<Color>,
    background: Option<Color>,
    bold: bool,
    italic: bool,
    underline: bool,
    strikethrough: bool,
    dim: bool,
    padding: Option<(u16, u16)>,
    margin: Option<(u16, u16)>,
    border: Option<Border>,
    width: Option<u16>,
    align: Position,
}

impl StyleCmd {
    /// Create a new style command.
    pub fn new(text: impl Into<String>) -> Self {
        Self {
            text: text.into(),
            foreground: None,
            background: None,
            bold: false,
            italic: false,
            underline: false,
            strikethrough: false,
            dim: false,
            padding: None,
            margin: None,
            border: None,
            width: None,
            align: Position::Start,
        }
    }

    /// Set foreground color.
    #[must_use]
    pub fn foreground(mut self, color: Color) -> Self {
        self.foreground = Some(color);
        self
    }

    /// Set foreground from hex.
    #[must_use]
    pub fn foreground_hex(self, hex: &str) -> Self {
        self.foreground(Color::from_hex(hex))
    }

    /// Set background color.
    #[must_use]
    pub fn background(mut self, color: Color) -> Self {
        self.background = Some(color);
        self
    }

    /// Make text bold.
    #[must_use]
    pub fn bold(mut self) -> Self {
        self.bold = true;
        self
    }

    /// Make text italic.
    #[must_use]
    pub fn italic(mut self) -> Self {
        self.italic = true;
        self
    }

    /// Underline text.
    #[must_use]
    pub fn underline(mut self) -> Self {
        self.underline = true;
        self
    }

    /// Strikethrough text.
    #[must_use]
    pub fn strikethrough(mut self) -> Self {
        self.strikethrough = true;
        self
    }

    /// Dim text.
    #[must_use]
    pub fn dim(mut self) -> Self {
        self.dim = true;
        self
    }

    /// Add padding.
    #[must_use]
    pub fn padding(mut self, vertical: u16, horizontal: u16) -> Self {
        self.padding = Some((vertical, horizontal));
        self
    }

    /// Add margin.
    #[must_use]
    pub fn margin(mut self, vertical: u16, horizontal: u16) -> Self {
        self.margin = Some((vertical, horizontal));
        self
    }

    /// Add border.
    #[must_use]
    pub fn border(mut self, border: Border) -> Self {
        self.border = Some(border);
        self
    }

    /// Set width.
    #[must_use]
    pub fn width(mut self, width: u16) -> Self {
        self.width = Some(width);
        self
    }

    /// Align text.
    #[must_use]
    pub fn align(mut self, align: Position) -> Self {
        self.align = align;
        self
    }

    /// Center text.
    #[must_use]
    pub fn center(self) -> Self {
        self.align(Position::Center)
    }

    /// Render the styled text.
    #[must_use]
    pub fn render(self) -> String {
        // If we have box model props, use lacquer
        if self.padding.is_some() || self.margin.is_some() || self.border.is_some() || self.width.is_some() {
            let mut style = LacquerStyle::new();

            if let Some((v, h)) = self.padding {
                style = style.padding(v, h);
            }
            if let Some((v, h)) = self.margin {
                style = style.margin(v, h);
            }
            if let Some(border) = self.border {
                style = style.border(border);
            }
            if let Some(width) = self.width {
                style = style.width(width);
            }

            style = style.align(self.align);

            if let Some(fg) = self.foreground {
                style = style.foreground(fg);
            }
            if let Some(bg) = self.background {
                style = style.background(bg);
            }
            if self.bold {
                style = style.bold();
            }
            if self.italic {
                style = style.italic();
            }
            if self.underline {
                style = style.underline();
            }
            if self.strikethrough {
                style = style.strikethrough();
            }
            if self.dim {
                style = style.dim();
            }

            style.render(&self.text)
        } else {
            // Just use glyphs for simple styling
            let mut styled = style(&self.text);

            if let Some(fg) = self.foreground {
                styled = styled.fg(fg);
            }
            if let Some(bg) = self.background {
                styled = styled.bg(bg);
            }
            if self.bold {
                styled = styled.bold();
            }
            if self.italic {
                styled = styled.italic();
            }
            if self.underline {
                styled = styled.underline();
            }
            if self.strikethrough {
                styled = styled.strikethrough();
            }
            if self.dim {
                styled = styled.dim();
            }

            styled.to_string()
        }
    }

    /// Print the styled text.
    pub fn print(self) {
        println!("{}", self.render());
    }
}