clankerdiff-theme 0.1.1

Renderer-neutral themes and palettes for Diff
Documentation
use crate::ReviewTheme;
use std::sync::Arc;

#[derive(Debug, Clone)]
pub struct ThemeChoice {
    pub name: String,
    pub theme: ReviewTheme,
}

impl ThemeChoice {
    #[must_use]
    pub fn new(name: impl Into<String>, theme: ReviewTheme) -> Self {
        Self {
            name: name.into(),
            theme,
        }
    }

    #[must_use]
    pub fn catalog() -> Arc<[Self]> {
        ReviewTheme::catalog()
            .into_iter()
            .filter_map(|descriptor| {
                ReviewTheme::builtin(&descriptor.id)
                    .ok()
                    .map(|theme| Self::new(descriptor.name, theme))
            })
            .collect()
    }
}

#[derive(Debug)]
pub struct ThemeSelection {
    themes: Arc<[ThemeChoice]>,
    selected: usize,
    original: ReviewTheme,
}

impl ThemeSelection {
    #[must_use]
    pub fn new(current: &ReviewTheme, themes: Arc<[ThemeChoice]>) -> Option<Self> {
        if themes.is_empty() {
            return None;
        }
        let selected = themes
            .iter()
            .position(|choice| choice.theme.id() == current.id())
            .unwrap_or(0);
        Some(Self {
            themes,
            selected,
            original: current.clone(),
        })
    }

    #[must_use]
    pub fn themes(&self) -> &[ThemeChoice] {
        &self.themes
    }

    #[must_use]
    pub const fn selected(&self) -> usize {
        self.selected
    }

    #[must_use]
    pub fn selected_theme(&self) -> ReviewTheme {
        self.themes[self.selected].theme.clone()
    }

    #[must_use]
    pub fn cancel(self) -> ReviewTheme {
        self.original
    }

    #[must_use]
    pub fn commit(self) -> ReviewTheme {
        self.selected_theme()
    }

    pub fn select_relative(&mut self, delta: isize) -> ReviewTheme {
        self.selected = self
            .selected
            .saturating_add_signed(delta)
            .min(self.themes.len() - 1);
        self.selected_theme()
    }

    pub fn select(&mut self, selected: usize) -> Option<ReviewTheme> {
        let theme = self.themes.get(selected)?.theme.clone();
        self.selected = selected;
        Some(theme)
    }
}