diff --git a/src/config/mod.rs b/src/config/mod.rs index e12bbf0..eb58235 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -178,9 +178,7 @@ impl EwwConfig { } #[repr(transparent)] -#[derive( - Debug, Clone, Hash, PartialEq, Eq, derive_more::AsRef, derive_more::From, derive_more::FromStr, Serialize, Deserialize, -)] +#[derive(Clone, Hash, PartialEq, Eq, derive_more::AsRef, derive_more::From, derive_more::FromStr, Serialize, Deserialize)] pub struct WindowName(String); impl std::borrow::Borrow for WindowName { @@ -195,6 +193,12 @@ impl fmt::Display for WindowName { } } +impl fmt::Debug for WindowName { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "WindowName(\"{}\")", self.0) + } +} + #[derive(Debug, Clone, PartialEq)] pub struct EwwWindowDefinition { pub position: Coords, diff --git a/src/eww_state.rs b/src/eww_state.rs index 37eb32b..3663ad7 100644 --- a/src/eww_state.rs +++ b/src/eww_state.rs @@ -1,7 +1,7 @@ use crate::{ config::WindowName, util, - value::{AttrName, StringOrVarRef, VarName}, + value::{AttrName, AttrValueElement, VarName}, }; use anyhow::*; use std::{collections::HashMap, process::Command, sync::Arc}; @@ -51,7 +51,7 @@ pub struct EwwWindowState { } impl EwwWindowState { - /// register a new [StateChangeHandler] + /// register a new [`StateChangeHandler`] fn put_handler(&mut self, handler: StateChangeHandler) { let handler = Arc::new(handler); for var_name in handler.used_variables() { @@ -128,8 +128,8 @@ impl EwwState { value .iter() .map(|element| match element { - StringOrVarRef::Primitive(primitive) => Ok(primitive.clone()), - StringOrVarRef::VarRef(var_name) => self + AttrValueElement::Primitive(primitive) => Ok(primitive.clone()), + AttrValueElement::VarRef(var_name) => self .variables_state .get(var_name) .cloned() @@ -148,26 +148,27 @@ impl EwwState { &mut self, window_name: &WindowName, local_env: &HashMap, - mut attributes: HashMap, + attributes: HashMap, set_value: F, ) { - let window_state = self - .windows - .entry(window_name.clone()) - .or_insert_with(EwwWindowState::default); - - let resolved_attributes: Vec<(AttrName, AttrValue)> = attributes - .drain() - .map(|(attr_name, attr_value)| (attr_name, attr_value.resolve_one_level(local_env))) - .collect(); - let handler = StateChangeHandler { func: Box::new(set_value), - unresolved_values: resolved_attributes, + unresolved_values: attributes + .into_iter() + .map(|(attr_name, attr_value)| (attr_name, attr_value.resolve_one_level(local_env))) + .collect(), }; handler.run_with_state(&self.variables_state); - window_state.put_handler(handler); + + // only store the handler if at least one variable is being used + if handler.used_variables().next().is_some() { + let window_state = self + .windows + .entry(window_name.clone()) + .or_insert_with(EwwWindowState::default); + window_state.put_handler(handler); + } } } diff --git a/src/value/attr_value.rs b/src/value/attr_value.rs index 42965ec..4013e07 100644 --- a/src/value/attr_value.rs +++ b/src/value/attr_value.rs @@ -3,32 +3,39 @@ use std::{collections::HashMap, iter::FromIterator}; use super::*; -#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, derive_more::Into, derive_more::From)] -pub struct AttrValue(Vec); +/// A value assigned to an attribute in a widget. +/// This can be a primitive String that contains any amount of variable +/// references, as would be generated by the string "foo {{var}} bar". +#[derive(Serialize, Deserialize, Clone, PartialEq, derive_more::Into, derive_more::From)] +pub struct AttrValue(Vec); + +impl fmt::Debug for AttrValue { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "AttrValue({:?})", self.0) + } +} impl IntoIterator for AttrValue { type IntoIter = std::vec::IntoIter; - type Item = StringOrVarRef; + type Item = AttrValueElement; fn into_iter(self) -> Self::IntoIter { self.0.into_iter() } } -impl FromIterator for AttrValue { - fn from_iter>(iter: T) -> Self { - let mut result = AttrValue(Vec::new()); - result.0.extend(iter); - result +impl FromIterator for AttrValue { + fn from_iter>(iter: T) -> Self { + AttrValue(iter.into_iter().collect()) } } impl AttrValue { pub fn from_primitive>(v: T) -> Self { - AttrValue(vec![StringOrVarRef::Primitive(v.into())]) + AttrValue(vec![AttrValueElement::Primitive(v.into())]) } - pub fn iter(&self) -> std::slice::Iter { + pub fn iter(&self) -> std::slice::Iter { self.0.iter() } @@ -39,9 +46,9 @@ impl AttrValue { pub fn resolve_one_level(self, variables: &HashMap) -> AttrValue { self.into_iter() .flat_map(|entry| match entry { - StringOrVarRef::VarRef(var_name) => match variables.get(&var_name) { + AttrValueElement::VarRef(var_name) => match variables.get(&var_name) { Some(value) => value.0.clone(), - _ => vec![StringOrVarRef::VarRef(var_name)], + _ => vec![AttrValueElement::VarRef(var_name)], }, _ => vec![entry], }) @@ -51,8 +58,8 @@ impl AttrValue { pub fn resolve_fully(self, variables: &HashMap) -> Result { self.into_iter() .map(|element| match element { - StringOrVarRef::Primitive(x) => Ok(x), - StringOrVarRef::VarRef(var_name) => variables + AttrValueElement::Primitive(x) => Ok(x), + AttrValueElement::VarRef(var_name) => variables .get(&var_name) .cloned() .with_context(|| format!("Unknown variable '{}' referenced", var_name)), @@ -72,7 +79,7 @@ impl AttrValue { if c == '}' { curly_count -= 1; if curly_count == 0 { - elements.push(StringOrVarRef::VarRef(VarName(std::mem::take(varref)))); + elements.push(AttrValueElement::VarRef(VarName(std::mem::take(varref)))); cur_varref = None } } else { @@ -84,7 +91,7 @@ impl AttrValue { curly_count += 1; if curly_count == 2 { if !cur_word.is_empty() { - elements.push(StringOrVarRef::primitive(std::mem::take(&mut cur_word))); + elements.push(AttrValueElement::primitive(std::mem::take(&mut cur_word))); } cur_varref = Some(String::new()) } @@ -94,35 +101,44 @@ impl AttrValue { } } if let Some(unfinished_varref) = cur_varref.take() { - elements.push(StringOrVarRef::primitive(unfinished_varref)); + elements.push(AttrValueElement::primitive(unfinished_varref)); } else if !cur_word.is_empty() { - elements.push(StringOrVarRef::primitive(cur_word.to_owned())); + elements.push(AttrValueElement::primitive(cur_word.to_owned())); } AttrValue(elements) } } -#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] -pub enum StringOrVarRef { +#[derive(Clone, PartialEq, Serialize, Deserialize)] +pub enum AttrValueElement { Primitive(PrimitiveValue), VarRef(VarName), } -impl StringOrVarRef { +impl fmt::Debug for AttrValueElement { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + AttrValueElement::Primitive(x) => write!(f, "Primitive({:?})", x), + AttrValueElement::VarRef(x) => write!(f, "VarRef({:?})", x), + } + } +} + +impl AttrValueElement { pub fn primitive(s: String) -> Self { - StringOrVarRef::Primitive(PrimitiveValue::from_string(s)) + AttrValueElement::Primitive(PrimitiveValue::from_string(s)) } pub fn as_var_ref(&self) -> Option<&VarName> { match self { - StringOrVarRef::VarRef(x) => Some(&x), + AttrValueElement::VarRef(x) => Some(&x), _ => None, } } pub fn as_primitive(&self) -> Option<&PrimitiveValue> { match self { - StringOrVarRef::Primitive(x) => Some(&x), + AttrValueElement::Primitive(x) => Some(&x), _ => None, } } diff --git a/src/value/mod.rs b/src/value/mod.rs index e2b7e45..035f0db 100644 --- a/src/value/mod.rs +++ b/src/value/mod.rs @@ -5,11 +5,10 @@ use std::fmt; pub mod attr_value; pub mod primitive; -pub mod string_with_varrefs; pub use attr_value::*; pub use primitive::*; -pub use string_with_varrefs::*; +/// The name of a variable #[repr(transparent)] #[derive( Clone, Hash, PartialEq, Eq, derive_more::AsRef, derive_more::From, derive_more::FromStr, Serialize, Deserialize, RefCast, @@ -34,6 +33,7 @@ impl fmt::Debug for VarName { } } +/// The name of an attribute #[repr(transparent)] #[derive( Clone, Hash, PartialEq, Eq, derive_more::AsRef, derive_more::From, derive_more::FromStr, Serialize, Deserialize, RefCast, @@ -54,6 +54,6 @@ impl fmt::Display for AttrName { impl fmt::Debug for AttrName { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "AttrName({})", self.0) + write!(f, "AttrName(\"{}\")", self.0) } } diff --git a/src/value/primitive.rs b/src/value/primitive.rs index e367821..417df50 100644 --- a/src/value/primitive.rs +++ b/src/value/primitive.rs @@ -16,7 +16,7 @@ impl fmt::Display for PrimitiveValue { } impl fmt::Debug for PrimitiveValue { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "\"{}\"", self) + write!(f, "\"{}\"", self.0) } }