use crate::core::render::{Renderable, Rendered};
use crate::core::style::Style;
use crate::core::text::{Line, Span};
use crate::core::theme::theme;
pub struct Badge {
text: String,
left_cap: String,
right_cap: String,
style: Style,
pad: u16,
}
impl Badge {
pub fn new(text: impl Into<String>) -> Self {
Self {
text: text.into(),
left_cap: "[".to_string(),
right_cap: "]".to_string(),
style: Style::new().fg(theme().accent).bold(),
pad: 0,
}
}
#[must_use]
pub fn caps(
mut self,
left: impl Into<String>,
right: impl Into<String>,
) -> Self {
self.left_cap = left.into();
self.right_cap = right.into();
self
}
#[must_use]
pub fn style(mut self, style: Style) -> Self {
self.style = style;
self
}
#[must_use]
pub fn pad(mut self, pad: u16) -> Self {
self.pad = pad;
self
}
pub fn span(&self) -> Span {
let spaces = " ".repeat(self.pad as usize);
let content = format!(
"{}{spaces}{}{spaces}{}",
self.left_cap, self.text, self.right_cap
);
Span::styled(content, self.style)
}
}
impl Renderable for Badge {
fn render(&self, _max_width: u16) -> Rendered {
Rendered::new(vec![Line::new(vec![self.span()])])
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn badge_wraps_text_in_caps() {
assert_eq!(Badge::new("OK").span().content, "[OK]");
}
#[test]
fn badge_honors_custom_caps_and_pad() {
let span = Badge::new("v1").caps("(", ")").pad(1).span();
assert_eq!(span.content, "( v1 )");
}
}