From 71cbc7ca4975978845b0beb2b70c5a4dfc9bac6b Mon Sep 17 00:00:00 2001 From: elkowar <5300871+elkowar@users.noreply.github.com> Date: Sat, 3 Oct 2020 20:14:37 +0200 Subject: [PATCH] Handle script-var command polling --- Cargo.lock | 519 ++++++++++++++++++++++++++++-- Cargo.toml | 3 + src/app.rs | 60 +++- src/config/element.rs | 47 ++- src/config/mod.rs | 104 ++++-- src/eww_state.rs | 15 +- src/main.rs | 50 +-- src/util.rs | 29 ++ src/value.rs | 7 - src/widgets/widget_definitions.rs | 10 +- 10 files changed, 732 insertions(+), 112 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fbd1dcc..32faaf5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -101,6 +101,16 @@ version = "1.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" +[[package]] +name = "bytes" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" +dependencies = [ + "byteorder", + "iovec", +] + [[package]] name = "cairo-rs" version = "0.9.1" @@ -154,6 +164,15 @@ dependencies = [ "vec_map", ] +[[package]] +name = "cloudabi" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" +dependencies = [ + "bitflags", +] + [[package]] name = "codemap" version = "0.1.3" @@ -170,6 +189,43 @@ dependencies = [ "maybe-uninit", ] +[[package]] +name = "crossbeam-deque" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f02af974daeee82218205558e51ec8768b48cf524bd01d550abe5573a608285" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", + "maybe-uninit", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "058ed274caafc1f60c4997b5fc07bf7dc7cca454af7c6e81edffe5f33f70dace" +dependencies = [ + "autocfg", + "cfg-if", + "crossbeam-utils", + "lazy_static", + "maybe-uninit", + "memoffset", + "scopeguard", +] + +[[package]] +name = "crossbeam-queue" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "774ba60a54c213d409d5353bda12d49cd68d14e45036a285234c8d6f91f92570" +dependencies = [ + "cfg-if", + "crossbeam-utils", + "maybe-uninit", +] + [[package]] name = "crossbeam-utils" version = "0.7.2" @@ -187,8 +243,18 @@ version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39858aa5bac06462d4dd4b9164848eb81ffc4aa5c479746393598fd193afa227" dependencies = [ - "quote", - "syn", + "quote 1.0.7", + "syn 1.0.41", +] + +[[package]] +name = "debug_stub_derive" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "496b7f8a2f853313c3ca370641d7ff3e42c32974fdccda8f0684599ed0a3ff6b" +dependencies = [ + "quote 0.3.15", + "syn 0.11.11", ] [[package]] @@ -198,8 +264,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1dcfabdab475c16a93d669dddfc393027803e347d09663f524447f642fbb84ba" dependencies = [ "proc-macro2", - "quote", - "syn", + "quote 1.0.7", + "syn 1.0.41", ] [[package]] @@ -220,6 +286,7 @@ version = "0.1.0" dependencies = [ "anyhow", "crossbeam-channel", + "debug_stub_derive", "derive_more", "extend", "gdk", @@ -231,10 +298,12 @@ dependencies = [ "ipc-channel", "itertools", "maplit", + "notify", "num", "pretty_assertions", "regex", "roxmltree", + "scheduled-executor", "serde", "stoppable_thread", "structopt", @@ -249,8 +318,8 @@ checksum = "0c635fdc695a9cbf89115695b04c27c864fa1bf5a94a253798a7bd0752fad5e5" dependencies = [ "proc-macro-error", "proc-macro2", - "quote", - "syn", + "quote 1.0.7", + "syn 1.0.41", ] [[package]] @@ -306,6 +375,12 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" +[[package]] +name = "futures" +version = "0.1.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b980f2816d6ee8673b6517b52cb0e808a180efc92e5c19d02cdda79066703ef" + [[package]] name = "futures" version = "0.3.5" @@ -337,6 +412,16 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "59f5fff90fd5d971f936ad674802482ba441b6f09ba5e15fd8b39145582ca399" +[[package]] +name = "futures-cpupool" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" +dependencies = [ + "futures 0.1.29", + "num_cpus", +] + [[package]] name = "futures-executor" version = "0.3.5" @@ -362,8 +447,8 @@ checksum = "d0b5a30a4328ab5473878237c447333c093297bded83a4983d10f4deea240d39" dependencies = [ "proc-macro-hack", "proc-macro2", - "quote", - "syn", + "quote 1.0.7", + "syn 1.0.41", ] [[package]] @@ -484,7 +569,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fb60242bfff700772dae5d9e3a1f7aa2e4ebccf18b89662a16acb2822568561" dependencies = [ "bitflags", - "futures", + "futures 0.3.5", "futures-channel", "futures-core", "futures-io", @@ -542,8 +627,8 @@ dependencies = [ "proc-macro-crate", "proc-macro-error", "proc-macro2", - "quote", - "syn", + "quote 1.0.7", + "syn 1.0.41", ] [[package]] @@ -673,7 +758,7 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba0add391e9cd7d19c29024617a44df79c867ab003bce7f3224c1636595ec740" dependencies = [ - "log", + "log 0.4.11", "notify", ] @@ -780,6 +865,24 @@ version = "0.2.77" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2f96b10ec2560088a8e76961b00d47107b3a625fecb76dedb29ee7ccbf98235" +[[package]] +name = "lock_api" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4da24a77a3d8a6d4862d95f72e6fdb9c09a643ecdb402d754004a557f2bec75" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "log" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" +dependencies = [ + "log 0.4.11", +] + [[package]] name = "log" version = "0.4.11" @@ -807,6 +910,15 @@ version = "2.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400" +[[package]] +name = "memoffset" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "043175f069eda7b85febe4a74abbaeff828d9f8b448515d3151a14a3542811aa" +dependencies = [ + "autocfg", +] + [[package]] name = "mio" version = "0.6.22" @@ -819,7 +931,7 @@ dependencies = [ "iovec", "kernel32-sys", "libc", - "log", + "log 0.4.11", "miow", "net2", "slab", @@ -833,11 +945,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52403fe290012ce777c4626790c8951324a2b9e3316b3143779c72b029742f19" dependencies = [ "lazycell", - "log", + "log 0.4.11", "mio", "slab", ] +[[package]] +name = "mio-uds" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afcb699eb26d4332647cc848492bbc15eafb26f08d0304550d5aa1f612e066f0" +dependencies = [ + "iovec", + "libc", + "mio", +] + [[package]] name = "miow" version = "0.2.1" @@ -955,6 +1078,16 @@ dependencies = [ "autocfg", ] +[[package]] +name = "num_cpus" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3" +dependencies = [ + "hermit-abi", + "libc", +] + [[package]] name = "once_cell" version = "1.4.1" @@ -997,13 +1130,39 @@ dependencies = [ "system-deps", ] +[[package]] +name = "parking_lot" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" +dependencies = [ + "lock_api", + "parking_lot_core", + "rustc_version", +] + +[[package]] +name = "parking_lot_core" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b" +dependencies = [ + "cfg-if", + "cloudabi", + "libc", + "redox_syscall", + "rustc_version", + "smallvec 0.6.13", + "winapi 0.3.9", +] + [[package]] name = "peekmore" version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e029e89e27328ecf6a2e0820b5767ce6deb10872f2f18fb9e98d2e8ab7aef29f" dependencies = [ - "smallvec", + "smallvec 1.4.2", ] [[package]] @@ -1037,8 +1196,8 @@ dependencies = [ "phf_shared", "proc-macro-hack", "proc-macro2", - "quote", - "syn", + "quote 1.0.7", + "syn 1.0.41", ] [[package]] @@ -1066,8 +1225,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2c0e815c3ee9a031fdf5af21c10aa17c573c9c6a566328d99e3936c34e36461f" dependencies = [ "proc-macro2", - "quote", - "syn", + "quote 1.0.7", + "syn 1.0.41", ] [[package]] @@ -1117,8 +1276,8 @@ checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" dependencies = [ "proc-macro-error-attr", "proc-macro2", - "quote", - "syn", + "quote 1.0.7", + "syn 1.0.41", "version_check", ] @@ -1129,7 +1288,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ "proc-macro2", - "quote", + "quote 1.0.7", "version_check", ] @@ -1151,9 +1310,15 @@ version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "36e28516df94f3dd551a587da5357459d9b36d945a7c37c3557928c1c2ff2a2c" dependencies = [ - "unicode-xid", + "unicode-xid 0.2.1", ] +[[package]] +name = "quote" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" + [[package]] name = "quote" version = "1.0.7" @@ -1256,6 +1421,15 @@ dependencies = [ "xmlparser", ] +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +dependencies = [ + "semver", +] + [[package]] name = "same-file" version = "1.0.6" @@ -1265,6 +1439,45 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "scheduled-executor" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bd49c2044efea26d613a5a38d53c2148b378ba0c5bd297c1d056b4555401b9b" +dependencies = [ + "futures 0.1.29", + "futures-cpupool", + "log 0.3.9", + "tokio-core", +] + +[[package]] +name = "scoped-tls" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "332ffa32bf586782a3efaeb58f127980944bbc8c4d6913a86107ac2a5ab24b28" + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +dependencies = [ + "semver-parser", +] + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" + [[package]] name = "serde" version = "1.0.116" @@ -1281,8 +1494,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f630a6370fd8e457873b4bd2ffdae75408bc291ba72be773772a4c2a065d9ae8" dependencies = [ "proc-macro2", - "quote", - "syn", + "quote 1.0.7", + "syn 1.0.41", ] [[package]] @@ -1297,6 +1510,15 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" +[[package]] +name = "smallvec" +version = "0.6.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7b0758c52e15a8b5e3691eae6cc559f08eee9406e548a4477ba4e67770a82b6" +dependencies = [ + "maybe-uninit", +] + [[package]] name = "smallvec" version = "1.4.2" @@ -1335,8 +1557,8 @@ dependencies = [ "heck", "proc-macro-error", "proc-macro2", - "quote", - "syn", + "quote 1.0.7", + "syn 1.0.41", ] [[package]] @@ -1353,8 +1575,19 @@ checksum = "87c85aa3f8ea653bfd3ddf25f7ee357ee4d204731f6aa9ad04002306f6e2774c" dependencies = [ "heck", "proc-macro2", - "quote", - "syn", + "quote 1.0.7", + "syn 1.0.41", +] + +[[package]] +name = "syn" +version = "0.11.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" +dependencies = [ + "quote 0.3.15", + "synom", + "unicode-xid 0.0.4", ] [[package]] @@ -1364,8 +1597,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6690e3e9f692504b941dc6c3b188fd28df054f7fb8469ab40680df52fdcc842b" dependencies = [ "proc-macro2", - "quote", - "unicode-xid", + "quote 1.0.7", + "unicode-xid 0.2.1", +] + +[[package]] +name = "synom" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" +dependencies = [ + "unicode-xid 0.0.4", ] [[package]] @@ -1422,8 +1664,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd80fc12f73063ac132ac92aceea36734f04a1d93c1240c6944e23a3b8841793" dependencies = [ "proc-macro2", - "quote", - "syn", + "quote 1.0.7", + "syn 1.0.41", ] [[package]] @@ -1435,6 +1677,207 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "tokio" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a09c0b5bb588872ab2f09afa13ee6e9dac11e10a0ec9e8e3ba39a5a5d530af6" +dependencies = [ + "bytes", + "futures 0.1.29", + "mio", + "num_cpus", + "tokio-codec", + "tokio-current-thread", + "tokio-executor", + "tokio-fs", + "tokio-io", + "tokio-reactor", + "tokio-sync", + "tokio-tcp", + "tokio-threadpool", + "tokio-timer", + "tokio-udp", + "tokio-uds", +] + +[[package]] +name = "tokio-codec" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25b2998660ba0e70d18684de5d06b70b70a3a747469af9dea7618cc59e75976b" +dependencies = [ + "bytes", + "futures 0.1.29", + "tokio-io", +] + +[[package]] +name = "tokio-core" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aeeffbbb94209023feaef3c196a41cbcdafa06b4a6f893f68779bb5e53796f71" +dependencies = [ + "bytes", + "futures 0.1.29", + "iovec", + "log 0.4.11", + "mio", + "scoped-tls", + "tokio", + "tokio-executor", + "tokio-io", + "tokio-reactor", + "tokio-timer", +] + +[[package]] +name = "tokio-current-thread" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1de0e32a83f131e002238d7ccde18211c0a5397f60cbfffcb112868c2e0e20e" +dependencies = [ + "futures 0.1.29", + "tokio-executor", +] + +[[package]] +name = "tokio-executor" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb2d1b8f4548dbf5e1f7818512e9c406860678f29c300cdf0ebac72d1a3a1671" +dependencies = [ + "crossbeam-utils", + "futures 0.1.29", +] + +[[package]] +name = "tokio-fs" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "297a1206e0ca6302a0eed35b700d292b275256f596e2f3fea7729d5e629b6ff4" +dependencies = [ + "futures 0.1.29", + "tokio-io", + "tokio-threadpool", +] + +[[package]] +name = "tokio-io" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57fc868aae093479e3131e3d165c93b1c7474109d13c90ec0dda2a1bbfff0674" +dependencies = [ + "bytes", + "futures 0.1.29", + "log 0.4.11", +] + +[[package]] +name = "tokio-reactor" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09bc590ec4ba8ba87652da2068d150dcada2cfa2e07faae270a5e0409aa51351" +dependencies = [ + "crossbeam-utils", + "futures 0.1.29", + "lazy_static", + "log 0.4.11", + "mio", + "num_cpus", + "parking_lot", + "slab", + "tokio-executor", + "tokio-io", + "tokio-sync", +] + +[[package]] +name = "tokio-sync" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edfe50152bc8164fcc456dab7891fa9bf8beaf01c5ee7e1dd43a397c3cf87dee" +dependencies = [ + "fnv", + "futures 0.1.29", +] + +[[package]] +name = "tokio-tcp" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98df18ed66e3b72e742f185882a9e201892407957e45fbff8da17ae7a7c51f72" +dependencies = [ + "bytes", + "futures 0.1.29", + "iovec", + "mio", + "tokio-io", + "tokio-reactor", +] + +[[package]] +name = "tokio-threadpool" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df720b6581784c118f0eb4310796b12b1d242a7eb95f716a8367855325c25f89" +dependencies = [ + "crossbeam-deque", + "crossbeam-queue", + "crossbeam-utils", + "futures 0.1.29", + "lazy_static", + "log 0.4.11", + "num_cpus", + "slab", + "tokio-executor", +] + +[[package]] +name = "tokio-timer" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93044f2d313c95ff1cb7809ce9a7a05735b012288a888b62d4434fd58c94f296" +dependencies = [ + "crossbeam-utils", + "futures 0.1.29", + "slab", + "tokio-executor", +] + +[[package]] +name = "tokio-udp" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2a0b10e610b39c38b031a2fcab08e4b82f16ece36504988dcbd81dbba650d82" +dependencies = [ + "bytes", + "futures 0.1.29", + "log 0.4.11", + "mio", + "tokio-codec", + "tokio-io", + "tokio-reactor", +] + +[[package]] +name = "tokio-uds" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab57a4ac4111c8c9dbcf70779f6fc8bc35ae4b2454809febac840ad19bd7e4e0" +dependencies = [ + "bytes", + "futures 0.1.29", + "iovec", + "libc", + "log 0.4.11", + "mio", + "mio-uds", + "tokio-codec", + "tokio-io", + "tokio-reactor", +] + [[package]] name = "toml" version = "0.5.6" @@ -1463,8 +1906,8 @@ dependencies = [ "proc-macro-error", "proc-macro-hack", "proc-macro2", - "quote", - "syn", + "quote 1.0.7", + "syn 1.0.41", ] [[package]] @@ -1479,6 +1922,12 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3" +[[package]] +name = "unicode-xid" +version = "0.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" + [[package]] name = "unicode-xid" version = "0.2.1" diff --git a/Cargo.toml b/Cargo.toml index 92c94f3..3c9da6b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,11 +23,14 @@ serde = {version = "1.0", features = ["derive"]} extend = "0.3.0" grass = "0.10" hotwatch = "0.4" +notify = "4.0" crossbeam-channel = "0.4" num = "0.3" stoppable_thread = "0.2" roxmltree = "0.13" itertools = "0.9" +scheduled-executor = "0.4" +debug_stub_derive = "0.3" #thiserror = "1.0" diff --git a/src/app.rs b/src/app.rs index 6608373..9fb06fc 100644 --- a/src/app.rs +++ b/src/app.rs @@ -1,19 +1,27 @@ use crate::*; +use debug_stub_derive::*; use std::collections::HashMap; #[derive(Debug)] pub enum EwwEvent { UserCommand(Opt), + UpdateVar(String, PrimitiveValue), ReloadConfig(config::EwwConfig), ReloadCss(String), } -#[derive(Debug)] +#[derive(DebugStub)] pub struct App { pub eww_state: EwwState, pub eww_config: config::EwwConfig, pub windows: HashMap, pub css_provider: gtk::CssProvider, + #[debug_stub = "script-var poll script handles"] + pub script_var_poll_handles: Vec, + #[debug_stub = "script-var poll executor"] + pub script_var_poll_executor: scheduled_executor::CoreExecutor, + + pub app_evt_send: glib::Sender, } impl App { @@ -30,6 +38,7 @@ impl App { let result: Result<_> = try { match event { EwwEvent::UserCommand(command) => self.handle_user_command(command)?, + EwwEvent::UpdateVar(key, value) => self.update_state(key, value), EwwEvent::ReloadConfig(config) => self.reload_all_windows(config)?, EwwEvent::ReloadCss(css) => self.load_css(&css)?, } @@ -70,6 +79,10 @@ impl App { window.set_decorated(false); window.set_resizable(false); + // run on_screen_changed to set the visual correctly initially. + on_screen_changed(&window, None); + window.connect_screen_changed(on_screen_changed); + let empty_local_state = HashMap::new(); let root_widget = &widgets::element_to_gtk_thing( &self.eww_config.get_widgets(), @@ -95,8 +108,16 @@ impl App { } pub fn reload_all_windows(&mut self, config: config::EwwConfig) -> Result<()> { + // refresh script-var poll stuff + self.script_var_poll_handles.iter().for_each(|handle| handle.stop()); + self.script_var_poll_handles.clear(); + if let Err(e) = self.init_command_poll_tasks() { + eprintln!("Error while setting up script-var commands: {:?}", e); + } + self.eww_config = config; self.eww_state.clear_callbacks(); + let windows = self.windows.clone(); for (window_name, window) in windows { window.close(); @@ -109,4 +130,41 @@ impl App { self.css_provider.load_from_data(css.as_bytes())?; Ok(()) } + + pub fn init_command_poll_tasks(&mut self) -> Result<()> { + let evt_send = self.app_evt_send.clone(); + self.script_var_poll_handles = self + .eww_config + .get_script_vars() + .iter() + .map(|var| { + self.script_var_poll_executor.schedule_fixed_interval( + std::time::Duration::from_secs(0), + var.interval, + glib::clone!(@strong var, @strong evt_send => move |_| { + let result = eww_state::run_command(&var.command); + match result { + Ok(value) => { + let _ = evt_send.send(app::EwwEvent::UpdateVar(var.name.clone(), value)); + } + Err(e) => { + eprintln!("Error while running script-var command: {:?}", e); + } + } + }), + ) + }) + .collect_vec(); + Ok(()) + } +} + +fn on_screen_changed(window: >k::Window, _old_screen: Option<&gdk::Screen>) { + let visual = window.get_screen().and_then(|screen| { + screen + .get_rgba_visual() + .filter(|_| screen.is_composited()) + .or_else(|| screen.get_system_visual()) + }); + window.set_visual(visual.as_ref()); } diff --git a/src/config/element.rs b/src/config/element.rs index 663bd16..92d7792 100644 --- a/src/config/element.rs +++ b/src/config/element.rs @@ -1,4 +1,5 @@ use super::*; +use itertools::Itertools; use crate::value::AttrValue; use crate::with_text_pos_context; @@ -53,7 +54,9 @@ impl WidgetUse { } pub fn from_xml_node(xml: XmlNode) -> Result { match xml { - XmlNode::Text(text) => Ok(WidgetUse::simple_text(AttrValue::parse_string(text.text()))), + XmlNode::Text(text) => Ok(WidgetUse::simple_text(AttrValue::Concrete(PrimitiveValue::String( + text.text(), + )))), XmlNode::Element(elem) => Ok(WidgetUse { name: elem.tag_name().to_string(), children: with_text_pos_context! { elem => elem.children().map(WidgetUse::from_xml_node).collect::>()?}?, @@ -75,6 +78,26 @@ impl WidgetUse { } } + // TODO Even just thinking of this gives me horrible nightmares..... + //pub fn from_text(text: String) -> Self { + //WidgetUse::text_with_var_refs( + //text.split(" ") + //.map(|word| AttrValue::parse_string(word.to_owned())) + //.collect_vec(), + //) + //} + + //pub fn text_with_var_refs(elements: Vec) -> Self { + //dbg!(WidgetUse { + //name: "layout".to_owned(), + //attrs: hashmap! { + //"halign".to_owned() => AttrValue::Concrete(PrimitiveValue::String("center".to_owned())), + //"space-evenly".to_owned() => AttrValue::Concrete(PrimitiveValue::String("false".to_owned())), + //}, + //children: elements.into_iter().map(WidgetUse::simple_text).collect(), + //}) + //} + pub fn get_attr(&self, key: &str) -> Result<&AttrValue> { self.attrs .get(key) @@ -88,6 +111,10 @@ mod test { use maplit::hashmap; use pretty_assertions::assert_eq; + fn mk_attr_str(s: &str) -> AttrValue { + AttrValue::Concrete(PrimitiveValue::String(s.to_owned())) + } + #[test] fn test_simple_text() { let expected_attr_value = AttrValue::Concrete(PrimitiveValue::String("my text".to_owned())); @@ -102,6 +129,24 @@ 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 widget = WidgetUse::text_with_var_refs(vec![expected_attr_value1.clone(), expected_attr_value2.clone()]); + assert_eq!( + widget, + WidgetUse { + name: "layout".to_owned(), + attrs: hashmap! { "halign".to_owned() => mk_attr_str("center"), "space-evenly".to_owned() => mk_attr_str("false")}, + children: vec![ + WidgetUse::simple_text(expected_attr_value1), + WidgetUse::simple_text(expected_attr_value2), + ] + } + ) + } + #[test] fn test_parse_widget_use() { let input = r#" diff --git a/src/config/mod.rs b/src/config/mod.rs index 79fe75f..b0abdac 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -1,3 +1,4 @@ +use crate::util; use crate::value::PrimitiveValue; use anyhow::*; use element::*; @@ -19,11 +20,45 @@ macro_rules! try_type { }}; } +#[macro_export] +macro_rules! ensure_xml_tag_is { + ($element:ident, $name:literal) => { + ensure!( + $element.tag_name() == $name, + anyhow!( + "{} | Tag needed to be of type '{}', but was: {}", + $element.text_pos(), + $name, + $element.as_tag_string() + ) + ) + }; +} + +#[derive(Clone, Debug, PartialEq)] +pub struct ScriptVar { + pub name: String, + pub command: String, + pub interval: std::time::Duration, +} + +impl ScriptVar { + pub fn from_xml_element(xml: XmlElement) -> Result { + ensure_xml_tag_is!(xml, "script-var"); + + let name = 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 }) + } +} + #[derive(Debug, Clone)] pub struct EwwConfig { widgets: HashMap, windows: HashMap, - default_vars: HashMap, + initial_variables: HashMap, + script_vars: Vec, } impl EwwConfig { @@ -51,29 +86,44 @@ impl EwwConfig { .collect::>>() .context("error parsing window definitions")?; - let default_vars = xml - .child("variables") - .ok() - .map(|variables_node| { - variables_node - .child_elements() - .map(|child| { - Ok(( - child.tag_name().to_owned(), - PrimitiveValue::parse_string(&child.only_child()?.as_text()?.text()), - )) - }) - .collect::>>() - }) - .transpose() - .context("error parsing default variable value")? - .unwrap_or_default(); + let variables_block = xml.child("variables").ok(); - Ok(dbg!(EwwConfig { + let mut initial_variables = HashMap::new(); + let mut script_vars = Vec::new(); + if let Some(variables_block) = variables_block { + for node in variables_block.child_elements() { + match node.tag_name() { + "var" => { + initial_variables.insert( + node.attr("name")?.to_owned(), + PrimitiveValue::parse_string(&node.only_child()?.as_text()?.text()), + ); + } + "script-var" => { + script_vars.push(ScriptVar::from_xml_element(node)?); + } + _ => bail!("Illegal element in variables block: {}", node.as_tag_string()), + } + } + } + + Ok(EwwConfig { widgets: definitions, windows, - default_vars, - })) + initial_variables, + script_vars, + }) + } + + // TODO this is kinda ugly + pub fn generate_initial_state(&self) -> Result> { + let mut vars = self + .script_vars + .iter() + .map(|var| Ok((var.name.to_string(), crate::eww_state::run_command(&var.command)?))) + .collect::>>()?; + vars.extend(self.get_default_vars().into_iter().map(|(k, v)| (k.clone(), v.clone()))); + Ok(vars) } pub fn get_widgets(&self) -> &HashMap { @@ -83,7 +133,10 @@ impl EwwConfig { &self.windows } pub fn get_default_vars(&self) -> &HashMap { - &self.default_vars + &self.initial_variables + } + pub fn get_script_vars(&self) -> &Vec { + &self.script_vars } } @@ -96,12 +149,7 @@ pub struct EwwWindowDefinition { impl EwwWindowDefinition { pub fn from_xml_element(xml: XmlElement) -> Result { - if xml.tag_name() != "window" { - bail!( - "Only tags are valid window definitions, but found {}", - xml.as_tag_string() - ); - } + ensure_xml_tag_is!(xml, "window"); let size_node = xml.child("size")?; let size = (size_node.attr("x")?.parse()?, size_node.attr("y")?.parse()?); diff --git a/src/eww_state.rs b/src/eww_state.rs index 68c94b0..2a2c424 100644 --- a/src/eww_state.rs +++ b/src/eww_state.rs @@ -4,12 +4,11 @@ use std::convert::TryFrom; use std::convert::TryInto; use std::process::Command; -use crate::value::{AttrValue, CommandPollingUse, PrimitiveValue}; +use crate::value::{AttrValue, PrimitiveValue}; #[derive(Default)] pub struct EwwState { on_change_handlers: HashMap>>, - polling_commands: Vec<(CommandPollingUse, Box)>, state: HashMap, } @@ -31,10 +30,6 @@ impl EwwState { self.on_change_handlers.clear(); } - pub fn get_command_polling_uses(&self) -> Vec<&CommandPollingUse> { - self.polling_commands.iter().map(|(x, _)| x).collect() - } - pub fn update_value(&mut self, key: String, value: PrimitiveValue) { if let Some(handlers) = self.on_change_handlers.get(&key) { for on_change in handlers { @@ -67,13 +62,6 @@ impl EwwState { false } } - AttrValue::CommandPolling(command_polling_use) => { - self.polling_commands - .push((command_polling_use.clone(), Box::new(set_value.clone()))); - // TODO how do i handle commands needing to be run on the first resolve? this is an issue,.... - //self.resolve(local_env, &value.into(), set_value); - true - } AttrValue::Concrete(value) => { set_value(value.clone()); true @@ -135,5 +123,6 @@ impl EwwState { pub fn run_command(cmd: &str) -> Result { let output = String::from_utf8(Command::new("/bin/bash").arg("-c").arg(cmd).output()?.stdout)?; + let output = output.trim_matches('\n'); Ok(PrimitiveValue::from(output)) } diff --git a/src/main.rs b/src/main.rs index e74d4a7..29c80b1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,5 @@ #![feature(trace_macros)] +#![feature(iterator_fold_self)] #![feature(try_blocks)] extern crate gio; extern crate gtk; @@ -9,6 +10,8 @@ use gdk::*; use gtk::prelude::*; use hotwatch; use ipc_channel::ipc; +use itertools::Itertools; +use scheduled_executor; use serde::{Deserialize, Serialize}; use std::collections::HashMap; use std::path::{Path, PathBuf}; @@ -24,9 +27,9 @@ pub mod widgets; #[macro_export] macro_rules! build { - ($var_name:ident = $value:expr ; $code:block) => {{ + ($var_name:ident = $value:expr ; $($code:tt)*) => {{ let mut $var_name = $value; - $code; + $($code)* $var_name }}; } @@ -102,12 +105,16 @@ fn initialize_server(opts: Opt) -> Result<()> { let eww_config = config::EwwConfig::read_from_file(&config_file_path)?; gtk::init()?; + let (evt_send, evt_recv) = glib::MainContext::channel(glib::PRIORITY_DEFAULT); let mut app = app::App { - eww_state: EwwState::from_default_vars(eww_config.get_default_vars().clone()), + eww_state: EwwState::from_default_vars(eww_config.generate_initial_state()?.clone()), eww_config, windows: HashMap::new(), css_provider: gtk::CssProvider::new(), + script_var_poll_handles: Vec::new(), + script_var_poll_executor: scheduled_executor::CoreExecutor::new()?, + app_evt_send: evt_send.clone(), }; if let Some(screen) = gdk::Screen::get_default() { @@ -121,9 +128,10 @@ fn initialize_server(opts: Opt) -> Result<()> { // run the command that eww was started with app.handle_user_command(opts)?; - let (evt_send, evt_recv) = glib::MainContext::channel(glib::PRIORITY_DEFAULT); run_server_thread(evt_send.clone()); - run_filewatch_thread(&config_file_path, &scss_file_path, evt_send.clone())?; + let _hotwatch = run_filewatch_thread(&config_file_path, &scss_file_path, evt_send.clone())?; + + app.init_command_poll_tasks()?; evt_recv.attach(None, move |msg| { app.handle_event(msg); @@ -135,7 +143,7 @@ fn initialize_server(opts: Opt) -> Result<()> { Ok(()) } -fn run_server_thread(evt_send: glib::Sender) -> std::thread::JoinHandle<()> { +fn run_server_thread(evt_send: glib::Sender) { std::thread::spawn(move || { let result: Result<_> = try { loop { @@ -149,24 +157,23 @@ fn run_server_thread(evt_send: glib::Sender) -> std::thread::Join eprintln!("error in server thread: {}", err); std::process::exit(1); } - }) + }); } fn run_filewatch_thread>( config_file_path: P, scss_file_path: P, evt_send: glib::Sender, -) -> Result<()> { +) -> Result { let mut hotwatch = hotwatch::Hotwatch::new()?; - hotwatch.watch_file_changes( - config_file_path, - glib::clone!(@strong evt_send => move |path| { - try_logging_errors!("handling change of config file" => { - let new_eww_config = config::EwwConfig::read_from_file(path)?; - evt_send.send(app::EwwEvent::ReloadConfig(new_eww_config))?; - }); - }), - )?; + + let config_file_change_send = evt_send.clone(); + hotwatch.watch_file_changes(config_file_path, move |path| { + try_logging_errors!("handling change of config file" => { + let new_eww_config = config::EwwConfig::read_from_file(path)?; + config_file_change_send.send(app::EwwEvent::ReloadConfig(new_eww_config))?; + }); + })?; let result = hotwatch.watch_file_changes(scss_file_path, move |path| { try_logging_errors!("handling change of scss file" => { @@ -177,20 +184,19 @@ fn run_filewatch_thread>( if let Err(e) = result { eprintln!("WARN: error while loading CSS file for hot-reloading: \n{}", e) }; - Ok(()) + Ok(hotwatch) } #[extend::ext(pub)] impl hotwatch::Hotwatch { - fn watch_file_changes(&mut self, path: P, callback: F) -> Result<()> + fn watch_file_changes(&mut self, file_path: P, callback: F) -> Result<()> where P: AsRef, F: 'static + Fn(PathBuf) + Send, { - let result = self.watch(path, move |evt| match evt { + Ok(self.watch(file_path, move |evt| match evt { hotwatch::Event::Write(path) | hotwatch::Event::NoticeWrite(path) => callback(path), _ => {} - }); - Ok(result?) + })?) } } diff --git a/src/util.rs b/src/util.rs index a3dd88c..f81f079 100644 --- a/src/util.rs +++ b/src/util.rs @@ -22,3 +22,32 @@ impl> T { self.as_ref().lines().map(|line| line.trim()).join("\n") } } + +pub fn parse_duration(s: &str) -> Result { + use std::time::Duration; + if s.ends_with("ms") { + Ok(Duration::from_millis(s.trim_end_matches("ms").parse()?)) + } else if s.ends_with("s") { + Ok(Duration::from_secs(s.trim_end_matches("s").parse()?)) + } else if s.ends_with("m") { + Ok(Duration::from_secs(s.trim_end_matches("m").parse::()? * 60)) + } else if s.ends_with("h") { + Ok(Duration::from_secs(s.trim_end_matches("h").parse::()? * 60 * 60)) + } else { + Err(anyhow!("unrecognized time format: {}", s)) + } +} + +//#[macro_export] +//macro_rules! check_that { +//($( +//$cond:expr => $err:expr +//),*$(,)?) => { +//$( +//if !($cond) { +//return Err($err); +//} +//)* +//} + +//} diff --git a/src/value.rs b/src/value.rs index 55ee737..ef29688 100644 --- a/src/value.rs +++ b/src/value.rs @@ -106,13 +106,6 @@ impl PrimitiveValue { pub enum AttrValue { Concrete(PrimitiveValue), VarRef(String), - CommandPolling(CommandPollingUse), -} - -#[derive(Clone, Debug, PartialEq)] -pub struct CommandPollingUse { - pub command: String, - pub interval: std::time::Duration, } impl AttrValue { diff --git a/src/widgets/widget_definitions.rs b/src/widgets/widget_definitions.rs index b2852e4..c56284c 100644 --- a/src/widgets/widget_definitions.rs +++ b/src/widgets/widget_definitions.rs @@ -24,8 +24,8 @@ pub(super) fn resolve_widget_attrs(bargs: &mut BuilderArgs, gtk_widget: >k::Wi /// attributes that apply to all container widgets pub(super) fn resolve_container_attrs(bargs: &mut BuilderArgs, gtk_widget: >k::Container) { resolve!(bargs, gtk_widget, { - resolve_bool => "vexpand" = true => |v| gtk_widget.set_vexpand(v), - resolve_bool => "hexpand" = true => |v| gtk_widget.set_hexpand(v), + resolve_bool => "vexpand" = false => |v| gtk_widget.set_vexpand(v), + resolve_bool => "hexpand" = false => |v| gtk_widget.set_hexpand(v), }); } @@ -98,9 +98,9 @@ fn build_gtk_image(bargs: &mut BuilderArgs) -> Result { fn build_gtk_layout(bargs: &mut BuilderArgs) -> Result { let gtk_widget = gtk::Box::new(gtk::Orientation::Horizontal, 0); resolve!(bargs, gtk_widget, { - resolve_f64 => "spacing" = 0.0 => |v| gtk_widget.set_spacing(v as i32), - resolve_str => "orientation" => |v| gtk_widget.set_orientation(parse_orientation(&v)), - resolve_bool => "homogenous" = true => |v| gtk_widget.set_homogeneous(v), + resolve_f64 => "spacing" = 0.0 => |v| gtk_widget.set_spacing(v as i32), + resolve_str => "orientation" => |v| gtk_widget.set_orientation(parse_orientation(&v)), + resolve_bool => "space-evenly" = true => |v| gtk_widget.set_homogeneous(v), }); Ok(gtk_widget) }