VarName newtype, nothing works RN just tmp
This commit is contained in:
parent
9f69bbb440
commit
1f86c72ef6
10 changed files with 148 additions and 49 deletions
21
Cargo.lock
generated
21
Cargo.lock
generated
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 },
|
||||
|
|
40
src/value.rs
40
src/value.rs
|
@ -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))
|
||||
}
|
||||
|
|
|
@ -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; }
|
||||
});
|
||||
}
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Reference in a new issue