use crate::theme::Theme;
#[derive(Debug, Clone, PartialEq)]
pub struct ThemeSwitcher {
themes: Vec<Theme>,
index: usize,
}
impl Default for ThemeSwitcher {
fn default() -> Self {
Self::new()
}
}
impl ThemeSwitcher {
#[must_use]
pub fn new() -> Self {
Self {
themes: Theme::all(),
index: 0,
}
}
#[must_use]
pub fn with_themes(themes: Vec<Theme>) -> Self {
if themes.is_empty() {
Self::new()
} else {
Self { themes, index: 0 }
}
}
#[must_use]
pub fn current(&self) -> &Theme {
&self.themes[self.index]
}
#[must_use]
pub fn index(&self) -> usize {
self.index
}
#[must_use]
pub fn len(&self) -> usize {
self.themes.len()
}
#[must_use]
pub fn is_empty(&self) -> bool {
false
}
#[must_use]
pub fn themes(&self) -> &[Theme] {
&self.themes
}
#[must_use]
pub fn names(&self) -> Vec<&str> {
self.themes.iter().map(|t| t.name.as_str()).collect()
}
#[allow(clippy::should_implement_trait)]
pub fn next(&mut self) -> &Theme {
self.index = (self.index + 1) % self.themes.len();
self.current()
}
pub fn prev(&mut self) -> &Theme {
self.index = (self.index + self.themes.len() - 1) % self.themes.len();
self.current()
}
pub fn set_index(&mut self, index: usize) -> &Theme {
self.index = index % self.themes.len();
self.current()
}
pub fn set_by_name(&mut self, name: &str) -> bool {
let key = name.trim().to_ascii_lowercase().replace(['_', ' '], "-");
match self.themes.iter().position(|t| t.name == key) {
Some(i) => {
self.index = i;
true
}
None => false,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn starts_at_first() {
let s = ThemeSwitcher::new();
assert_eq!(s.index(), 0);
assert_eq!(s.len(), Theme::all().len());
assert!(!s.is_empty());
}
#[test]
fn next_wraps() {
let mut s = ThemeSwitcher::new();
for _ in 0..s.len() {
s.next();
}
assert_eq!(s.index(), 0);
}
#[test]
fn prev_wraps() {
let mut s = ThemeSwitcher::new();
s.prev();
assert_eq!(s.index(), s.len() - 1);
}
#[test]
fn set_index_wraps() {
let mut s = ThemeSwitcher::new();
s.set_index(s.len() + 2);
assert_eq!(s.index(), 2);
}
#[test]
fn set_by_name_found_and_missing() {
let mut s = ThemeSwitcher::new();
assert!(s.set_by_name("Tokyo Night"));
assert_eq!(s.current().name, "tokyo-night");
assert!(!s.set_by_name("zzz"));
assert_eq!(s.current().name, "tokyo-night");
}
#[test]
fn custom_and_empty() {
let s = ThemeSwitcher::with_themes(vec![Theme::default().name("a")]);
assert_eq!(s.names(), vec!["a"]);
assert_eq!(ThemeSwitcher::with_themes(vec![]).len(), Theme::all().len());
let mut one = s;
one.next();
assert_eq!(one.index(), 0);
}
}