Implement basic cli with IPC

This commit is contained in:
elkowar 2020-09-23 01:06:17 +02:00
parent ada307aac2
commit c9c9f25afb
8 changed files with 527 additions and 88 deletions

326
Cargo.lock generated
View file

@ -30,7 +30,7 @@ version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
dependencies = [ dependencies = [
"winapi", "winapi 0.3.9",
] ]
[[package]] [[package]]
@ -65,6 +65,17 @@ dependencies = [
"system-deps", "system-deps",
] ]
[[package]]
name = "atty"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
dependencies = [
"hermit-abi",
"libc",
"winapi 0.3.9",
]
[[package]] [[package]]
name = "autocfg" name = "autocfg"
version = "1.0.1" version = "1.0.1"
@ -85,12 +96,28 @@ dependencies = [
"rustc-demangle", "rustc-demangle",
] ]
[[package]]
name = "bincode"
version = "1.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f30d3a39baa26f9651f17b375061f3233dde33424a8b72b0dbe93a68a0bc896d"
dependencies = [
"byteorder",
"serde",
]
[[package]] [[package]]
name = "bitflags" name = "bitflags"
version = "1.2.1" version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
[[package]]
name = "byteorder"
version = "1.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"
[[package]] [[package]]
name = "cairo-rs" name = "cairo-rs"
version = "0.9.1" version = "0.9.1"
@ -129,6 +156,42 @@ version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
[[package]]
name = "clap"
version = "2.33.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002"
dependencies = [
"ansi_term",
"atty",
"bitflags",
"strsim",
"textwrap",
"unicode-width",
"vec_map",
]
[[package]]
name = "crossbeam-channel"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b153fe7cbef478c567df0f972e02e6d736db11affe43dfc9c56a9374d1adfb87"
dependencies = [
"crossbeam-utils",
"maybe-uninit",
]
[[package]]
name = "crossbeam-utils"
version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8"
dependencies = [
"autocfg",
"cfg-if",
"lazy_static",
]
[[package]] [[package]]
name = "ctor" name = "ctor"
version = "0.1.15" version = "0.1.15"
@ -232,17 +295,33 @@ version = "0.1.0"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"derive_more", "derive_more",
"extend",
"gdk", "gdk",
"gio", "gio",
"glib", "glib",
"gtk", "gtk",
"hocon", "hocon",
"ipc-channel",
"maplit", "maplit",
"pretty_assertions", "pretty_assertions",
"regex", "regex",
"serde",
"structopt",
"try_match", "try_match",
] ]
[[package]]
name = "extend"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c635fdc695a9cbf89115695b04c27c864fa1bf5a94a253798a7bd0752fad5e5"
dependencies = [
"proc-macro-error",
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "failure" name = "failure"
version = "0.1.8" version = "0.1.8"
@ -265,6 +344,28 @@ dependencies = [
"synstructure", "synstructure",
] ]
[[package]]
name = "fnv"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
name = "fuchsia-zircon"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82"
dependencies = [
"bitflags",
"fuchsia-zircon-sys",
]
[[package]]
name = "fuchsia-zircon-sys"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7"
[[package]] [[package]]
name = "futures" name = "futures"
version = "0.3.5" version = "0.3.5"
@ -473,7 +574,7 @@ dependencies = [
"gobject-sys", "gobject-sys",
"libc", "libc",
"system-deps", "system-deps",
"winapi", "winapi 0.3.9",
] ]
[[package]] [[package]]
@ -587,6 +688,15 @@ dependencies = [
"unicode-segmentation", "unicode-segmentation",
] ]
[[package]]
name = "hermit-abi"
version = "0.1.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c30f6d0bc6b00693347368a67d41b58f2fb851215ff1da49e90fe2c5c667151"
dependencies = [
"libc",
]
[[package]] [[package]]
name = "hocon" name = "hocon"
version = "0.3.5" version = "0.3.5"
@ -601,6 +711,33 @@ dependencies = [
"uuid", "uuid",
] ]
[[package]]
name = "iovec"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e"
dependencies = [
"libc",
]
[[package]]
name = "ipc-channel"
version = "0.14.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3698b8affd5656032a074a7d40b3c2a29b71971f3e1ff6042b9d40724e20d97c"
dependencies = [
"bincode",
"crossbeam-channel",
"fnv",
"lazy_static",
"libc",
"mio",
"rand",
"serde",
"tempfile",
"uuid",
]
[[package]] [[package]]
name = "itertools" name = "itertools"
version = "0.9.0" version = "0.9.0"
@ -620,6 +757,16 @@ dependencies = [
"regex", "regex",
] ]
[[package]]
name = "kernel32-sys"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
dependencies = [
"winapi 0.2.8",
"winapi-build",
]
[[package]] [[package]]
name = "lazy_static" name = "lazy_static"
version = "1.4.0" version = "1.4.0"
@ -632,12 +779,27 @@ version = "0.2.77"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2f96b10ec2560088a8e76961b00d47107b3a625fecb76dedb29ee7ccbf98235" checksum = "f2f96b10ec2560088a8e76961b00d47107b3a625fecb76dedb29ee7ccbf98235"
[[package]]
name = "log"
version = "0.4.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b"
dependencies = [
"cfg-if",
]
[[package]] [[package]]
name = "maplit" name = "maplit"
version = "1.0.2" version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d"
[[package]]
name = "maybe-uninit"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00"
[[package]] [[package]]
name = "memchr" name = "memchr"
version = "2.3.3" version = "2.3.3"
@ -654,6 +816,48 @@ dependencies = [
"autocfg", "autocfg",
] ]
[[package]]
name = "mio"
version = "0.6.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fce347092656428bc8eaf6201042cb551b8d67855af7374542a92a0fbfcac430"
dependencies = [
"cfg-if",
"fuchsia-zircon",
"fuchsia-zircon-sys",
"iovec",
"kernel32-sys",
"libc",
"log",
"miow",
"net2",
"slab",
"winapi 0.2.8",
]
[[package]]
name = "miow"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919"
dependencies = [
"kernel32-sys",
"net2",
"winapi 0.2.8",
"ws2_32-sys",
]
[[package]]
name = "net2"
version = "0.2.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ebc3ec692ed7c9a255596c67808dee269f64655d8baf7b4f0638e51ba1d6853"
dependencies = [
"cfg-if",
"libc",
"winapi 0.3.9",
]
[[package]] [[package]]
name = "nom" name = "nom"
version = "4.2.3" version = "4.2.3"
@ -682,7 +886,7 @@ version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53cdc5b785b7a58c5aad8216b3dfa114df64b0b06ae6e1501cef91df2fbdf8f9" checksum = "53cdc5b785b7a58c5aad8216b3dfa114df64b0b06ae6e1501cef91df2fbdf8f9"
dependencies = [ dependencies = [
"winapi", "winapi 0.3.9",
] ]
[[package]] [[package]]
@ -866,6 +1070,12 @@ dependencies = [
"rand_core", "rand_core",
] ]
[[package]]
name = "redox_syscall"
version = "0.1.57"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce"
[[package]] [[package]]
name = "regex" name = "regex"
version = "1.3.9" version = "1.3.9"
@ -884,6 +1094,15 @@ version = "0.6.18"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26412eb97c6b088a6997e05f69403a802a92d520de2f8e63c2b65f9e0f47c4e8" checksum = "26412eb97c6b088a6997e05f69403a802a92d520de2f8e63c2b65f9e0f47c4e8"
[[package]]
name = "remove_dir_all"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
dependencies = [
"winapi 0.3.9",
]
[[package]] [[package]]
name = "rustc-demangle" name = "rustc-demangle"
version = "0.1.16" version = "0.1.16"
@ -895,6 +1114,20 @@ name = "serde"
version = "1.0.116" version = "1.0.116"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96fe57af81d28386a513cbc6858332abc6117cfdb5999647c6444b8f43a370a5" checksum = "96fe57af81d28386a513cbc6858332abc6117cfdb5999647c6444b8f43a370a5"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.116"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f630a6370fd8e457873b4bd2ffdae75408bc291ba72be773772a4c2a065d9ae8"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "slab" name = "slab"
@ -902,6 +1135,36 @@ version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
[[package]]
name = "strsim"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
[[package]]
name = "structopt"
version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6cc388d94ffabf39b5ed5fadddc40147cb21e605f53db6f8f36a625d27489ac5"
dependencies = [
"clap",
"lazy_static",
"structopt-derive",
]
[[package]]
name = "structopt-derive"
version = "0.4.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e2513111825077552a6751dfad9e11ce0fba07d7276a3943a037d7e93e64c5f"
dependencies = [
"heck",
"proc-macro-error",
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "strum" name = "strum"
version = "0.18.0" version = "0.18.0"
@ -958,6 +1221,29 @@ dependencies = [
"version-compare", "version-compare",
] ]
[[package]]
name = "tempfile"
version = "3.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9"
dependencies = [
"cfg-if",
"libc",
"rand",
"redox_syscall",
"remove_dir_all",
"winapi 0.3.9",
]
[[package]]
name = "textwrap"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
dependencies = [
"unicode-width",
]
[[package]] [[package]]
name = "thiserror" name = "thiserror"
version = "1.0.20" version = "1.0.20"
@ -1025,6 +1311,12 @@ version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0" checksum = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0"
[[package]]
name = "unicode-width"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3"
[[package]] [[package]]
name = "unicode-xid" name = "unicode-xid"
version = "0.2.1" version = "0.2.1"
@ -1040,6 +1332,12 @@ dependencies = [
"rand", "rand",
] ]
[[package]]
name = "vec_map"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
[[package]] [[package]]
name = "version-compare" name = "version-compare"
version = "0.0.10" version = "0.0.10"
@ -1064,6 +1362,12 @@ version = "0.9.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
[[package]]
name = "winapi"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
[[package]] [[package]]
name = "winapi" name = "winapi"
version = "0.3.9" version = "0.3.9"
@ -1074,6 +1378,12 @@ dependencies = [
"winapi-x86_64-pc-windows-gnu", "winapi-x86_64-pc-windows-gnu",
] ]
[[package]]
name = "winapi-build"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
[[package]] [[package]]
name = "winapi-i686-pc-windows-gnu" name = "winapi-i686-pc-windows-gnu"
version = "0.4.0" version = "0.4.0"
@ -1085,3 +1395,13 @@ name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0" version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "ws2_32-sys"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e"
dependencies = [
"winapi 0.2.8",
"winapi-build",
]

View file

@ -13,18 +13,17 @@ gio = { version = "", features = ["v2_44"] }
glib = { version = "", features = ["v2_44"] } glib = { version = "", features = ["v2_44"] }
regex = "1" regex = "1"
hocon = { version = "0.3", default-features = false, features = [ "serde-support" ]} hocon = { version = "0.3", default-features = false, features = [ "serde-support" ]}
try_match = "0.2.2" try_match = "0.2.2"
anyhow = "1.0" anyhow = "1.0"
#thiserror = "1.0"
derive_more = "0.99" derive_more = "0.99"
maplit = "1" maplit = "1"
structopt = "0.3"
ipc-channel="0.14.1"
serde = {version = "1.0", features = ["derive"]}
extend = "0.3.0"
#thiserror = "1.0"
[dev-dependencies] [dev-dependencies]
pretty_assertions = "0.6.1" pretty_assertions = "0.6.1"

View file

@ -37,13 +37,13 @@ impl WidgetDefinition {
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub enum ElementUse { pub enum ElementUse {
Widget(WidgetUse), Widget(WidgetUse),
Text(String), Text(AttrValue),
} }
impl ElementUse { impl ElementUse {
pub fn parse_hocon(hocon: Hocon) -> Result<Self> { pub fn parse_hocon(hocon: Hocon) -> Result<Self> {
match hocon { match hocon {
Hocon::String(s) => Ok(ElementUse::Text(s)), Hocon::String(s) => Ok(ElementUse::Text(AttrValue::from_string(s))),
Hocon::Hash(hash) => WidgetUse::parse_hocon_hash(hash).map(ElementUse::Widget), Hocon::Hash(hash) => WidgetUse::parse_hocon_hash(hash).map(ElementUse::Widget),
_ => Err(anyhow!("'{:?}' is not a valid element", hocon)), _ => Err(anyhow!("'{:?}' is not a valid element", hocon)),
} }
@ -73,7 +73,7 @@ impl WidgetUse {
// TODO allow for `layout_horizontal: [ elements ]` shorthand // TODO allow for `layout_horizontal: [ elements ]` shorthand
let children = match &widget_config.get("children") { let children = match &widget_config.get("children") {
Some(Hocon::String(text)) => Ok(vec![ElementUse::Text(text.to_string())]), Some(Hocon::String(text)) => Ok(vec![ElementUse::Text(AttrValue::from_string(text.to_string()))]),
Some(Hocon::Array(children)) => children Some(Hocon::Array(children)) => children
.clone() .clone()
.into_iter() .into_iter()
@ -120,7 +120,7 @@ mod test {
fn test_parse_text() { fn test_parse_text() {
assert_eq!( assert_eq!(
ElementUse::parse_hocon(Hocon::String("hi".to_string())).unwrap(), ElementUse::parse_hocon(Hocon::String("hi".to_string())).unwrap(),
ElementUse::Text("hi".to_string()) ElementUse::Text(AttrValue::Concrete(PrimitiveValue::String("hi".to_string())))
); );
} }

View file

@ -10,6 +10,12 @@ pub struct EwwState {
state: HashMap<String, PrimitiveValue>, state: HashMap<String, PrimitiveValue>,
} }
impl std::fmt::Debug for EwwState {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "EwwState {{ state: {:?} }}", self.state)
}
}
impl EwwState { impl EwwState {
pub fn from_default_vars(defaults: HashMap<String, PrimitiveValue>) -> Self { pub fn from_default_vars(defaults: HashMap<String, PrimitiveValue>) -> Self {
EwwState { EwwState {

View file

@ -7,8 +7,10 @@ use anyhow::*;
use gdk::*; use gdk::*;
use gio::prelude::*; use gio::prelude::*;
use gtk::prelude::*; use gtk::prelude::*;
use gtk::{Application, ApplicationWindow}; use ipc_channel::ipc;
use serde::{Deserialize, Serialize};
use std::collections::HashMap; use std::collections::HashMap;
use structopt::StructOpt;
pub mod config; pub mod config;
pub mod eww_state; pub mod eww_state;
@ -43,7 +45,8 @@ const EXAMPLE_CONFIG: &str = r#"{
} } } }
{ layout: { { layout: {
children: [ children: [
"hi", "date" // TODO FIX!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
{ label: { text: "$$date" } }
{ button: { children: "click me you" } } { button: { children: "click me you" } }
{ slider: { value: "$$some_value", min: 0, max: 100, onchange: "notify-send 'changed' {}" } } { slider: { value: "$$some_value", min: 0, max: 100, onchange: "notify-send 'changed' {}" } }
{ slider: { value: "$$some_value", orientation: "vertical" } } { slider: { value: "$$some_value", orientation: "vertical" } }
@ -64,6 +67,7 @@ const EXAMPLE_CONFIG: &str = r#"{
}, },
default_vars: { default_vars: {
ree: 12 ree: 12
date: "never"
} }
windows: { windows: {
main_window: { main_window: {
@ -80,95 +84,174 @@ const EXAMPLE_CONFIG: &str = r#"{
}, },
}"#; }"#;
#[derive(Debug)]
enum MuhhMsg {
UpdateValue(String, PrimitiveValue),
}
fn main() { fn main() {
if let Err(e) = try_main() { if let Err(e) = try_main() {
eprintln!("{:?}", e); eprintln!("{:?}", e);
} }
} }
#[derive(StructOpt, Debug, Serialize, Deserialize)]
struct Opt {
#[structopt(subcommand)]
action: OptAction,
}
#[derive(StructOpt, Debug, Serialize, Deserialize)]
enum OptAction {
#[structopt(name = "update")]
Update(OptActionUpdate),
#[structopt(name = "open")]
OpenWindow(OptActionOpen),
}
#[derive(StructOpt, Debug, Serialize, Deserialize)]
struct OptActionUpdate {
fieldname: String,
value: PrimitiveValue,
}
#[derive(StructOpt, Debug, Serialize, Deserialize)]
struct OptActionOpen {
window_name: String,
}
fn try_main() -> Result<()> { fn try_main() -> Result<()> {
let opts: Opt = StructOpt::from_args();
if let Ok(sender) = find_server_process() {
sender.send(opts)?;
} else {
initialize_server(opts)?;
}
Ok(())
}
fn find_server_process() -> Result<ipc::IpcSender<Opt>> {
let instance_path = std::fs::read_to_string("/tmp/eww-instance-path")?;
Ok(ipc::IpcSender::connect(instance_path)?)
}
fn initialize_server(opts: Opt) -> Result<()> {
let eww_config = config::EwwConfig::from_hocon(&config::parse_hocon(EXAMPLE_CONFIG)?)?; let eww_config = config::EwwConfig::from_hocon(&config::parse_hocon(EXAMPLE_CONFIG)?)?;
let application = Application::new(Some("de.elkowar.eww"), gio::ApplicationFlags::FLAGS_NONE) let mut app = App {
.expect("failed to initialize GTK application "); eww_state: EwwState::from_default_vars(eww_config.get_default_vars().clone()),
eww_config,
};
let window_def = eww_config.get_windows()["main_window"].clone(); let (send, recv) = glib::MainContext::channel(glib::PRIORITY_DEFAULT);
application.connect_activate(move |app| { gtk::init()?;
let result: Result<()> = try {
let app_window = ApplicationWindow::new(app);
app_window.set_title("Eww");
app_window.set_wmclass("noswallow", "noswallow");
app_window.set_type_hint(gdk::WindowTypeHint::Dock);
app_window.set_position(gtk::WindowPosition::Center);
app_window.set_keep_above(true);
app_window.set_default_size(window_def.size.0, window_def.size.1);
app_window.set_visual(
app_window
.get_display()
.get_default_screen()
.get_rgba_visual()
.or_else(|| app_window.get_display().get_default_screen().get_system_visual())
.as_ref(),
);
app_window.fullscreen(); app.handle_user_command(opts)?;
let mut eww_state = EwwState::from_default_vars(eww_config.get_default_vars().clone());
let empty_local_state = HashMap::new();
app_window.add(&widgets::element_to_gtk_thing(
&eww_config.get_widgets(),
&mut eww_state,
&empty_local_state,
&window_def.widget,
)?);
app_window.show_all();
let (tx, rx) = glib::MainContext::channel(glib::PRIORITY_DEFAULT);
std::thread::spawn(move || event_loop(tx));
rx.attach(None, move |msg| {
match msg {
MuhhMsg::UpdateValue(key, value) => eww_state.update_value(key, value),
}
std::thread::spawn(move || run_ipc_server(send));
recv.attach(None, move |msg| {
app.handle_event(msg);
glib::Continue(true) glib::Continue(true)
}); });
let window = app_window.get_window().unwrap(); gtk::main();
window.set_override_redirect(true);
window.move_(window_def.position.0, window_def.position.1);
window.show();
window.raise();
};
if let Err(err) = result {
eprintln!("{:?}", err);
std::process::exit(1);
}
});
application.run(&[]);
Ok(()) Ok(())
} }
fn event_loop(sender: glib::Sender<MuhhMsg>) { fn run_ipc_server(send: glib::Sender<EwwEvent>) -> Result<()> {
loop {
let (ipc_server, instance_path): (ipc::IpcOneShotServer<Opt>, _) = ipc::IpcOneShotServer::new()?;
std::fs::write("/tmp/eww-instance-path", instance_path)?;
let (receiver, initial) = ipc_server.accept()?;
send.send(EwwEvent::UserCommand(initial))?;
}
}
#[derive(Debug)]
struct App {
eww_state: EwwState,
eww_config: config::EwwConfig,
}
impl App {
fn handle_user_command(&mut self, opts: Opt) -> Result<()> {
match opts.action {
OptAction::Update(update) => self.update_state(update),
OptAction::OpenWindow(update) => self.open_window(update)?,
}
Ok(())
}
fn update_state(&mut self, update: OptActionUpdate) {
self.eww_state.update_value(update.fieldname, update.value);
}
fn open_window(&mut self, open_window: OptActionOpen) -> Result<()> {
let window_def = self.eww_config.get_windows()[&open_window.window_name].clone();
let window = gtk::Window::new(gtk::WindowType::Toplevel);
window.set_title("Eww");
window.set_wmclass("noswallow", "noswallow");
window.set_type_hint(gdk::WindowTypeHint::Dock);
window.set_position(gtk::WindowPosition::Center);
window.set_keep_above(true);
window.set_default_size(window_def.size.0, window_def.size.1);
window.set_visual(
window
.get_display()
.get_default_screen()
.get_rgba_visual()
.or_else(|| window.get_display().get_default_screen().get_system_visual())
.as_ref(),
);
window.fullscreen();
let empty_local_state = HashMap::new();
window.add(&widgets::element_to_gtk_thing(
&self.eww_config.get_widgets(),
&mut self.eww_state,
&empty_local_state,
&window_def.widget,
)?);
window.show_all();
let gdk_window = window.get_window().unwrap();
gdk_window.set_override_redirect(true);
gdk_window.move_(window_def.position.0, window_def.position.1);
gdk_window.show();
gdk_window.raise();
Ok(())
}
fn handle_event(&mut self, event: EwwEvent) {
let result: Result<_> = try {
match event {
EwwEvent::UserCommand(command) => self.handle_user_command(command)?,
}
};
if let Err(err) = result {
eprintln!("Error while handling event: {:?}", err);
}
}
}
#[derive(Debug)]
enum EwwEvent {
UserCommand(Opt),
}
fn event_loop(sender: glib::Sender<EwwEvent>) {
let mut x = 0; let mut x = 0;
loop { loop {
x += 1; x += 1;
std::thread::sleep(std::time::Duration::from_millis(1000)); std::thread::sleep(std::time::Duration::from_millis(1000));
sender let event_opt = Opt {
.send(MuhhMsg::UpdateValue( action: OptAction::Update(OptActionUpdate {
"ree".to_string(), fieldname: "ree".to_string(),
PrimitiveValue::Number(x as f64 * 10.0), value: PrimitiveValue::Number(x as f64 * 10.0),
)) }),
.unwrap(); };
sender.send(EwwEvent::UserCommand(event_opt)).unwrap();
} }
} }

View file

@ -1,16 +1,32 @@
use anyhow::*; use anyhow::*;
use derive_more; use derive_more;
use hocon::Hocon; use hocon::Hocon;
use serde::{Deserialize, Serialize};
use std::convert::TryFrom; use std::convert::TryFrom;
use try_match::try_match; use try_match::try_match;
#[derive(Clone, Debug, PartialEq, derive_more::From)] #[derive(Clone, Debug, PartialEq, Deserialize, Serialize, derive_more::From)]
pub enum PrimitiveValue { pub enum PrimitiveValue {
String(String), String(String),
Number(f64), Number(f64),
Boolean(bool), Boolean(bool),
} }
impl std::str::FromStr for PrimitiveValue {
type Err = anyhow::Error;
fn from_str(s: &str) -> Result<PrimitiveValue> {
Ok(s.parse()
.map(PrimitiveValue::Number)
.or_else(|_| s.parse().map(PrimitiveValue::Boolean))
.unwrap_or_else(|_| PrimitiveValue::String(remove_surrounding(s, '\'').to_string())))
}
}
fn remove_surrounding(s: &str, surround: char) -> &str {
s.strip_prefix(surround).unwrap_or(s).strip_suffix(surround).unwrap_or(s)
}
impl TryFrom<PrimitiveValue> for String { impl TryFrom<PrimitiveValue> for String {
type Error = anyhow::Error; type Error = anyhow::Error;
fn try_from(x: PrimitiveValue) -> Result<Self> { fn try_from(x: PrimitiveValue) -> Result<Self> {
@ -102,8 +118,15 @@ impl AttrValue {
pub fn as_var_ref(&self) -> Result<&String> { pub fn as_var_ref(&self) -> Result<&String> {
try_match!(AttrValue::VarRef(x) = self).map_err(|e| anyhow!("{:?} is not a VarRef", e)) try_match!(AttrValue::VarRef(x) = self).map_err(|e| anyhow!("{:?} is not a VarRef", e))
} }
}
pub fn from_string(s: String) -> Self {
if s.starts_with("$$") {
AttrValue::VarRef(s.trim_start_matches("$$").to_string())
} else {
AttrValue::Concrete(PrimitiveValue::String(s.clone()))
}
}
}
impl From<PrimitiveValue> for AttrValue { impl From<PrimitiveValue> for AttrValue {
fn from(value: PrimitiveValue) -> Self { fn from(value: PrimitiveValue) -> Self {
AttrValue::Concrete(value) AttrValue::Concrete(value)
@ -114,8 +137,7 @@ impl std::convert::TryFrom<&Hocon> for AttrValue {
type Error = anyhow::Error; type Error = anyhow::Error;
fn try_from(value: &Hocon) -> Result<Self> { fn try_from(value: &Hocon) -> Result<Self> {
Ok(match value { Ok(match value {
Hocon::String(s) if s.starts_with("$$") => AttrValue::VarRef(s.trim_start_matches("$$").to_string()), Hocon::String(s) => AttrValue::from_string(s.clone()),
Hocon::String(s) => AttrValue::Concrete(PrimitiveValue::String(s.clone())),
Hocon::Integer(n) => AttrValue::Concrete(PrimitiveValue::Number(*n as f64)), Hocon::Integer(n) => AttrValue::Concrete(PrimitiveValue::Number(*n as f64)),
Hocon::Real(n) => AttrValue::Concrete(PrimitiveValue::Number(*n as f64)), Hocon::Real(n) => AttrValue::Concrete(PrimitiveValue::Number(*n as f64)),
Hocon::Boolean(b) => AttrValue::Concrete(PrimitiveValue::Boolean(*b)), Hocon::Boolean(b) => AttrValue::Concrete(PrimitiveValue::Boolean(*b)),

View file

@ -30,7 +30,7 @@ pub fn element_to_gtk_thing(
element: &element::ElementUse, element: &element::ElementUse,
) -> Result<gtk::Widget> { ) -> Result<gtk::Widget> {
match element { match element {
element::ElementUse::Text(text) => Ok(gtk::Label::new(Some(&text)).upcast()), element::ElementUse::Text(text) => Ok(gtk::Label::new(Some(text.as_string()?)).upcast()), // TODO this should use resolve
element::ElementUse::Widget(widget) => { element::ElementUse::Widget(widget) => {
let gtk_container = build_gtk_widget(widget_definitions, eww_state, local_env, widget)?; let gtk_container = build_gtk_widget(widget_definitions, eww_state, local_env, widget)?;

View file

@ -55,6 +55,7 @@ pub(super) fn widget_to_gtk_widget(bargs: &mut BuilderArgs) -> Result<Option<gtk
"image" => build_gtk_image(bargs)?.upcast(), "image" => build_gtk_image(bargs)?.upcast(),
"layout" => build_gtk_layout(bargs)?.upcast(), "layout" => build_gtk_layout(bargs)?.upcast(),
"button" => build_gtk_button(bargs)?.upcast(), "button" => build_gtk_button(bargs)?.upcast(),
"label" => build_gtk_label(bargs)?.upcast(),
_ => return Ok(None), _ => return Ok(None),
}; };
Ok(Some(gtk_widget)) Ok(Some(gtk_widget))
@ -100,6 +101,14 @@ fn build_gtk_layout(bargs: &mut BuilderArgs) -> Result<gtk::Box> {
Ok(gtk_widget) Ok(gtk_widget)
} }
fn build_gtk_label(bargs: &mut BuilderArgs) -> Result<gtk::Label> {
let gtk_widget = gtk::Label::new(None);
resolve!(bargs, gtk_widget, {
resolve_str => "text" = 10.0 => |v| gtk_widget.set_text(&v),
});
Ok(gtk_widget)
}
fn parse_orientation(o: &str) -> gtk::Orientation { fn parse_orientation(o: &str) -> gtk::Orientation {
match o { match o {
"vertical" | "v" => gtk::Orientation::Vertical, "vertical" | "v" => gtk::Orientation::Vertical,