there was an attempt at variable intrepolation support
This commit is contained in:
parent
3cbd81219b
commit
f173ec04e3
4 changed files with 100 additions and 855 deletions
815
Cargo.lock
generated
815
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -11,8 +11,10 @@ gtk = { version = "0.9", features = [ "v3_16" ] }
|
||||||
gdk = { version = "", features = ["v3_16"] }
|
gdk = { version = "", features = ["v3_16"] }
|
||||||
gio = { version = "", features = ["v2_44"] }
|
gio = { version = "", features = ["v2_44"] }
|
||||||
|
|
||||||
|
regex = "1"
|
||||||
|
|
||||||
hocon = { version = "0.3", features = [ "serde-support" ]}
|
|
||||||
|
hocon = { version = "0.3", default-features = false, features = [ "serde-support" ]}
|
||||||
|
|
||||||
try_match = "0.2.2"
|
try_match = "0.2.2"
|
||||||
|
|
||||||
|
@ -20,8 +22,3 @@ anyhow = "1.0"
|
||||||
#thiserror = "1.0"
|
#thiserror = "1.0"
|
||||||
|
|
||||||
|
|
||||||
[target.x86_64-unknown-linux-gnu]
|
|
||||||
rustflags = [
|
|
||||||
"-C", "link-arg=-fuse-ld=lld",
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,14 @@
|
||||||
use anyhow::*;
|
use anyhow::*;
|
||||||
use hocon::*;
|
use hocon::*;
|
||||||
use hocon_ext::HoconExt;
|
use hocon_ext::HoconExt;
|
||||||
use std::collections::HashMap;
|
use std::{collections::HashMap, convert::TryFrom};
|
||||||
use try_match::try_match;
|
use try_match::try_match;
|
||||||
|
|
||||||
pub mod hocon_ext;
|
pub mod hocon_ext;
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
|
pub struct AttrValue(pub String);
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub struct WidgetDefinition {
|
pub struct WidgetDefinition {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
|
@ -22,8 +25,7 @@ pub enum ElementUse {
|
||||||
pub struct WidgetUse {
|
pub struct WidgetUse {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub children: Vec<ElementUse>,
|
pub children: Vec<ElementUse>,
|
||||||
pub num_attrs: HashMap<String, f64>,
|
pub attrs: HashMap<String, AttrValue>,
|
||||||
pub str_attrs: HashMap<String, String>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WidgetUse {
|
impl WidgetUse {
|
||||||
|
@ -31,8 +33,7 @@ impl WidgetUse {
|
||||||
WidgetUse {
|
WidgetUse {
|
||||||
name,
|
name,
|
||||||
children,
|
children,
|
||||||
num_attrs: HashMap::new(),
|
attrs: HashMap::new(),
|
||||||
str_attrs: HashMap::new(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -85,25 +86,18 @@ pub fn parse_widget_use(data: HashMap<String, Hocon>) -> Result<WidgetUse> {
|
||||||
)),
|
)),
|
||||||
}?;
|
}?;
|
||||||
|
|
||||||
let str_attrs: HashMap<String, String> = widget_config
|
let attrs: HashMap<String, AttrValue> = widget_config
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter_map(|(key, value)| {
|
.filter_map(|(key, value)| {
|
||||||
Some((
|
Some((
|
||||||
key.clone(),
|
key.clone(),
|
||||||
try_match!(Hocon::String(x) = value).ok()?.clone(),
|
match value {
|
||||||
))
|
Hocon::String(s) => AttrValue(s.to_string()),
|
||||||
})
|
Hocon::Integer(n) => AttrValue(format!("{}", n)),
|
||||||
.collect();
|
Hocon::Real(n) => AttrValue(format!("{}", n)),
|
||||||
|
Hocon::Boolean(b) => AttrValue(format!("{}", b)),
|
||||||
let num_attrs: HashMap<String, f64> = widget_config
|
_ => return None,
|
||||||
.iter()
|
},
|
||||||
.filter_map(|(key, value)| {
|
|
||||||
Some((
|
|
||||||
key.to_string(),
|
|
||||||
try_match!(Hocon::Integer(x) = value)
|
|
||||||
.map(|&x| x as f64)
|
|
||||||
.or_else(|_| try_match!(Hocon::Real(x) = value).map(|&x| x as f64))
|
|
||||||
.ok()?,
|
|
||||||
))
|
))
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
@ -111,8 +105,7 @@ pub fn parse_widget_use(data: HashMap<String, Hocon>) -> Result<WidgetUse> {
|
||||||
Ok(WidgetUse {
|
Ok(WidgetUse {
|
||||||
name: widget_name.to_string(),
|
name: widget_name.to_string(),
|
||||||
children,
|
children,
|
||||||
str_attrs,
|
attrs,
|
||||||
num_attrs,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,6 +143,7 @@ mod test {
|
||||||
name: "example_widget".to_string(),
|
name: "example_widget".to_string(),
|
||||||
structure: ElementUse::Widget(WidgetUse {
|
structure: ElementUse::Widget(WidgetUse {
|
||||||
name: "layout_horizontal".to_string(),
|
name: "layout_horizontal".to_string(),
|
||||||
|
attrs: HashMap::new(),
|
||||||
children: vec![
|
children: vec![
|
||||||
ElementUse::Widget(WidgetUse::new(
|
ElementUse::Widget(WidgetUse::new(
|
||||||
"text".to_string(),
|
"text".to_string(),
|
||||||
|
|
89
src/main.rs
89
src/main.rs
|
@ -1,11 +1,14 @@
|
||||||
|
#![feature(try_blocks)]
|
||||||
extern crate gio;
|
extern crate gio;
|
||||||
extern crate gtk;
|
extern crate gtk;
|
||||||
|
|
||||||
use anyhow::*;
|
use anyhow::{self, Context, Result};
|
||||||
use gdk::*;
|
use gdk::*;
|
||||||
use gio::prelude::*;
|
use gio::prelude::*;
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
use gtk::{Adjustment, Application, ApplicationWindow, Button, Scale};
|
use gtk::{Adjustment, Application, ApplicationWindow, Button, Scale};
|
||||||
|
use regex::Regex;
|
||||||
|
use std::{collections::HashMap, str::FromStr};
|
||||||
|
|
||||||
pub mod config;
|
pub mod config;
|
||||||
pub mod widgets;
|
pub mod widgets;
|
||||||
|
@ -20,6 +23,7 @@ fn main() -> Result<()> {
|
||||||
window.set_wmclass("noswallow", "noswallow");
|
window.set_wmclass("noswallow", "noswallow");
|
||||||
window.set_type_hint(gdk::WindowTypeHint::Dock);
|
window.set_type_hint(gdk::WindowTypeHint::Dock);
|
||||||
window.set_position(gtk::WindowPosition::Center);
|
window.set_position(gtk::WindowPosition::Center);
|
||||||
|
window.set_keep_above(true);
|
||||||
|
|
||||||
let element = config::parse_element_use(
|
let element = config::parse_element_use(
|
||||||
config::parse_hocon(
|
config::parse_hocon(
|
||||||
|
@ -37,7 +41,10 @@ fn main() -> Result<()> {
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
window.add(&element_to_gtk_widget(&element).unwrap());
|
|
||||||
|
let widget_state = WidgetState(HashMap::new());
|
||||||
|
|
||||||
|
window.add(&element_to_gtk_widget(&widget_state, &element).unwrap());
|
||||||
|
|
||||||
window.show_all();
|
window.show_all();
|
||||||
});
|
});
|
||||||
|
@ -46,16 +53,21 @@ fn main() -> Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn element_to_gtk_widget(element: &config::ElementUse) -> Option<gtk::Widget> {
|
fn element_to_gtk_widget(
|
||||||
|
widget_state: &WidgetState,
|
||||||
|
element: &config::ElementUse,
|
||||||
|
) -> Option<gtk::Widget> {
|
||||||
match element {
|
match element {
|
||||||
config::ElementUse::Text(text) => Some(gtk::Label::new(Some(&text)).upcast()),
|
config::ElementUse::Text(text) => Some(gtk::Label::new(Some(&text)).upcast()),
|
||||||
config::ElementUse::Widget(widget) => {
|
config::ElementUse::Widget(widget) => widget_use_to_gtk_container(widget_state, &widget)
|
||||||
widget_use_to_gtk_container(&widget).or(widget_use_to_gtk_widget(&widget))
|
.or(widget_use_to_gtk_widget(widget_state, &widget)),
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn widget_use_to_gtk_container(widget: &config::WidgetUse) -> Option<gtk::Widget> {
|
fn widget_use_to_gtk_container(
|
||||||
|
widget_state: &WidgetState,
|
||||||
|
widget: &config::WidgetUse,
|
||||||
|
) -> Option<gtk::Widget> {
|
||||||
let container_widget: gtk::Container = match widget.name.as_str() {
|
let container_widget: gtk::Container = match widget.name.as_str() {
|
||||||
"layout_horizontal" => gtk::Box::new(gtk::Orientation::Horizontal, 0).upcast(),
|
"layout_horizontal" => gtk::Box::new(gtk::Orientation::Horizontal, 0).upcast(),
|
||||||
"button" => gtk::Button::new().upcast(),
|
"button" => gtk::Button::new().upcast(),
|
||||||
|
@ -63,20 +75,73 @@ fn widget_use_to_gtk_container(widget: &config::WidgetUse) -> Option<gtk::Widget
|
||||||
};
|
};
|
||||||
|
|
||||||
for child in &widget.children {
|
for child in &widget.children {
|
||||||
container_widget.add(&element_to_gtk_widget(child)?);
|
container_widget.add(&element_to_gtk_widget(widget_state, child)?);
|
||||||
}
|
}
|
||||||
Some(container_widget.upcast())
|
Some(container_widget.upcast())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn widget_use_to_gtk_widget(widget: &config::WidgetUse) -> Option<gtk::Widget> {
|
fn widget_use_to_gtk_widget(
|
||||||
|
widget_state: &WidgetState,
|
||||||
|
widget: &config::WidgetUse,
|
||||||
|
) -> Option<gtk::Widget> {
|
||||||
let new_widget: gtk::Widget = match widget.name.as_str() {
|
let new_widget: gtk::Widget = match widget.name.as_str() {
|
||||||
"slider" => gtk::Scale::new(
|
"slider" => {
|
||||||
|
let slider_value: f64 = widget_state.resolve(widget.attrs.get("value")?)?;
|
||||||
|
|
||||||
|
gtk::Scale::new(
|
||||||
gtk::Orientation::Horizontal,
|
gtk::Orientation::Horizontal,
|
||||||
Some(>k::Adjustment::new(50.0, 0.0, 100.0, 1.0, 1.0, 1.0)),
|
Some(>k::Adjustment::new(
|
||||||
|
slider_value,
|
||||||
|
0.0,
|
||||||
|
100.0,
|
||||||
|
1.0,
|
||||||
|
1.0,
|
||||||
|
1.0,
|
||||||
|
)),
|
||||||
)
|
)
|
||||||
.upcast(),
|
.upcast()
|
||||||
|
}
|
||||||
|
|
||||||
_ => return None,
|
_ => return None,
|
||||||
};
|
};
|
||||||
Some(new_widget)
|
Some(new_widget)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct WidgetState(HashMap<String, config::AttrValue>);
|
||||||
|
|
||||||
|
impl WidgetState {
|
||||||
|
pub fn resolve<T>(&self, value: &config::AttrValue) -> Option<String>
|
||||||
|
where
|
||||||
|
T: FromStr,
|
||||||
|
{
|
||||||
|
let var_pattern: Regex = Regex::new(r"\$\$\{(.*)\}").unwrap();
|
||||||
|
let config::AttrValue(value) = value;
|
||||||
|
|
||||||
|
let mut missing_var: Option<String> = None;
|
||||||
|
var_pattern.replace_all(value, |caps: ®ex::Captures| {
|
||||||
|
self.lookup_full::<T>(&caps[1]).unwrap_or_else(|| {
|
||||||
|
missing_var = Some(caps[1].to_string());
|
||||||
|
"missing".to_string()
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
// TODO REEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEe
|
||||||
|
|
||||||
|
unimplemented!();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn lookup_full<T>(&self, key: &str) -> Option<String>
|
||||||
|
where
|
||||||
|
T: FromStr,
|
||||||
|
{
|
||||||
|
self.resolve::<T>(self.0.get(key)?)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// macro_rules! build {
|
||||||
|
// ($var_name:ident = $value:expr ; $code:block) => {{
|
||||||
|
// let mut $var_name = $value;
|
||||||
|
// $code;
|
||||||
|
// $var_name
|
||||||
|
// }};
|
||||||
|
// }
|
||||||
|
|
Loading…
Add table
Reference in a new issue