use ratatui::style::Style;
use std::borrow::Cow;
use unicode_width::UnicodeWidthStr;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct BreadcrumbSeparator<'a> {
pub symbol: Cow<'a, str>,
pub style: Style,
pub spacing: u16,
}
impl Default for BreadcrumbSeparator<'static> {
fn default() -> Self {
Self::chevron()
}
}
impl<'a> BreadcrumbSeparator<'a> {
pub fn custom(symbol: impl Into<Cow<'a, str>>) -> Self {
Self {
symbol: symbol.into(),
style: Style::default(),
spacing: 1,
}
}
#[must_use]
pub fn chevron() -> Self {
Self::custom("❯")
}
#[must_use]
pub fn slash() -> Self {
Self::custom("/")
}
#[must_use]
pub fn angle() -> Self {
Self::custom("›")
}
#[must_use]
pub fn arrow() -> Self {
Self::custom("→")
}
#[must_use]
pub fn pipe() -> Self {
Self::custom("|")
}
#[must_use]
pub fn backslash() -> Self {
Self::custom("\\")
}
#[must_use]
pub fn double_angle() -> Self {
Self::custom("»")
}
#[must_use]
pub fn style(mut self, style: impl Into<Style>) -> Self {
self.style = style.into();
self
}
#[must_use]
pub fn spacing(mut self, spacing: u16) -> Self {
self.spacing = spacing;
self
}
#[must_use]
pub fn total_width(&self) -> usize {
UnicodeWidthStr::width(self.symbol.as_ref()) + (self.spacing as usize * 2)
}
}
impl<'a> From<&'a str> for BreadcrumbSeparator<'a> {
fn from(s: &'a str) -> Self {
Self::custom(s)
}
}
impl From<String> for BreadcrumbSeparator<'static> {
fn from(s: String) -> Self {
Self::custom(s)
}
}
impl From<char> for BreadcrumbSeparator<'static> {
fn from(c: char) -> Self {
Self::custom(c.to_string())
}
}
#[cfg(test)]
mod tests {
use super::*;
use ratatui::style::Color;
#[test]
fn test_separator_presets_width() {
let chevron = BreadcrumbSeparator::chevron();
assert_eq!(chevron.symbol, "❯");
assert_eq!(chevron.spacing, 1);
assert_eq!(chevron.total_width(), 3);
let slash = BreadcrumbSeparator::slash().spacing(0);
assert_eq!(slash.symbol, "/");
assert_eq!(slash.spacing, 0);
assert_eq!(slash.total_width(), 1);
let pipe = BreadcrumbSeparator::pipe();
assert_eq!(pipe.total_width(), 3);
let arrow = BreadcrumbSeparator::arrow();
assert_eq!(arrow.total_width(), 3);
let angle = BreadcrumbSeparator::angle();
assert_eq!(angle.total_width(), 3);
let backslash = BreadcrumbSeparator::backslash();
assert_eq!(backslash.total_width(), 3);
let double_angle = BreadcrumbSeparator::double_angle();
assert_eq!(double_angle.total_width(), 3);
}
#[test]
fn test_custom_separator_styling() {
let sep = BreadcrumbSeparator::custom("•")
.spacing(2)
.style(Style::default().fg(Color::Magenta));
assert_eq!(sep.symbol, "•");
assert_eq!(sep.spacing, 2);
assert_eq!(sep.total_width(), 5);
assert_eq!(sep.style, Style::default().fg(Color::Magenta));
}
}