VarName newtype, nothing works RN just tmp

This commit is contained in:
elkowar 2020-10-06 20:06:16 +02:00
parent 9f69bbb440
commit 1f86c72ef6
10 changed files with 148 additions and 49 deletions

21
Cargo.lock generated
View file

@ -319,6 +319,7 @@ dependencies = [
"num",
"pretty_assertions",
"pretty_env_logger",
"ref-cast",
"regex",
"roxmltree",
"scheduled-executor",
@ -1428,6 +1429,26 @@ version = "0.1.57"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce"
[[package]]
name = "ref-cast"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "745c1787167ddae5569661d5ffb8b25ae5fedbf46717eaa92d652221cec72623"
dependencies = [
"ref-cast-impl",
]
[[package]]
name = "ref-cast-impl"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d21b475ab879ef0e315ad99067fa25778c3b0377f57f1b00207448dac1a3144"
dependencies = [
"proc-macro2",
"quote 1.0.7",
"syn 1.0.41",
]
[[package]]
name = "regex"
version = "1.3.9"

View file

@ -13,6 +13,7 @@ gio = { version = "", features = ["v2_44"] }
glib = { version = "", features = ["v2_44"] }
gdk-pixbuf = "0.9"
regex = "1"
try_match = "0.2.2"
anyhow = "1.0"
@ -36,6 +37,7 @@ log = "0.4"
pretty_env_logger = "0.4"
lazy_static = "1.4.0"
libc = "0.2"
ref-cast = "1.0"
#thiserror = "1.0"

View file

@ -2,11 +2,12 @@ use crate::*;
use debug_stub_derive::*;
use script_var_handler::*;
use std::collections::HashMap;
use value::VarName;
#[derive(Debug)]
pub enum EwwEvent {
UserCommand(Opt),
UpdateVar(String, PrimitiveValue),
UpdateVar(VarName, PrimitiveValue),
ReloadConfig(config::EwwConfig),
ReloadCss(String),
}
@ -33,6 +34,7 @@ impl App {
std::process::exit(0)
}
}
Ok(())
}
@ -51,7 +53,7 @@ impl App {
}
}
fn update_state(&mut self, fieldname: String, value: PrimitiveValue) {
fn update_state(&mut self, fieldname: VarName, value: PrimitiveValue) {
self.eww_state.update_value(fieldname, value);
}

View file

@ -4,6 +4,7 @@ use regex::Regex;
use std::ops::Range;
use crate::value::AttrValue;
use crate::value::VarName;
use crate::with_text_pos_context;
use maplit::hashmap;
use std::collections::HashMap;
@ -140,7 +141,7 @@ impl StringOrVarRef {
fn to_attr_value(self) -> AttrValue {
match self {
StringOrVarRef::String(x) => AttrValue::Concrete(PrimitiveValue::parse_string(&x)),
StringOrVarRef::VarRef(x) => AttrValue::VarRef(x),
StringOrVarRef::VarRef(x) => AttrValue::VarRef(VarName(x)),
}
}
}
@ -214,7 +215,7 @@ mod test {
#[test]
fn test_text_with_var_refs() {
let expected_attr_value1 = mk_attr_str("my text");
let expected_attr_value2 = AttrValue::VarRef("var".to_owned());
let expected_attr_value2 = AttrValue::VarRef(VarName("var".to_owned()));
let widget = WidgetUse::from_text_with_var_refs("my text{{var}}");
assert_eq!(
widget,

View file

@ -1,5 +1,6 @@
use crate::util;
use crate::value::PrimitiveValue;
use crate::value::VarName;
use anyhow::*;
use element::*;
use std::collections::HashMap;
@ -37,7 +38,7 @@ macro_rules! ensure_xml_tag_is {
#[derive(Clone, Debug, PartialEq)]
pub struct ScriptVar {
pub name: String,
pub name: VarName,
pub command: String,
pub interval: std::time::Duration,
}
@ -46,7 +47,7 @@ impl ScriptVar {
pub fn from_xml_element(xml: XmlElement) -> Result<Self> {
ensure_xml_tag_is!(xml, "script-var");
let name = xml.attr("name")?.to_owned();
let name = VarName(xml.attr("name")?.to_owned());
let interval = util::parse_duration(xml.attr("interval")?)?;
let command = xml.only_child()?.as_text()?.text();
Ok(ScriptVar { name, interval, command })
@ -121,13 +122,17 @@ impl EwwConfig {
}
// TODO this is kinda ugly
pub fn generate_initial_state(&self) -> Result<HashMap<String, PrimitiveValue>> {
pub fn generate_initial_state(&self) -> Result<HashMap<VarName, PrimitiveValue>> {
let mut vars = self
.script_vars
.iter()
.map(|var| Ok((var.name.to_string(), crate::eww_state::run_command(&var.command)?)))
.map(|var| Ok((var.name.clone(), crate::eww_state::run_command(&var.command)?)))
.collect::<Result<HashMap<_, _>>>()?;
vars.extend(self.get_default_vars().into_iter().map(|(k, v)| (k.clone(), v.clone())));
vars.extend(
self.get_default_vars()
.into_iter()
.map(|(k, v)| (VarName(k.clone()), v.clone())),
);
Ok(vars)
}

View file

@ -1,15 +1,42 @@
use crate::value::VarName;
use anyhow::*;
use std::collections::HashMap;
use std::convert::TryFrom;
use std::convert::TryInto;
use std::process::Command;
use std::sync::Arc;
use crate::value::{AttrValue, PrimitiveValue};
#[derive(Default)]
//pub struct StateChangeHandler(Box<dyn Fn(HashMap<String, PrimitiveValue>) + 'static>);
pub struct StateChangeHandlers {
handlers: HashMap<VarName, Vec<Arc<dyn Fn(HashMap<String, PrimitiveValue>) + 'static>>>,
}
impl StateChangeHandlers {
fn put_handler(&mut self, var_names: Vec<VarName>, handler: Arc<dyn Fn(HashMap<String, PrimitiveValue>) + 'static>) {
for var_name in var_names {
let entry: &mut Vec<Arc<dyn Fn(HashMap<String, PrimitiveValue>) + 'static>> =
self.handlers.entry(var_name).or_insert_with(Vec::new);
entry.push(handler);
}
}
}
pub struct EwwState {
on_change_handlers: HashMap<String, Vec<Box<dyn Fn(PrimitiveValue) + 'static>>>,
state: HashMap<String, PrimitiveValue>,
state_change_handlers: StateChangeHandlers,
//on_change_handlers: HashMap<VarName, Vec<StateChangeHandler>>,
state: HashMap<VarName, PrimitiveValue>,
}
impl Default for EwwState {
fn default() -> Self {
EwwState {
state_change_handlers: StateChangeHandlers {
handlers: HashMap::new(),
},
state: HashMap::new(),
}
}
}
impl std::fmt::Debug for EwwState {
@ -19,7 +46,7 @@ impl std::fmt::Debug for EwwState {
}
impl EwwState {
pub fn from_default_vars(defaults: HashMap<String, PrimitiveValue>) -> Self {
pub fn from_default_vars(defaults: HashMap<VarName, PrimitiveValue>) -> Self {
EwwState {
state: defaults,
..EwwState::default()
@ -30,7 +57,7 @@ impl EwwState {
self.on_change_handlers.clear();
}
pub fn update_value(&mut self, key: String, value: PrimitiveValue) {
pub fn update_value(&mut self, key: VarName, value: PrimitiveValue) {
if let Some(handlers) = self.on_change_handlers.get(&key) {
for on_change in handlers {
on_change(value.clone());
@ -41,20 +68,20 @@ impl EwwState {
pub fn resolve<F: Fn(PrimitiveValue) + 'static + Clone>(
&mut self,
local_env: &HashMap<String, AttrValue>,
local_env: &HashMap<VarName, AttrValue>,
value: &AttrValue,
set_value: F,
) -> bool {
match value {
AttrValue::VarRef(name) => {
// get value from globals
if let Some(value) = self.state.get(name).cloned() {
if let Some(value) = self.state.get(&name).cloned() {
self.on_change_handlers
.entry(name.to_string())
.entry(name.clone())
.or_insert_with(Vec::new)
.push(Box::new(set_value.clone()));
self.resolve(local_env, &value.into(), set_value)
} else if let Some(value) = local_env.get(name).cloned() {
} else if let Some(value) = local_env.get(&name).cloned() {
// get value from local
self.resolve(local_env, &value, set_value)
} else {
@ -69,21 +96,20 @@ impl EwwState {
}
}
pub fn resolve_into<TE: std::fmt::Debug, V: TryFrom<PrimitiveValue, Error = TE>, F: Fn(V) + 'static + Clone>(
&mut self,
local_env: &HashMap<String, AttrValue>,
value: &AttrValue,
set_value: F,
) -> bool {
self.resolve(local_env, value, move |x| {
if let Err(e) = x.try_into().map(|v| set_value(v)) {
eprintln!("error while resolving value: {:?}", e);
};
})
}
//pub fn resolve_attrs<F: Fn(HashMap<String, PrimitiveValue>) + 'static + Clone>(
//&mut self,
//local_env: &HashMap<VarName, AttrValue>,
//unresolved_attrs: HashMap<String, AttrValue>,
//state_update_handler: F,
//) {
//let var_names = values.iter().filter_map(|value| value.as_var_ref().ok()).collect();
//self.state_change_handlers
//.put_handler(var_names, Arc::new(state_update_handler))
//}
pub fn resolve_f64<F: Fn(f64) + 'static + Clone>(
&mut self,
local_env: &HashMap<String, AttrValue>,
local_env: &HashMap<VarName, AttrValue>,
value: &AttrValue,
set_value: F,
) -> bool {
@ -97,7 +123,7 @@ impl EwwState {
#[allow(dead_code)]
pub fn resolve_bool<F: Fn(bool) + 'static + Clone>(
&mut self,
local_env: &HashMap<String, AttrValue>,
local_env: &HashMap<VarName, AttrValue>,
value: &AttrValue,
set_value: F,
) -> bool {
@ -109,7 +135,7 @@ impl EwwState {
}
pub fn resolve_str<F: Fn(String) + 'static + Clone>(
&mut self,
local_env: &HashMap<String, AttrValue>,
local_env: &HashMap<VarName, AttrValue>,
value: &AttrValue,
set_value: F,
) -> bool {

View file

@ -17,6 +17,7 @@ use std::collections::HashMap;
use std::path::{Path, PathBuf};
use structopt::StructOpt;
use value::PrimitiveValue;
use value::VarName;
pub mod app;
pub mod config;
@ -65,7 +66,7 @@ pub struct Opt {
#[derive(StructOpt, Debug, Serialize, Deserialize)]
pub enum OptAction {
#[structopt(name = "update")]
Update { fieldname: String, value: PrimitiveValue },
Update { fieldname: VarName, value: PrimitiveValue },
#[structopt(name = "open")]
OpenWindow { window_name: String },

View file

@ -1,6 +1,7 @@
use anyhow::*;
use derive_more;
use lazy_static::lazy_static;
use ref_cast::RefCast;
use regex::Regex;
use serde::{Deserialize, Serialize};
use std::convert::TryFrom;
@ -103,10 +104,38 @@ impl PrimitiveValue {
}
}
#[repr(transparent)]
#[derive(
Debug,
Clone,
Hash,
PartialEq,
Eq,
derive_more::AsRef,
derive_more::From,
derive_more::FromStr,
Serialize,
Deserialize,
RefCast,
)]
pub struct VarName(pub String);
impl std::borrow::Borrow<str> for VarName {
fn borrow(&self) -> &str {
&self.0
}
}
impl fmt::Display for VarName {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}
#[derive(Clone, Debug, PartialEq)]
pub enum AttrValue {
Concrete(PrimitiveValue),
VarRef(String),
VarRef(VarName),
}
impl AttrValue {
@ -129,6 +158,13 @@ impl AttrValue {
}
}
pub fn as_var_ref(&self) -> Result<VarName> {
match self {
AttrValue::VarRef(x) => Ok(x),
_ => Err(anyhow!("{:?} is not a variable reference", self)),
}
}
/// parses the value, trying to turn it into VarRef,
/// a number and a boolean first, before deciding that it is a string.
pub fn parse_string(s: String) -> Self {
@ -137,7 +173,7 @@ impl AttrValue {
};
if let Some(ref_name) = PATTERN.captures(&s).and_then(|cap| cap.get(1)).map(|x| x.as_str()) {
AttrValue::VarRef(ref_name.to_owned())
AttrValue::VarRef(VarName(ref_name.to_owned()))
} else {
AttrValue::Concrete(PrimitiveValue::String(s))
}

View file

@ -1,8 +1,10 @@
use crate::config::element;
use crate::eww_state::*;
use crate::value::AttrValue;
use crate::value::{AttrValue, VarName};
use anyhow::*;
use gtk::prelude::*;
use itertools::Itertools;
use ref_cast::RefCast;
use std::{collections::HashMap, process::Command};
use widget_definitions::*;
@ -19,7 +21,7 @@ pub fn run_command<T: std::fmt::Display>(cmd: &str, arg: T) {
struct BuilderArgs<'a, 'b, 'c> {
eww_state: &'a mut EwwState,
local_env: &'b HashMap<String, AttrValue>,
local_env: &'b HashMap<VarName, AttrValue>,
widget: &'c element::WidgetUse,
unhandled_attrs: Vec<&'c str>,
}
@ -27,7 +29,7 @@ struct BuilderArgs<'a, 'b, 'c> {
pub fn element_to_gtk_thing(
widget_definitions: &HashMap<String, element::WidgetDefinition>,
eww_state: &mut EwwState,
local_env: &HashMap<String, AttrValue>,
local_env: &HashMap<VarName, AttrValue>,
widget: &element::WidgetUse,
) -> Result<gtk::Widget> {
let gtk_container = build_gtk_widget(widget_definitions, eww_state, local_env, widget)?;
@ -36,7 +38,7 @@ pub fn element_to_gtk_thing(
gtk_container
} else if let Some(def) = widget_definitions.get(widget.name.as_str()) {
let mut local_env = local_env.clone();
local_env.extend(widget.attrs.clone());
local_env.extend(widget.attrs.clone().into_iter().map(|(k, v)| (VarName(k), v)));
let custom_widget = element_to_gtk_thing(widget_definitions, eww_state, &local_env, &def.structure)?;
custom_widget.get_style_context().add_class(widget.name.as_str());
custom_widget
@ -50,14 +52,14 @@ pub fn element_to_gtk_thing(
pub fn build_gtk_widget(
widget_definitions: &HashMap<String, element::WidgetDefinition>,
eww_state: &mut EwwState,
local_env: &HashMap<String, AttrValue>,
local_env: &HashMap<VarName, AttrValue>,
widget: &element::WidgetUse,
) -> Result<Option<gtk::Widget>> {
let mut bargs = BuilderArgs {
eww_state,
local_env,
widget,
unhandled_attrs: widget.attrs.keys().map(|x| x.as_str()).collect(),
unhandled_attrs: widget.attrs.keys().map(|x| x.as_ref()).collect(),
};
let gtk_widget = match widget_to_gtk_widget(&mut bargs) {
Ok(Some(gtk_widget)) => gtk_widget,
@ -150,10 +152,13 @@ macro_rules! resolve {
// with default
($args:ident, $gtk_widget:ident, $func:ident => $attr:literal [$default:expr] => |$arg:ident| $body:expr) => {
$args.unhandled_attrs.retain(|a| a != &$attr);
$args.eww_state.$func($args.local_env, $args.widget.attrs.get($attr).unwrap_or(&AttrValue::Concrete(PrimitiveValue::from($default))), {
$args.eww_state.$func(
$args.local_env, $args.widget.attrs.get($attr).unwrap_or(&AttrValue::Concrete(PrimitiveValue::from($default))),
{
let $gtk_widget = $gtk_widget.clone();
move |$arg| { $body; }
});
}
);
};
}

View file

@ -1,6 +1,6 @@
use super::{run_command, BuilderArgs};
use crate::resolve;
use crate::value::{AttrValue, PrimitiveValue};
use crate::value::{AttrValue, PrimitiveValue, VarName};
use anyhow::*;
use gtk::prelude::*;
use gtk::ImageExt;