diff --git a/src/cursive.rs b/src/cursive.rs index ea55fe8..5fa0b99 100644 --- a/src/cursive.rs +++ b/src/cursive.rs @@ -418,6 +418,16 @@ impl Cursive { self.clear(); } + /// Updates the current theme. + pub fn update_theme(&mut self, f: impl FnOnce(&mut theme::Theme)) { + // We don't just expose a `current_theme_mut` because we may want to + // run some logic _after_ setting the theme. + // Though right now, it's only clearing the screen, so... + let mut theme = self.theme.clone(); + f(&mut theme); + self.set_theme(theme); + } + /// Clears the screen. /// /// Users rarely have to call this directly. diff --git a/src/theme/palette.rs b/src/theme/palette.rs index ff76080..f54d88e 100644 --- a/src/theme/palette.rs +++ b/src/theme/palette.rs @@ -4,6 +4,7 @@ use enum_map::{enum_map, Enum, EnumMap}; use log::warn; use std::ops::{Index, IndexMut}; +use std::str::FromStr; // Use AHash instead of the slower SipHash type HashMap = std::collections::HashMap; @@ -14,18 +15,25 @@ type HashMap = std::collections::HashMap; /// /// It implements `Index` and `IndexMut` to access and modify this mapping: /// +/// It also implements [`Extend`] to update a batch of colors at +/// once. +/// /// # Example /// /// ```rust /// # use cursive::theme::Palette; -/// use cursive::theme::PaletteColor::*; -/// use cursive::theme::Color::*; -/// use cursive::theme::BaseColor::*; +/// use cursive::theme::{BaseColor::*, Color::*, PaletteColor::*}; /// /// let mut palette = Palette::default(); /// /// assert_eq!(palette[Background], Dark(Blue)); /// palette[Shadow] = Light(Red); +/// assert_eq!(palette[Shadow], Light(Red)); +/// +/// let colors = vec![(Shadow, Dark(Green)), (Primary, Light(Blue))]; +/// palette.extend(colors); +/// assert_eq!(palette[Shadow], Dark(Green)); +/// assert_eq!(palette[Primary], Light(Blue)); /// ``` #[derive(PartialEq, Eq, Clone, Debug)] pub struct Palette { @@ -105,26 +113,23 @@ impl Palette { /// /// This will update either the basic palette or the custom values. pub fn set_color(&mut self, key: &str, color: Color) { - use crate::theme::PaletteColor::*; - - match key { - "background" => self.basic[Background] = color, - "shadow" => self.basic[Shadow] = color, - "view" => self.basic[View] = color, - "primary" => self.basic[Primary] = color, - "secondary" => self.basic[Secondary] = color, - "tertiary" => self.basic[Tertiary] = color, - "title_primary" => self.basic[TitlePrimary] = color, - "title_secondary" => self.basic[TitleSecondary] = color, - "highlight" => self.basic[Highlight] = color, - "highlight_inactive" => self.basic[HighlightInactive] = color, - other => { - self.custom - .insert(other.to_string(), PaletteNode::Color(color)); - } + if self.set_basic_color(key, color).is_err() { + self.custom + .insert(key.to_string(), PaletteNode::Color(color)); } } + /// Sets a basic color from its name. + /// + /// Returns `Err(())` if `key` is not a known `PaletteColor`. + pub fn set_basic_color( + &mut self, + key: &str, + color: Color, + ) -> Result<(), ()> { + PaletteColor::from_str(key).map(|c| self.basic[c] = color) + } + /// Adds a color namespace to this palette. pub fn add_namespace( &mut self, @@ -136,6 +141,17 @@ impl Palette { } } +impl Extend<(PaletteColor, Color)> for Palette { + fn extend(&mut self, iter: T) + where + T: IntoIterator, + { + for (k, v) in iter { + (*self)[k] = v; + } + } +} + /// Returns the default palette for a cursive application. /// /// * `Background` => `Dark(Blue)` @@ -263,3 +279,25 @@ impl PaletteColor { palette[self] } } + +impl FromStr for PaletteColor { + type Err = (); + + fn from_str(s: &str) -> Result { + use PaletteColor::*; + + Ok(match s { + "Background" | "background" => Background, + "Shadow" | "shadow" => Shadow, + "View" | "view" => View, + "Primary" | "primary" => Primary, + "Secondary" | "secondary" => Secondary, + "Tertiary" | "tertiary" => Tertiary, + "TitlePrimary" | "title_primary" => TitlePrimary, + "TitleSecondary" | "title_secondary" => TitleSecondary, + "Highlight" | "highlight" => Highlight, + "HighlightInactive" | "highlight_inactive" => HighlightInactive, + _ => return Err(()), + }) + } +}