use crate::style::color::{Color, ColorSpec};
use crate::style::style::ProgressStyle;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Theme {
Default,
Unicode,
Braille,
Block,
Minimal,
Colorful,
Gradient,
Retro,
Dots,
Rounded,
Shaded,
Arrows,
}
impl Theme {
pub fn style(&self) -> ProgressStyle {
match self {
Self::Default => themed("[{bar:30}] {pos}/{len} {msg}", "#>-"),
Self::Unicode => themed("[{bar:30}] {pos}/{len} {msg}", "━╸░"),
Self::Braille => themed("[{bar:30}] {pos}/{len} {msg}", "⣿⣷⣦"),
Self::Block => themed("[{bar:30}] {pos}/{len} {msg}", "█▉▒"),
Self::Minimal => themed("{bar:30} {pos}/{len} {msg}", "=>."),
Self::Colorful => themed("[{bar:30.green/red}] {percent}% {msg}", "#>-")
.color(ColorSpec::new().set_fg(Color::BrightGreen).set_bold(true)),
Self::Gradient => themed("[{bar:30}] {percent}% {msg}", "█▓▒░"),
Self::Retro => themed("[{bar:30}] {pos}/{len} {msg}", "=>-"),
Self::Dots => themed("[{bar:30}] {percent}% {msg}", "•∘ "),
Self::Rounded => themed("[{bar:30}] {percent}% {msg}", "●○─"),
Self::Shaded => themed("[{bar:30}] {percent}% {msg}", "▪▫ "),
Self::Arrows => themed("[{bar:30}] {percent}% {msg}", ">->"),
}
}
pub fn name(&self) -> &'static str {
match self {
Self::Default => "default",
Self::Unicode => "unicode",
Self::Braille => "braille",
Self::Block => "block",
Self::Minimal => "minimal",
Self::Colorful => "colorful",
Self::Gradient => "gradient",
Self::Retro => "retro",
Self::Dots => "dots",
Self::Rounded => "rounded",
Self::Shaded => "shaded",
Self::Arrows => "arrows",
}
}
pub fn all() -> &'static [Theme] {
static THEMES: [Theme; 12] = [
Theme::Default,
Theme::Unicode,
Theme::Braille,
Theme::Block,
Theme::Minimal,
Theme::Colorful,
Theme::Gradient,
Theme::Retro,
Theme::Dots,
Theme::Rounded,
Theme::Shaded,
Theme::Arrows,
];
&THEMES
}
}
fn themed(template: &str, chars: &str) -> ProgressStyle {
match ProgressStyle::with_template(template) {
Ok(style) => style.progress_chars(chars),
Err(_) => ProgressStyle::default_bar().progress_chars(chars),
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::collections::HashSet;
#[test]
fn test_all_themes_return_valid_style() {
for theme in Theme::all() {
assert!(!theme.style().parsed_template.parts.is_empty());
}
}
#[test]
fn test_theme_names_unique() {
let names: HashSet<&str> = Theme::all().iter().map(Theme::name).collect();
assert_eq!(names.len(), Theme::all().len());
}
#[test]
fn test_theme_all_count() {
assert_eq!(Theme::all().len(), 12);
}
#[test]
fn test_default_theme_style() {
assert_eq!(Theme::Default.style().progress_chars, "#>-");
}
#[test]
fn test_colorful_theme_has_color() {
assert!(Theme::Colorful.style().color_spec.is_some());
}
}