From e6b693487fb341afc56a562bdad4d2a97b76c917 Mon Sep 17 00:00:00 2001 From: Troels Dalsgaard Hoffmeyer Date: Tue, 30 Jul 2024 23:57:24 +0200 Subject: [PATCH 1/2] Method calls! You can now do dbus method calls in the TUI! When hitting Enter on a method in the tree a popup will show. You can then enter each argument in text fields in this popup the arguments are then parsed into dbus types that are sent with the method call The return value is then put into the output text box. To do this a parser for a human readable format for dbus types was created parsers are created for a given type signature, and the then input is validated against that The parser is written using chumsky with subparsers for each dbus type. --- Cargo.lock | 518 ++++++++++++++++++++-------------- Cargo.toml | 13 +- src/bin/dtui/app.rs | 216 +++++++++++++- src/bin/dtui/dbus_handler.rs | 55 +++- src/bin/dtui/main.rs | 6 +- src/bin/dtui/messages.rs | 14 +- src/bin/dtui/notes.md | 3 - src/bin/dtui/parser.rs | 476 +++++++++++++++++++++++++++++++ src/bin/dtui/stateful_tree.rs | 39 ++- src/bin/dtui/ui.rs | 128 ++++++++- 10 files changed, 1212 insertions(+), 256 deletions(-) delete mode 100644 src/bin/dtui/notes.md create mode 100644 src/bin/dtui/parser.rs diff --git a/Cargo.lock b/Cargo.lock index 91fa626..77ecc58 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,18 +4,18 @@ version = 3 [[package]] name = "addr2line" -version = "0.22.0" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" +checksum = "f5fb1d8e4442bd405fdfd1dacb42792696b0cf9cb15882e5d097b742a676d375" dependencies = [ "gimli", ] [[package]] -name = "adler" -version = "1.0.2" +name = "adler2" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" [[package]] name = "ahash" @@ -46,9 +46,9 @@ checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" [[package]] name = "anstream" -version = "0.6.14" +version = "0.6.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" +checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" dependencies = [ "anstyle", "anstyle-parse", @@ -61,33 +61,33 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.7" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" +checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" [[package]] name = "anstyle-parse" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" +checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391" +checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" dependencies = [ "windows-sys 0.52.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.3" +version = "3.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" +checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" dependencies = [ "anstyle", "windows-sys 0.52.0", @@ -119,9 +119,9 @@ dependencies = [ [[package]] name = "async-io" -version = "2.3.3" +version = "2.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d6baa8f0178795da0e71bc42c9e5d13261aac7ee549853162e66a241ba17964" +checksum = "444b0228950ee6501b3568d3c93bf1176a1fdbc3b758dcd9475046d30f4dc7e8" dependencies = [ "async-lock", "cfg-if", @@ -133,7 +133,7 @@ dependencies = [ "rustix", "slab", "tracing", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -149,9 +149,9 @@ dependencies = [ [[package]] name = "async-process" -version = "2.2.3" +version = "2.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7eda79bbd84e29c2b308d1dc099d7de8dcc7035e48f4bf5dc4a531a44ff5e2a" +checksum = "a8a07789659a4d385b79b18b9127fc27e1a59e1e89117c78c5ea3b806f016374" dependencies = [ "async-channel", "async-io", @@ -164,7 +164,7 @@ dependencies = [ "futures-lite", "rustix", "tracing", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -180,9 +180,9 @@ dependencies = [ [[package]] name = "async-signal" -version = "0.2.8" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "794f185324c2f00e771cd9f1ae8b5ac68be2ca7abb129a87afd6e86d228bc54d" +checksum = "637e00349800c0bdf8bfc21ebbc0b6524abea702b0da4168ac00d070d0c0b9f3" dependencies = [ "async-io", "async-lock", @@ -193,7 +193,7 @@ dependencies = [ "rustix", "signal-hook-registry", "slab", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -204,9 +204,9 @@ checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" [[package]] name = "async-trait" -version = "0.1.80" +version = "0.1.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" +checksum = "a27b8a3a6e1a44fa4c8baf1f653e4172e81486d4941f2237e20dc2d0cf4ddff1" dependencies = [ "proc-macro2", "quote", @@ -227,24 +227,24 @@ checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "backtrace" -version = "0.3.72" +version = "0.3.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17c6a35df3749d2e8bb1b7b21a976d82b15548788d2735b9d82f329268f71a11" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" dependencies = [ "addr2line", - "cc", "cfg-if", "libc", "miniz_oxide", "object", "rustc-demangle", + "windows-targets 0.52.6", ] [[package]] name = "bitflags" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[package]] name = "block-buffer" @@ -268,11 +268,17 @@ dependencies = [ "piper", ] +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + [[package]] name = "bytes" -version = "1.6.0" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" +checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" [[package]] name = "cassowary" @@ -282,18 +288,21 @@ checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53" [[package]] name = "castaway" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a17ed5635fc8536268e5d4de1e22e81ac34419e5f052d4d51f4e01dcc263fcc" +checksum = "0abae9be0aaf9ea96a3b1b8b1b55c602ca751eba1b1500220cea4ecbafe7c0d5" dependencies = [ "rustversion", ] [[package]] name = "cc" -version = "1.0.99" +version = "1.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96c51067fd44124faa7f870b4b1c969379ad32b2ba805aa959430ceaa384f695" +checksum = "b62ac837cdb5cb22e10a256099b4fc502b1dfe560cb282963a974d7abd80e476" +dependencies = [ + "shlex", +] [[package]] name = "cfg-if" @@ -303,15 +312,25 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "cfg_aliases" -version = "0.1.1" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + +[[package]] +name = "chumsky" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eebd66744a15ded14960ab4ccdbfb51ad3b81f51f3f04a80adac98c985396c9" +dependencies = [ + "hashbrown", + "stacker", +] [[package]] name = "clap" -version = "4.5.7" +version = "4.5.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5db83dced34638ad474f39f250d7fea9598bdd239eaced1bdf45d597da0f433f" +checksum = "3e5a21b8495e732f1b3c364c9949b201ca7bae518c502c80256c96ad79eaf6ac" dependencies = [ "clap_builder", "clap_derive", @@ -319,9 +338,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.7" +version = "4.5.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7e204572485eb3fbf28f871612191521df159bc3e15a9f5064c66dba3a8c05f" +checksum = "8cf2dd12af7a047ad9d6da2b6b249759a22a7abc0f474c1dae1777afa4b21a73" dependencies = [ "anstream", "anstyle", @@ -331,9 +350,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.5" +version = "4.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c780290ccf4fb26629baa7a1081e68ced113f1d3ec302fa5948f1c381ebf06c6" +checksum = "501d359d5f3dcaf6ecdeee48833ae73ec6e42723a1e52419c79abf9507eec0a0" dependencies = [ "heck", "proc-macro2", @@ -343,15 +362,15 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70" +checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" [[package]] name = "colorchoice" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" +checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" [[package]] name = "compact_str" @@ -377,9 +396,9 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.12" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" dependencies = [ "libc", ] @@ -399,7 +418,7 @@ dependencies = [ "bitflags", "crossterm_winapi", "libc", - "mio", + "mio 0.8.11", "parking_lot", "signal-hook", "signal-hook-mio", @@ -440,6 +459,7 @@ name = "dtui" version = "2.0.0" dependencies = [ "async-recursion", + "chumsky", "clap", "crossterm", "itertools 0.11.0", @@ -449,16 +469,18 @@ dependencies = [ "tracing-error", "tracing-journald", "tracing-subscriber", + "tui-textarea", "tui-tree-widget", "zbus", + "zbus_names", "zbus_xml", ] [[package]] name = "either" -version = "1.12.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" [[package]] name = "endi" @@ -526,9 +548,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" +checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" [[package]] name = "futures-core" @@ -604,9 +626,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.29.0" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" +checksum = "32085ea23f3234fc7846555e85283ba4de91e21016dc0455a16286d87a292d64" [[package]] name = "hashbrown" @@ -630,6 +652,12 @@ version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" +[[package]] +name = "hermit-abi" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" + [[package]] name = "hex" version = "0.4.3" @@ -638,9 +666,9 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "indexmap" -version = "2.2.6" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" +checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5" dependencies = [ "equivalent", "hashbrown", @@ -648,9 +676,9 @@ dependencies = [ [[package]] name = "is_terminal_polyfill" -version = "1.70.0" +version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" [[package]] name = "itertools" @@ -663,9 +691,9 @@ dependencies = [ [[package]] name = "itertools" -version = "0.12.1" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" dependencies = [ "either", ] @@ -678,15 +706,15 @@ checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.155" +version = "0.2.158" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" [[package]] name = "linux-raw-sys" @@ -706,15 +734,15 @@ dependencies = [ [[package]] name = "log" -version = "0.4.21" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "lru" -version = "0.12.3" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3262e75e648fce39813cb56ac41f3c3e3f65217ebf3844d818d1f9398cfb0dc" +checksum = "37ee39891760e7d94734f6f63fedc29a2e4a152f836120753a72503f09fcf904" dependencies = [ "hashbrown", ] @@ -730,9 +758,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.2" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "memoffset" @@ -743,13 +771,19 @@ dependencies = [ "autocfg", ] +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + [[package]] name = "miniz_oxide" -version = "0.7.3" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87dfd01fe195c66b572b37921ad8803d010623c0aca821bea2302239d155cdae" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" dependencies = [ - "adler", + "adler2", ] [[package]] @@ -764,11 +798,23 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "mio" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" +dependencies = [ + "hermit-abi 0.3.9", + "libc", + "wasi", + "windows-sys 0.52.0", +] + [[package]] name = "nix" -version = "0.28.0" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4" +checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" dependencies = [ "bitflags", "cfg-if", @@ -778,30 +824,30 @@ dependencies = [ ] [[package]] -name = "nu-ansi-term" -version = "0.46.0" +name = "nom" +version = "7.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" dependencies = [ - "overload", - "winapi", + "memchr", + "minimal-lexical", ] [[package]] -name = "num_cpus" -version = "1.16.0" +name = "nu-ansi-term" +version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" dependencies = [ - "hermit-abi", - "libc", + "overload", + "winapi", ] [[package]] name = "object" -version = "0.35.0" +version = "0.36.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8ec7ab813848ba4522158d5517a6093db1ded27575b070f4177b8d12b41db5e" +checksum = "084f1a5821ac4c651660a94a7153d27ac9d8a53736203f58b31945ded098070a" dependencies = [ "memchr", ] @@ -830,9 +876,9 @@ checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" [[package]] name = "parking" -version = "2.2.0" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" [[package]] name = "parking_lot" @@ -854,7 +900,7 @@ dependencies = [ "libc", "redox_syscall", "smallvec", - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -877,9 +923,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "piper" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae1d5c74c9876f070d3e8fd503d748c7d974c3e48da8f41350fa5222ef9b4391" +checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066" dependencies = [ "atomic-waker", "fastrand", @@ -888,48 +934,60 @@ dependencies = [ [[package]] name = "polling" -version = "3.7.1" +version = "3.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e6a007746f34ed64099e88783b0ae369eaa3da6392868ba262e2af9b8fbaea1" +checksum = "cc2790cd301dec6cd3b7a025e4815cf825724a51c98dccfe6a3e55f05ffb6511" dependencies = [ "cfg-if", "concurrent-queue", - "hermit-abi", + "hermit-abi 0.4.0", "pin-project-lite", "rustix", "tracing", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "ppv-lite86" -version = "0.2.17" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] [[package]] name = "proc-macro-crate" -version = "3.1.0" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" +checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b" dependencies = [ "toml_edit", ] [[package]] name = "proc-macro2" -version = "1.0.85" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] +[[package]] +name = "psm" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa37f80ca58604976033fae9515a8a2989fc13797d953f7c04fb8fa36a11f205" +dependencies = [ + "cc", +] + [[package]] name = "quick-xml" -version = "0.30.0" +version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eff6510e86862b57b210fd8cbe8ed3f0d7d600b9c2863cd4549a2e033c66e956" +checksum = "96a05e2e8efddfa51a84ca47cec303fac86c8541b686d37cac5efc0e094417bc" dependencies = [ "memchr", "serde", @@ -937,9 +995,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.36" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ "proc-macro2", ] @@ -976,19 +1034,20 @@ dependencies = [ [[package]] name = "ratatui" -version = "0.26.3" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f44c9e68fd46eda15c646fbb85e1040b657a58cdc8c98db1d97a55930d991eef" +checksum = "d16546c5b5962abf8ce6e2881e722b4e0ae3b6f1a08a26ae3573c55853ca68d3" dependencies = [ "bitflags", "cassowary", "compact_str", "crossterm", - "itertools 0.12.1", + "itertools 0.13.0", "lru", "paste", "stability", "strum", + "strum_macros", "unicode-segmentation", "unicode-truncate", "unicode-width", @@ -996,18 +1055,18 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.1" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e" +checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" dependencies = [ "bitflags", ] [[package]] name = "regex" -version = "1.10.5" +version = "1.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" +checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" dependencies = [ "aho-corasick", "memchr", @@ -1055,9 +1114,9 @@ checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustix" -version = "0.38.34" +version = "0.38.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" +checksum = "3f55e80d50763938498dd5ebb18647174e0c76dc38c5505294bb224624f30f36" dependencies = [ "bitflags", "errno", @@ -1086,18 +1145,18 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "serde" -version = "1.0.203" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.203" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" dependencies = [ "proc-macro2", "quote", @@ -1106,11 +1165,12 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.117" +version = "1.0.128" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" +checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" dependencies = [ "itoa", + "memchr", "ryu", "serde", ] @@ -1146,6 +1206,12 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + [[package]] name = "signal-hook" version = "0.3.17" @@ -1158,12 +1224,12 @@ dependencies = [ [[package]] name = "signal-hook-mio" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29ad2e15f37ec9a6cc544097b78a1ec90001e9f71b81338ca39f430adaca99af" +checksum = "34db1a06d485c9142248b7a054f034b349b212551f3dfd19c94d45a754a217cd" dependencies = [ "libc", - "mio", + "mio 0.8.11", "signal-hook", ] @@ -1203,14 +1269,27 @@ dependencies = [ [[package]] name = "stability" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ff9eaf853dec4c8802325d8b6d3dffa86cc707fd7a1a4cdbf416e13b061787a" +checksum = "d904e7009df136af5297832a3ace3370cd14ff1546a232f4f185036c2736fcac" dependencies = [ "quote", "syn", ] +[[package]] +name = "stacker" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "799c883d55abdb5e98af1a7b3f23b9b6de8ecada0ecac058672d7635eb48ca7b" +dependencies = [ + "cc", + "cfg-if", + "libc", + "psm", + "windows-sys 0.59.0", +] + [[package]] name = "static_assertions" version = "1.1.0" @@ -1225,9 +1304,9 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "strum" -version = "0.26.2" +version = "0.26.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d8cec3501a5194c432b2b7976db6b7d10ec95c253208b45f83f7136aa985e29" +checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" dependencies = [ "strum_macros", ] @@ -1247,9 +1326,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.66" +version = "2.0.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" +checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" dependencies = [ "proc-macro2", "quote", @@ -1258,14 +1337,15 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.10.1" +version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" +checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" dependencies = [ "cfg-if", "fastrand", + "once_cell", "rustix", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -1280,29 +1360,28 @@ dependencies = [ [[package]] name = "tokio" -version = "1.38.0" +version = "1.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a" +checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" dependencies = [ "backtrace", "bytes", "libc", - "mio", - "num_cpus", + "mio 1.0.2", "parking_lot", "pin-project-lite", "signal-hook-registry", "socket2", "tokio-macros", "tracing", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "tokio-macros" -version = "2.3.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" +checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", @@ -1311,15 +1390,15 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.6" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" [[package]] name = "toml_edit" -version = "0.21.1" +version = "0.22.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" +checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d" dependencies = [ "indexmap", "toml_datetime", @@ -1421,11 +1500,22 @@ dependencies = [ "tracing-serde", ] +[[package]] +name = "tui-textarea" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00524c1366ee838839dd327d1f339ff51846ad4ea85bfa1332859e79adec612c" +dependencies = [ + "crossterm", + "ratatui", + "unicode-width", +] + [[package]] name = "tui-tree-widget" -version = "0.19.0" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb0c6f924587e719c50b8f83485afbe4d4c16edca6b641d5d9a3204edeba5cf0" +checksum = "0ac69db35529be6a75f9d27516ff33df299e2e8e961a1986d52185cef0427352" dependencies = [ "ratatui", "unicode-width", @@ -1462,11 +1552,12 @@ checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" [[package]] name = "unicode-truncate" -version = "1.0.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5fbabedabe362c618c714dbefda9927b5afc8e2a8102f47f081089a9019226" +checksum = "b3644627a5af5fa321c95b9b235a72fd24cd29c648c2c379431e6628655627bf" dependencies = [ - "itertools 0.12.1", + "itertools 0.13.0", + "unicode-segmentation", "unicode-width", ] @@ -1490,9 +1581,9 @@ checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" [[package]] name = "version_check" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "wasi" @@ -1537,7 +1628,16 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.5", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", ] [[package]] @@ -1557,18 +1657,18 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.5", - "windows_aarch64_msvc 0.52.5", - "windows_i686_gnu 0.52.5", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", "windows_i686_gnullvm", - "windows_i686_msvc 0.52.5", - "windows_x86_64_gnu 0.52.5", - "windows_x86_64_gnullvm 0.52.5", - "windows_x86_64_msvc 0.52.5", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", ] [[package]] @@ -1579,9 +1679,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" @@ -1591,9 +1691,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" @@ -1603,15 +1703,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" @@ -1621,9 +1721,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" @@ -1633,9 +1733,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" @@ -1645,9 +1745,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" @@ -1657,34 +1757,33 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" -version = "0.5.40" +version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" +checksum = "68a9bda4691f099d435ad181000724da8e5899daa10713c2d432552b9ccd3a6f" dependencies = [ "memchr", ] [[package]] name = "xdg-home" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca91dcf8f93db085f3a0a29358cd0b9d670915468f4290e8b85d118a34211ab8" +checksum = "ec1cdab258fb55c0da61328dc52c8764709b249011b2cad0454c72f0bf10a1f6" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "zbus" -version = "4.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "989c3977a7aafa97b12b9a35d21cdcff9b0d2289762b14683f45d66b1ba6c48f" +version = "4.4.0" +source = "git+https://github.com/dbus2/zbus.git?branch=main#60d0443ce1771559812af1f0945f0de1028a2f42" dependencies = [ "async-broadcast", "async-process", @@ -1706,7 +1805,7 @@ dependencies = [ "tokio", "tracing", "uds_windows", - "windows-sys 0.52.0", + "windows-sys 0.59.0", "xdg-home", "zbus_macros", "zbus_names", @@ -1715,9 +1814,8 @@ dependencies = [ [[package]] name = "zbus_macros" -version = "4.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fe9de53245dcf426b7be226a4217dd5e339080e5d46e64a02d6e5dcbf90fca1" +version = "4.4.0" +source = "git+https://github.com/dbus2/zbus.git?branch=main#60d0443ce1771559812af1f0945f0de1028a2f42" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -1729,8 +1827,7 @@ dependencies = [ [[package]] name = "zbus_names" version = "3.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b9b1fef7d021261cc16cba64c351d291b715febe0fa10dc3a443ac5a5022e6c" +source = "git+https://github.com/dbus2/zbus.git?branch=main#60d0443ce1771559812af1f0945f0de1028a2f42" dependencies = [ "serde", "static_assertions", @@ -1740,8 +1837,7 @@ dependencies = [ [[package]] name = "zbus_xml" version = "4.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab3f374552b954f6abb4bd6ce979e6c9b38fb9d0cd7cc68a7d796e70c9f3a233" +source = "git+https://github.com/dbus2/zbus.git?branch=main#60d0443ce1771559812af1f0945f0de1028a2f42" dependencies = [ "quick-xml", "serde", @@ -1752,18 +1848,19 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.7.34" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae87e3fcd617500e5d106f0380cf7b77f3c6092aae37191433159dda23cfb087" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ + "byteorder", "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.34" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", @@ -1772,22 +1869,21 @@ dependencies = [ [[package]] name = "zvariant" -version = "4.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aa6d31a02fbfb602bfde791de7fedeb9c2c18115b3d00f3a36e489f46ffbbc7" +version = "4.2.0" +source = "git+https://github.com/dbus2/zbus.git?branch=main#60d0443ce1771559812af1f0945f0de1028a2f42" dependencies = [ "endi", "enumflags2", "serde", "static_assertions", "zvariant_derive", + "zvariant_utils", ] [[package]] name = "zvariant_derive" -version = "4.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "642bf1b6b6d527988b3e8193d20969d53700a36eac734d21ae6639db168701c8" +version = "4.2.0" +source = "git+https://github.com/dbus2/zbus.git?branch=main#60d0443ce1771559812af1f0945f0de1028a2f42" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -1798,11 +1894,13 @@ dependencies = [ [[package]] name = "zvariant_utils" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc242db087efc22bd9ade7aa7809e4ba828132edc312871584a6b4391bdf8786" +version = "2.2.0" +source = "git+https://github.com/dbus2/zbus.git?branch=main#60d0443ce1771559812af1f0945f0de1028a2f42" dependencies = [ + "nom", "proc-macro2", "quote", + "serde", + "static_assertions", "syn", ] diff --git a/Cargo.toml b/Cargo.toml index 38ef063..54b93db 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,7 @@ authors = ["Troels Hoffmeyer "] description = "dBus TUI for introspecting your current dbus session/system" license = "MIT" repository = "https://github.com/Troels51/dtui" -rust-version = "1.56" +rust-version = "1.75" keywords = ["tui", "dbus"] categories = ["command-line-utilities"] exclude = [ @@ -16,16 +16,19 @@ exclude = [ ] [dependencies] -tui-tree-widget = "0.19" -zbus = { version = "4.2", default-features = false, features = ["tokio"] } +tui-tree-widget = "0.21" +zbus = { git = "https://github.com/dbus2/zbus.git", branch = "main", default-features = false, features = ["tokio"] } crossterm = "0.27" tokio = { version = "1.32", features = ["full"] } async-recursion = "1.1.1" itertools = "0.11.0" clap = { version = "4.4.1", features = ["derive"] } -ratatui = { version = "0.26.2", features = ["macros"] } -zbus_xml = "4.0.0" +ratatui = { version = "0.27", features = ["macros"] } +zbus_xml = { git = "https://github.com/dbus2/zbus.git", branch = "main", default-features = false } tracing-error = "0.2.0" tracing = "0.1.40" tracing-subscriber = { version = "0.3.18", features = ["env-filter", "json", "fmt"] } tracing-journald = "0.3.0" +tui-textarea = "0.5.1" +zbus_names = { git = "https://github.com/dbus2/zbus.git", branch = "main", default-features = false } +chumsky = "0.9.3" diff --git a/src/bin/dtui/app.rs b/src/bin/dtui/app.rs index 2e13518..a26280e 100644 --- a/src/bin/dtui/app.rs +++ b/src/bin/dtui/app.rs @@ -1,22 +1,72 @@ use std::time::{Duration, Instant}; +use chumsky::Parser; use crossterm::event::{self, Event, KeyCode}; +use itertools::Itertools; use ratatui::{backend::Backend, Terminal}; use tokio::sync::mpsc::Receiver; use tracing::Level; -use zbus::names::OwnedBusName; +use tui_textarea::CursorMove; +use zbus::{ + names::{OwnedBusName, OwnedInterfaceName, OwnedMemberName}, + zvariant::OwnedObjectPath, +}; use crate::{ - dbus_handler::DbusActorHandle, messages::AppMessage, stateful_list::StatefulList, - stateful_tree::StatefulTree, ui::ui, + dbus_handler::DbusActorHandle, + messages::AppMessage, + stateful_list::StatefulList, + stateful_tree::{MethodDescription, StatefulTree}, + ui::ui, }; +pub struct MethodArgVisual { + pub text_area: tui_textarea::TextArea<'static>, + pub parser: + Box, Error = chumsky::error::Simple>>, + pub is_input: bool, // Is this Arg an input or output +} +pub struct MethodCallPopUp { + pub service: OwnedBusName, + pub object: OwnedObjectPath, + pub interface: OwnedInterfaceName, + pub method_description: MethodDescription, + pub method_arg_vis: Vec, + pub selected: usize, + pub called: bool, +} +impl MethodCallPopUp { + fn new( + service: OwnedBusName, + object: OwnedObjectPath, + interface: OwnedInterfaceName, + method_description: MethodDescription, + ) -> Self { + Self { + service, + object, + interface, + method_description, + method_arg_vis: Vec::new(), // This gets filled on UI. Maybe there is a better way of doing this + selected: 0, + called: false, + } + } +} + +impl PartialEq for MethodCallPopUp { + fn eq(&self, other: &Self) -> bool { + self.method_description == other.method_description + } +} + #[derive(PartialEq)] pub enum WorkingArea { Services, Objects, + MethodCallPopUp(MethodCallPopUp), } - +// TODO: maybe we should use Components instead, Objects/Services/PopUp would be a componenet, and they would have their own input/render functions pub struct App { dbus_rx: Receiver, dbus_handle: DbusActorHandle, @@ -58,6 +108,26 @@ pub async fn run_app( AppMessage::Services(names) => { app.services = StatefulList::with_items(names); } + AppMessage::MethodCallResponse(_method, message) => { + if let WorkingArea::MethodCallPopUp(ref mut popup) = app.working_area { + popup.called = true; + if let Ok(value) = message.body().deserialize::() + { + for (index, output_field) in popup + .method_arg_vis + .iter_mut() + .filter(|field| !field.is_input) + .enumerate() + { + output_field.text_area.move_cursor(CursorMove::Head); + output_field.text_area.delete_line_by_end(); // The way to clear a text area + output_field + .text_area + .insert_str(format!("{}", value.fields()[index])); + } + } + } + } }, _error => (), }; @@ -67,39 +137,117 @@ pub async fn run_app( if crossterm::event::poll(timeout)? { if let Event::Key(key) = event::read()? { match key.code { - KeyCode::Char('q') => return Ok(()), - KeyCode::Enter => match app.working_area { - WorkingArea::Services => { - if let Some(selected_index) = app.services.state.selected() { - let item = app.services.items[selected_index].clone(); - app.dbus_handle.request_objects_from(item).await; + KeyCode::Char('q') => match app.working_area { + WorkingArea::Services => return Ok(()), + WorkingArea::Objects => return Ok(()), + WorkingArea::MethodCallPopUp(_) => (), + }, + KeyCode::Enter => { + match app.working_area { + WorkingArea::Services => { + if let Some(selected_index) = app.services.state.selected() { + let item = app.services.items[selected_index].clone(); + app.dbus_handle.request_objects_from(item).await; + } + } + WorkingArea::Objects => { + if let Some(full_description) = + extract_description(app.objects.state.selected()) + { + app.working_area = + WorkingArea::MethodCallPopUp(MethodCallPopUp::new( + app.services.items + [app.services.state.selected().unwrap()] + .clone(), + full_description.0, + full_description.1, + full_description.2, + )); + } + } + WorkingArea::MethodCallPopUp(ref popup) => + // Call method + { + let parses = popup + .method_arg_vis + .iter() + .filter(|input| input.is_input) + .map(|input| { + input.parser.parse(input.text_area.lines()[0].clone()) + }); + if parses.clone().all( + |result: Result< + zbus::zvariant::Value<'static>, + Vec>, + >| Result::is_ok(&result), + ) { + let values: Vec = parses + .map(|value| { + // We know that they are all Ok, so unwrap is fine here + zbus::zvariant::OwnedValue::try_from(value.unwrap()) + .unwrap() + }) + .collect(); + app.dbus_handle + .call_method( + popup.service.clone(), + popup.object.clone(), + popup.interface.clone(), + OwnedMemberName::from( + popup.method_description.0.name(), + ), + values, + ) + .await; + } else { + // Alert user that call cannot be made if arguments cannot be parsed + } } } - WorkingArea::Objects => { - //TOTO - } - }, + } KeyCode::Left => match app.working_area { WorkingArea::Services => app.services.unselect(), WorkingArea::Objects => app.objects.left(), + WorkingArea::MethodCallPopUp(ref mut popup) => { + popup.method_arg_vis[0].text_area.input(key); + } }, KeyCode::Down => match app.working_area { WorkingArea::Services => app.services.next(), WorkingArea::Objects => app.objects.down(), + WorkingArea::MethodCallPopUp(ref mut popup) => { + popup.selected = + std::cmp::min(popup.selected + 1, popup.method_arg_vis.len()); + } }, KeyCode::Up => match app.working_area { WorkingArea::Services => app.services.previous(), WorkingArea::Objects => app.objects.up(), + WorkingArea::MethodCallPopUp(ref mut popup) => { + popup.selected = popup.selected.saturating_sub(1); + } }, KeyCode::Right => match app.working_area { WorkingArea::Services => {} WorkingArea::Objects => app.objects.right(), + WorkingArea::MethodCallPopUp(ref mut popup) => { + popup.method_arg_vis[0].text_area.input(key); + } }, KeyCode::Tab => match app.working_area { WorkingArea::Services => app.working_area = WorkingArea::Objects, WorkingArea::Objects => app.working_area = WorkingArea::Services, + WorkingArea::MethodCallPopUp(ref _method) => {} + }, + KeyCode::Esc => { + app.working_area = WorkingArea::Objects; + } + _ => match app.working_area { + WorkingArea::MethodCallPopUp(ref mut popup) => { + popup.method_arg_vis[popup.selected].text_area.input(key); + } + _ => (), }, - _ => (), } tracing::event!( Level::DEBUG, @@ -114,3 +262,41 @@ pub async fn run_app( } } } + +/// Takes a stateful_tree::DbusIdentifier, which is an identifier for where a node is in the UI tree +/// and if the selection is a method, it will extract the path, interface name and method description +/// Otherwise it returns None +fn extract_description( + selected: &[crate::stateful_tree::DbusIdentifier], +) -> Option<(OwnedObjectPath, OwnedInterfaceName, MethodDescription)> { + let object_path = selected + .iter() + .filter_map(|identifier| match identifier { + crate::stateful_tree::DbusIdentifier::Object(o) => Some(o), + _ => None, + }) + .next(); + let interface_name = selected + .iter() + .filter_map(|identifier| match identifier { + crate::stateful_tree::DbusIdentifier::Interface(i) => Some(i), + _ => None, + }) + .next(); + let member_name = selected + .iter() + .filter_map(|identifier| match identifier { + crate::stateful_tree::DbusIdentifier::Method(m) => Some(m), + _ => None, + }) + .next(); + if object_path.is_some() && interface_name.is_some() && member_name.is_some() { + Some(( + OwnedObjectPath::try_from(object_path.unwrap().clone()).unwrap(), + OwnedInterfaceName::try_from(interface_name.unwrap().clone()).unwrap(), + member_name.unwrap().clone(), + )) + } else { + None + } +} diff --git a/src/bin/dtui/dbus_handler.rs b/src/bin/dtui/dbus_handler.rs index e6aae99..684770a 100644 --- a/src/bin/dtui/dbus_handler.rs +++ b/src/bin/dtui/dbus_handler.rs @@ -2,7 +2,11 @@ use std::{collections::HashMap, error::Error, io::BufReader}; use async_recursion::async_recursion; use tokio::sync::mpsc::{self, Receiver, Sender}; -use zbus::{names::OwnedBusName, zvariant::ObjectPath, Connection}; +use zbus::{ + names::{OwnedBusName, OwnedInterfaceName, OwnedMemberName}, + zvariant::{ObjectPath, OwnedValue, StructureBuilder}, + Connection, +}; use zbus_xml::Node; use crate::messages::{AppMessage, DbusMessage}; @@ -85,6 +89,43 @@ impl DbusActor { let _ = self.app_sender.send(AppMessage::Services(names)).await; } } + DbusMessage::MethodCallRequest(service, object_path, interface, method, values) => { + let mut body = StructureBuilder::new(); + let is_empty = values.is_empty(); + for v in values { + body.push_value(v.into()); + } + let method_call_response = if !is_empty { + self.connection + .call_method( + Some(service), + object_path, + Some(interface), + method.clone(), + &body.build().unwrap(), + ) + .await + } else { + self.connection + .call_method( + Some(service), + object_path, + Some(interface), + method.clone(), + &(), + ) + .await + }; + match method_call_response { + Ok(message) => { + let _ = self + .app_sender + .send(AppMessage::MethodCallResponse(method, message)) + .await; + } + Err(e) => tracing::debug!("Method call error {}", e), + }; + } } } } @@ -118,4 +159,16 @@ impl DbusActorHandle { let msg = DbusMessage::ServiceRequest(); let _ = self.sender.send(msg).await; } + + pub async fn call_method( + &self, + service: OwnedBusName, + object: zbus::zvariant::OwnedObjectPath, + interface: OwnedInterfaceName, + method: OwnedMemberName, + values: Vec, + ) { + let msg = DbusMessage::MethodCallRequest(service, object, interface, method, values); + let _ = self.sender.send(msg).await; + } } diff --git a/src/bin/dtui/main.rs b/src/bin/dtui/main.rs index c3ff9e2..926f4a9 100644 --- a/src/bin/dtui/main.rs +++ b/src/bin/dtui/main.rs @@ -1,10 +1,10 @@ pub mod app; pub mod dbus_handler; pub mod messages; +pub mod parser; pub mod stateful_list; pub mod stateful_tree; pub mod ui; - use app::{run_app, App}; use clap::{command, ArgGroup, Parser, ValueEnum}; use crossterm::{ @@ -22,9 +22,9 @@ use ratatui::{ }; use std::{error::Error, io, time::Duration}; use tokio::sync::mpsc::{self}; -use tracing::{level_filters::LevelFilter}; +use tracing::level_filters::LevelFilter; +use tracing_subscriber::layer::SubscriberExt; use tracing_subscriber::prelude::*; -use tracing_subscriber::{layer::SubscriberExt}; use zbus::{Connection, ConnectionBuilder}; diff --git a/src/bin/dtui/messages.rs b/src/bin/dtui/messages.rs index a72daa8..7c9ac38 100644 --- a/src/bin/dtui/messages.rs +++ b/src/bin/dtui/messages.rs @@ -1,13 +1,25 @@ use std::collections::HashMap; -use zbus::names::OwnedBusName; +use zbus::{ + names::{OwnedBusName, OwnedInterfaceName, OwnedMemberName}, + zvariant::{OwnedObjectPath, OwnedValue}, + Message, +}; use zbus_xml::Node; pub enum DbusMessage { GetObjects(OwnedBusName), ServiceRequest(), + MethodCallRequest( + OwnedBusName, + OwnedObjectPath, + OwnedInterfaceName, + OwnedMemberName, + Vec, + ), } pub enum AppMessage { Objects((OwnedBusName, HashMap>)), // Service name + Map of (Object names, node) Services(Vec), + MethodCallResponse(OwnedMemberName, Message), } diff --git a/src/bin/dtui/notes.md b/src/bin/dtui/notes.md deleted file mode 100644 index bc45458..0000000 --- a/src/bin/dtui/notes.md +++ /dev/null @@ -1,3 +0,0 @@ -# TODO - - Visualize properties better - - Call methods, visualize their types \ No newline at end of file diff --git a/src/bin/dtui/parser.rs b/src/bin/dtui/parser.rs new file mode 100644 index 0000000..088a1b4 --- /dev/null +++ b/src/bin/dtui/parser.rs @@ -0,0 +1,476 @@ +use chumsky::prelude::*; +use std::{collections::HashMap, u32}; +use zbus::zvariant::{self, parsed, ObjectPath, Signature, StructureBuilder}; + +/// Create a parser from a parsed::Signature. +/// The language that this parses is a human readable version of the dbus format. +/// Arrays are delimited by [], with values seperated by "," +/// Structure are delimited by (), with values seperated by "," +/// Dictionaries are delimited by {}, and with keys and values seperated by ":" and pairs seperated by "," +/// +/// # Examples +/// ["first", "second"] is a array with 2 string elements with a signature of "as" +/// {"first": 1, "second": 2} is a dictionary with string as key type and key type of some number, it's signature is "a{su}" +/// +/// ``` +/// let signature = parsed::Signature::from_str("as").unwrap(); +/// let result = get_parser(signature).parse("[\"first\", \"second\"]"); +/// assert_eq!(result, Ok(zvariant::Value::Array(vec!["first", "second"].into()))); +/// ``` +pub fn get_parser( + signature: parsed::Signature, +) -> impl Parser, Error = Simple> { + match signature { + zvariant::parsed::Signature::Unit => todo!(), + zvariant::parsed::Signature::U8 => parser_u8().boxed(), + zvariant::parsed::Signature::Bool => parser_bool().boxed(), + zvariant::parsed::Signature::I16 => parser_i16().boxed(), + zvariant::parsed::Signature::U16 => parser_u16().boxed(), + zvariant::parsed::Signature::I32 => parser_i32().boxed(), + zvariant::parsed::Signature::U32 => parser_u32().boxed(), + zvariant::parsed::Signature::I64 => parser_i64().boxed(), + zvariant::parsed::Signature::U64 => parser_u64().boxed(), + zvariant::parsed::Signature::F64 => parser_f64().boxed(), + zvariant::parsed::Signature::Str => parser_string().boxed(), + zvariant::parsed::Signature::Signature => parser_signature().boxed(), + zvariant::parsed::Signature::ObjectPath => parser_object_path().boxed(), + zvariant::parsed::Signature::Variant => parser_variant().boxed(), + zvariant::parsed::Signature::Fd => parser_fd().boxed(), + zvariant::parsed::Signature::Array(array) => { + parser_array(array.signature().clone()).boxed() + } + zvariant::parsed::Signature::Dict { key, value } => { + parser_dict(key.signature().clone(), value.signature().clone()).boxed() + } + zvariant::parsed::Signature::Structure(structure) => parser_struct(structure).boxed(), + } +} + +fn parser_variant<'a>() -> impl Parser, Error = Simple> { + parser_signature() + .boxed() + .then_ignore(just("->")) + .then_with(|s| match s { + zvariant::Value::Signature(signature) => get_parser(signature.into()) + .map(|variant| zvariant::Value::Value(Box::new(variant))), + _ => unreachable!(), + }) +} +// +fn parser_struct<'a>( + structure: parsed::FieldsSignatures, +) -> impl Parser, Error = Simple> { + let mut element_parsers = structure + .iter() + .map(|signature: &zbus::zvariant::parsed::Signature| get_parser(signature.clone())); + let mut full_parser = just('(').map(|_| Vec::>::new()).boxed(); // The map is there to get types to match as the chain in the loop needs the parser to output a Vec + full_parser = full_parser.chain(element_parsers.next().unwrap()).boxed(); // The first doesnt get a ',' the rest do + for element_parser in element_parsers { + full_parser = full_parser + .then_ignore(just(",").padded()) + .chain(element_parser) + .boxed(); + } + full_parser.map(|fields| { + let mut builder = StructureBuilder::new(); + for field in fields { + builder.push_value(field); + } + zvariant::Value::Structure(builder.build().unwrap()) + }) +} +fn parser_dict<'a>( + key_type: parsed::Signature, + value_type: parsed::Signature, +) -> impl Parser, Error = Simple> { + let key_parser = get_parser(key_type.clone()); + let value_parser = get_parser(value_type.clone()); + let member_parser = key_parser + .then_ignore(just(":").padded()) + .then(value_parser) + .boxed(); + member_parser + .clone() + .chain(just(',').ignore_then(member_parser).repeated()) + .or_not() + .flatten() + .delimited_by(just('{'), just('}')) + .collect::, zvariant::Value<'_>>>() + .map( + move |m: HashMap, zvariant::Value<'_>>| { + let mut dict = + zvariant::Dict::new(key_type.clone().into(), value_type.clone().into()); + for (k, v) in m { + dict.append(k, v).expect("Could not append to key value pair, this should not happen if types are correct"); + } + zvariant::Value::Dict(dict) + }, + ) +} + +fn parser_array<'a>( + signature: parsed::Signature, +) -> impl Parser, Error = Simple> { + let element_parser = get_parser(signature.clone()).boxed(); + element_parser + .clone() + .chain(just(',').ignore_then(element_parser.clone()).repeated()) + .or_not() + .flatten() + .delimited_by(just('['), just(']')) + .map(move |v: Vec>| { + let mut array: zvariant::Array<'_> = zvariant::Array::new(signature.clone().into()); + for element in v { + array + .append(element) + .expect("The type was somehow incorrect in an inner array"); + } + zvariant::Value::Array(array) + }) +} +// TODO: Can these be made generic, not sure how as they are generic over the Value type which is enums +// TODO: Validation on sizes of numbers +fn parser_u8() -> impl Parser, Error = Simple> { + text::digits(10) + .labelled("u8") + .map(|s: String| zvariant::Value::U8(s.parse().unwrap())) + .padded() +} +fn parser_u16() -> impl Parser, Error = Simple> { + text::digits(10) + .labelled("u16") + .map(|s: String| zvariant::Value::U16(s.parse().unwrap())) + .padded() +} +fn parser_i16() -> impl Parser, Error = Simple> { + just('-') + .or_not() + .chain::(text::digits(10)) + .collect::() + .map(|s: String| zvariant::Value::I16(s.parse().unwrap())) + .labelled("i16") + .padded() +} +fn parser_u32() -> impl Parser, Error = Simple> { + text::digits(10) + .labelled("u32") + .map(|s: String| zvariant::Value::U32(s.parse().unwrap())) + .padded() +} +fn parser_i32() -> impl Parser, Error = Simple> { + just('-') + .or_not() + .chain::(text::digits(10)) + .collect::() + .map(|s: String| zvariant::Value::I32(s.parse().unwrap())) + .padded() +} +fn parser_u64() -> impl Parser, Error = Simple> { + text::digits(10) + .labelled("u64") + .map(|s: String| zvariant::Value::U64(s.parse().unwrap())) + .padded() +} +fn parser_i64() -> impl Parser, Error = Simple> { + just('-') + .or_not() + .chain::(text::digits(10)) + .collect::() + .labelled("i64") + .map(|s: String| zvariant::Value::I64(s.parse().unwrap())) + .padded() +} +fn parser_f64() -> impl Parser, Error = Simple> { + just('-') + .or_not() + .chain::(text::digits(10)) + .chain::(just('.').chain(text::digits(10)).or_not().flatten()) + .collect::() + .labelled("f64") + .map(|s: String| zvariant::Value::F64(s.parse().unwrap())) + .padded() +} +fn parser_bool() -> impl Parser, Error = Simple> { + just("true") + .map(|_| zvariant::Value::Bool(true)) + .or(just("false").map(|_| zvariant::Value::Bool(false))) + .labelled("bool") + .padded() +} +fn parser_string() -> impl Parser, Error = Simple> { + let escape = just('\\').ignore_then( + just('\\') + .or(just('/')) + .or(just('"')) + .or(just('b').to('\x08')) + .or(just('f').to('\x0C')) + .or(just('n').to('\n')) + .or(just('r').to('\r')) + .or(just('t').to('\t')) + .or(just('u').ignore_then( + filter(|c: &char| c.is_ascii_hexdigit()) + .repeated() + .exactly(4) + .collect::() + .validate(|digits, span, emit| { + char::from_u32(u32::from_str_radix(&digits, 16).unwrap()).unwrap_or_else( + || { + emit(Simple::custom(span, "invalid unicode character")); + '\u{FFFD}' // unicode replacement character + }, + ) + }), + )), + ); + let string = just('"') + .ignore_then(filter(|c| *c != '\\' && *c != '"').or(escape).repeated()) + .then_ignore(just('"')) + .collect::() + .map(|s| zvariant::Value::Str(s.into())) + .labelled("string"); + string + .recover_with(skip_then_retry_until(['}', ']'])) + .padded() +} +fn parser_signature() -> impl Parser, Error = Simple> { + let escape = just('\\').ignore_then( + just('\\') + .or(just('/')) + .or(just('"')) + .or(just('b').to('\x08')) + .or(just('f').to('\x0C')) + .or(just('n').to('\n')) + .or(just('r').to('\r')) + .or(just('t').to('\t')) + .or(just('u').ignore_then( + filter(|c: &char| c.is_ascii_hexdigit()) + .repeated() + .exactly(4) + .collect::() + .validate(|digits, span, emit| { + char::from_u32(u32::from_str_radix(&digits, 16).unwrap()).unwrap_or_else( + || { + emit(Simple::custom(span, "invalid unicode character")); + '\u{FFFD}' // unicode replacement character + }, + ) + }), + )), + ); + let string = just('"') + .ignore_then(filter(|c| *c != '\\' && *c != '"').or(escape).repeated()) + .then_ignore(just('"')) + .collect::() + .try_map(|digits, span| { + if let Ok(signature) = Signature::try_from(digits) { + Ok(zvariant::Value::Signature(signature)) + } else { + Err(Simple::custom( + span, + "Could not parse signature from string value", + )) + } + }) + .labelled("signature"); + + string + .recover_with(skip_then_retry_until(['}', ']'])) + .padded() +} +fn parser_object_path() -> impl Parser, Error = Simple> { + let escape = just('\\').ignore_then( + just('\\') + .or(just('/')) + .or(just('"')) + .or(just('b').to('\x08')) + .or(just('f').to('\x0C')) + .or(just('n').to('\n')) + .or(just('r').to('\r')) + .or(just('t').to('\t')) + .or(just('u').ignore_then( + filter(|c: &char| c.is_ascii_hexdigit()) + .repeated() + .exactly(4) + .collect::() + .validate(|digits, span, emit| { + char::from_u32(u32::from_str_radix(&digits, 16).unwrap()).unwrap_or_else( + || { + emit(Simple::custom(span, "invalid unicode character")); + '\u{FFFD}' // unicode replacement character + }, + ) + }), + )), + ); + let string = just('"') + .ignore_then(filter(|c| *c != '\\' && *c != '"').or(escape).repeated()) + .then_ignore(just('"')) + .collect::() + .try_map(|digits, span| { + if let Ok(path) = ObjectPath::try_from(digits) { + Ok(zvariant::Value::ObjectPath(path)) + } else { + Err(Simple::custom( + span, + "Could not parse object path from string value", + )) + } + }) + .labelled("object_path"); + + string + .recover_with(skip_then_retry_until(['}', ']'])) + .padded() +} + +fn parser_fd() -> impl Parser, Error = Simple> { + empty().try_map(|(), span| Err(Simple::custom(span, "Cannot parse file descriptors"))) +} + +#[cfg(test)] +fn test_generic_signature(src: &'static str, signature: &'static str, value: zvariant::Value) { + use std::str::FromStr; + + let signature = parsed::Signature::from_str(signature).unwrap(); + println!("{}", signature); + let result = get_parser(signature).parse(src.trim()); + assert_eq!(result, Ok(value)); +} +#[test] +fn test_numbers() { + test_generic_signature("5", "y", zvariant::Value::U8(5)); + test_generic_signature("5", "n", zvariant::Value::I16(5)); + test_generic_signature("-5", "n", zvariant::Value::I16(-5)); + test_generic_signature("5", "q", zvariant::Value::U16(5)); + test_generic_signature("5", "i", zvariant::Value::I32(5)); + test_generic_signature("-5", "i", zvariant::Value::I32(-5)); + test_generic_signature("5", "u", zvariant::Value::U32(5)); + test_generic_signature("5", "x", zvariant::Value::I64(5)); + test_generic_signature("-5", "x", zvariant::Value::I64(-5)); + test_generic_signature("5", "t", zvariant::Value::U64(5)); +} +#[test] +fn test_float() { + test_generic_signature("5.0", "d", zvariant::Value::F64(5.0)); +} + +#[test] +fn test_string() { + test_generic_signature(r#""asd""#, "s", zvariant::Value::Str("asd".into())); +} + +#[test] +fn test_signature() { + test_generic_signature( + r#""s""#, + "g", + zvariant::Value::Signature(Signature::try_from("s").unwrap()), + ); + test_generic_signature( + r#""(ss)""#, + "g", + zvariant::Value::Signature(Signature::try_from("(ss)").unwrap()), + ); + test_generic_signature( + r#""as""#, + "g", + zvariant::Value::Signature(Signature::try_from("as").unwrap()), + ); + use std::str::FromStr; + let signature = parsed::Signature::from_str("g").unwrap(); + let result = get_parser(signature).parse("k"); // k is not a valid signature + assert!(result.is_err()); +} + +#[test] +fn test_object_path() { + test_generic_signature( + r#""/""#, + "o", + zvariant::Value::ObjectPath(ObjectPath::try_from("/").unwrap()), + ); + test_generic_signature( + r#""/test""#, + "o", + zvariant::Value::ObjectPath(ObjectPath::try_from("/test").unwrap()), + ); + test_generic_signature( + r#""/test/test2""#, + "o", + zvariant::Value::ObjectPath(ObjectPath::try_from("/test/test2").unwrap()), + ); + use std::str::FromStr; + + let signature = parsed::Signature::from_str("o").unwrap(); + let result = get_parser(signature).parse("k"); // k is not a valid object path + assert!(result.is_err()); + let signature = parsed::Signature::from_str("o").unwrap(); + let result = get_parser(signature).parse("//"); // // is not a valid object path + assert!(result.is_err()); +} + +#[test] +fn test_bool() { + test_generic_signature("true", "b", zvariant::Value::Bool(true)); + test_generic_signature("false", "b", zvariant::Value::Bool(false)); +} + +#[test] +fn test_array() { + test_generic_signature( + "[1,2,3,4]", + "ai", + zvariant::Value::Array(vec![1, 2, 3, 4].into()), + ); + // One element + test_generic_signature("[1]", "ai", zvariant::Value::Array(vec![1].into())); + // array of array + let expected_signature = Signature::from_static_str("ai").unwrap(); + let mut expected = zvariant::Array::new(expected_signature); + expected + .append(zvariant::Value::Array(vec![1].into())) + .unwrap(); + expected + .append(zvariant::Value::Array(vec![2].into())) + .unwrap(); + expected + .append(zvariant::Value::Array(vec![3].into())) + .unwrap(); + expected + .append(zvariant::Value::Array(vec![4].into())) + .unwrap(); + test_generic_signature("[[1],[2],[3],[4]]", "aai", zvariant::Value::Array(expected)); + // array of strings + test_generic_signature( + r#"["a","b","c","d"]"#, + "as", + zvariant::Value::Array(vec!["a", "b", "c", "d"].into()), + ); +} + +#[test] +fn test_dict() { + test_generic_signature( + r#"{"a": "b", "c":"d"}"#, + "a{ss}", + zvariant::Value::Dict(HashMap::from([("a", "b"), ("c", "d")]).into()), + ) +} + +#[test] +fn test_struct() { + test_generic_signature( + r#"("5", 1)"#, + "(si)", + zvariant::Value::Structure(zvariant::Structure::from(("5", 1))), + ); +} + +#[test] +fn test_variant() { + test_generic_signature( + r#""u"->5"#, + "v", + zvariant::Value::Value(Box::new(zvariant::Value::U32(5))), + ); +} diff --git a/src/bin/dtui/stateful_tree.rs b/src/bin/dtui/stateful_tree.rs index 3860538..8970681 100644 --- a/src/bin/dtui/stateful_tree.rs +++ b/src/bin/dtui/stateful_tree.rs @@ -2,7 +2,7 @@ use std::collections::HashMap; use itertools::Itertools; use tui_tree_widget::{TreeItem, TreeState}; -use zbus_xml::{ArgDirection, Node}; +use zbus_xml::{ArgDirection, Method, Node}; #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum MemberTypes { @@ -17,12 +17,24 @@ pub enum MemberTypes { // > Methods/Properties/Signals (The actual list of the methods) #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum DbusIdentifier { - Object(String), // ObjectPath - Interface(String), // InterfaceName - Member(MemberTypes), // Can be Method, Properties, Signals - Method(String), // zbus_name::MemberName - Property(String), // zbus_name::PropertyName - Signal(String), // zbus_name::MemberName + Object(String), // ObjectPath + Interface(String), // InterfaceName + Member(MemberTypes), // Can be Method, Properties, Signals + Method(MethodDescription), // zbus_name::MemberName + Property(String), // zbus_name::PropertyName + Signal(String), // zbus_name::MemberName +} + +#[derive(Debug, Clone, PartialEq)] +pub struct MethodDescription(pub Method<'static>); + +// Rely on PartialEq +impl Eq for MethodDescription {} + +impl std::hash::Hash for MethodDescription { + fn hash(&self, state: &mut H) { + self.0.name().hash(state); + } } impl Default for DbusIdentifier { @@ -31,7 +43,7 @@ impl Default for DbusIdentifier { } } -#[derive(Debug, Clone)] +#[derive(Debug)] pub struct StatefulTree { pub state: TreeState, pub items: Vec>, @@ -67,16 +79,16 @@ impl StatefulTree { .collect(); Self { state: TreeState::default(), - items: items, + items, } } pub fn down(&mut self) { - self.state.key_down(&self.items); + self.state.key_down(); } pub fn up(&mut self) { - self.state.key_up(&self.items); + self.state.key_up(); } pub fn left(&mut self) { @@ -92,7 +104,7 @@ impl StatefulTree { } } -fn node_to_treeitems(node: &zbus_xml::Node) -> Vec> { +fn node_to_treeitems(node: &zbus_xml::Node<'static>) -> Vec> { let children: Vec> = node .interfaces() .iter() @@ -100,6 +112,7 @@ fn node_to_treeitems(node: &zbus_xml::Node) -> Vec> = interface .methods() .iter() + .cloned() .map(|method| { let inputs: Vec = method .args() @@ -122,7 +135,7 @@ fn node_to_treeitems(node: &zbus_xml::Node) -> Vec Color { if app.working_area == working_area { @@ -20,10 +32,11 @@ fn working_area_border(app: &App, working_area: WorkingArea) -> Color { pub fn ui(frame: &mut Frame, app: &mut App) { // Create two chunks with equal horizontal screen space + let area = frame.size(); let full = Layout::default() .direction(Direction::Vertical) .constraints([Constraint::Min(5), Constraint::Max(2)]) - .split(frame.size()); + .split(area); let chunks = Layout::default() .direction(Direction::Horizontal) .constraints([Constraint::Percentage(25), Constraint::Percentage(75)].as_ref()) @@ -53,7 +66,7 @@ pub fn ui(frame: &mut Frame, app: &mut App) { // We can now render the item list frame.render_stateful_widget(items, chunks[0], &mut app.services.state); - let objects_view = Tree::new(app.objects.items.clone()) + let objects_view = Tree::new(&app.objects.items) .unwrap() .block( Block::default() @@ -65,8 +78,113 @@ pub fn ui(frame: &mut Frame, app: &mut App) { .highlight_style(Style::default().add_modifier(Modifier::BOLD)) .highlight_symbol(">> "); frame.render_stateful_widget(objects_view, chunks[1], &mut app.objects.state); + + // Render a potential pop up + if let WorkingArea::MethodCallPopUp(ref mut popup) = app.working_area { + // TODO: Big ass block, lets refactor to smaller functions + let method = &popup.method_description.0; + + let bottom_text = Span::raw("Navigation: ↓ ↑ | Call: Enter | Quit: esq"); + let border_color = if popup.called { + Color::Green + } else { + Color::Blue + }; + let block = Block::bordered() + .title(Title::from(method.name().to_string()).position(Position::Top)) + .title( + Title::from(bottom_text) + .alignment(Alignment::Center) + .position(Position::Bottom), + ) + .border_style(Style::default().fg(border_color)); + let area = centered_rect(80, 50, area); + let args = popup.method_description.0.args(); + let single_line_layout = Layout::vertical( + repeat_n(Constraint::Length(3), args.len()).chain([Constraint::Min(1)]), + ); + + let segments = single_line_layout.split(block.inner(area)); + frame.render_widget(Clear, area); //this clears out the background + frame.render_widget(block, area); + if popup.method_arg_vis.is_empty() { + // First time init of text areas + for arg in method.args().iter().take(segments.len()) { + let mut text_area = TextArea::default(); + let inout: String = if let Some(direction) = arg.direction() { + match direction { + zbus_xml::ArgDirection::In => "input".to_string(), + zbus_xml::ArgDirection::Out => "output".to_string(), + } + } else { + "".to_string() + }; + text_area.set_cursor_line_style(Style::default()); + text_area.set_cursor_style(Style::default()); + text_area.set_block( + Block::default() + .borders(Borders::ALL) + .title(format!("name: {} | {}", arg.name().unwrap(), inout)) + .title_bottom(format!("type: {}", arg.ty())), + ); + let parser = get_parser( + zvariant::parsed::Signature::from_str(arg.ty().signature().as_str()) + .expect("The type description for the method we got was not good"), + ); + let input = match arg.direction().unwrap_or(zbus_xml::ArgDirection::In) { + zbus_xml::ArgDirection::In => true, + zbus_xml::ArgDirection::Out => false, + }; + popup.method_arg_vis.push(MethodArgVisual { + text_area, + parser: Box::new(parser), + is_input: input, + }); + } + } + for (i, input) in popup.method_arg_vis.iter_mut().enumerate() { + let emphasis = if i == popup.selected { + let method_arg: String = input.text_area.lines()[0].clone(); + let parsed = input.parser.parse(method_arg); + match parsed { + Ok(_) => Style::default().fg(Color::Green), + Err(_) => Style::default().fg(Color::Red), + } + } else { + Style::default() + }; + input.text_area.set_block( + input + .text_area + .block() + .unwrap() + .clone() + .border_style(emphasis), + ); + input.text_area.set_cursor_line_style(emphasis); + frame.render_widget(&input.text_area, segments[i]); + } + } + let bottom_text = Span::raw("Change focus: Tab | Navigation: ← ↓ ↑ → | Get Service: Enter | Quit: q"); let helper_paragraph = Paragraph::new(bottom_text).alignment(Alignment::Center); frame.render_widget(helper_paragraph, full[1]); } + +/// helper function to create a centered rect using up certain percentage of the available rect `r` +fn centered_rect(percent_x: u16, percent_y: u16, r: Rect) -> Rect { + let popup_layout = Layout::vertical([ + Constraint::Percentage((100 - percent_y) / 2), + Constraint::Percentage(percent_y), + Constraint::Percentage((100 - percent_y) / 2), + ]) + .split(r); + + Layout::horizontal([ + Constraint::Percentage((100 - percent_x) / 2), + Constraint::Percentage(percent_x), + Constraint::Percentage((100 - percent_x) / 2), + ]) + .split(popup_layout[1])[1] +} From 3edf0f15d2d0c5a0e0e626a30ff810eca4bdf6a4 Mon Sep 17 00:00:00 2001 From: Troels Dalsgaard Hoffmeyer Date: Tue, 5 Nov 2024 23:36:13 +0100 Subject: [PATCH 2/2] zbus: Update to 5.1 --- Cargo.lock | 284 ++++++++++++---------------------- Cargo.toml | 8 +- src/bin/dtui/app.rs | 1 - src/bin/dtui/main.rs | 6 +- src/bin/dtui/parser.rs | 76 +++++---- src/bin/dtui/stateful_tree.rs | 26 +++- src/bin/dtui/ui.rs | 4 +- 7 files changed, 163 insertions(+), 242 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 77ecc58..5ad6a42 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -117,6 +117,30 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "async-executor" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30ca9a001c1e8ba5149f91a74362376cc6bc5b919d92d988668657bd570bdcec" +dependencies = [ + "async-task", + "concurrent-queue", + "fastrand", + "futures-lite", + "slab", +] + +[[package]] +name = "async-fs" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebcd09b382f40fcd159c2d695175b2ae620ffa5f3bd6f664131efff4e8b9e04a" +dependencies = [ + "async-lock", + "blocking", + "futures-lite", +] + [[package]] name = "async-io" version = "2.3.4" @@ -149,9 +173,9 @@ dependencies = [ [[package]] name = "async-process" -version = "2.2.4" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8a07789659a4d385b79b18b9127fc27e1a59e1e89117c78c5ea3b806f016374" +checksum = "63255f1dc2381611000436537bbedfe83183faa303a5a0edaf191edef06526bb" dependencies = [ "async-channel", "async-io", @@ -164,7 +188,6 @@ dependencies = [ "futures-lite", "rustix", "tracing", - "windows-sys 0.59.0", ] [[package]] @@ -204,9 +227,9 @@ checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" [[package]] name = "async-trait" -version = "0.1.82" +version = "0.1.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a27b8a3a6e1a44fa4c8baf1f653e4172e81486d4941f2237e20dc2d0cf4ddff1" +checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ "proc-macro2", "quote", @@ -246,15 +269,6 @@ version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" -[[package]] -name = "block-buffer" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" -dependencies = [ - "generic-array", -] - [[package]] name = "blocking" version = "1.6.1" @@ -268,12 +282,6 @@ dependencies = [ "piper", ] -[[package]] -name = "byteorder" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" - [[package]] name = "bytes" version = "1.7.1" @@ -322,7 +330,7 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8eebd66744a15ded14960ab4ccdbfb51ad3b81f51f3f04a80adac98c985396c9" dependencies = [ - "hashbrown", + "hashbrown 0.14.5", "stacker", ] @@ -394,15 +402,6 @@ dependencies = [ "crossbeam-utils", ] -[[package]] -name = "cpufeatures" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" -dependencies = [ - "libc", -] - [[package]] name = "crossbeam-utils" version = "0.8.20" @@ -434,26 +433,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "crypto-common" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" -dependencies = [ - "generic-array", - "typenum", -] - -[[package]] -name = "digest" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" -dependencies = [ - "block-buffer", - "crypto-common", -] - [[package]] name = "dtui" version = "2.0.0" @@ -554,21 +533,21 @@ checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" [[package]] name = "futures-core" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] name = "futures-io" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-lite" -version = "2.3.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52527eb5074e35e9339c6b4e8d12600c7128b68fb25dcb9fa9dec18f7c25f3a5" +checksum = "3f1fa2f9765705486b33fd2acf1577f8ec449c2ba1f318ae5447697b7c08d210" dependencies = [ "fastrand", "futures-core", @@ -579,51 +558,32 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" [[package]] name = "futures-task" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" [[package]] name = "futures-util" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures-core", + "futures-io", "futures-sink", "futures-task", + "memchr", "pin-project-lite", "pin-utils", "slab", ] -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", -] - -[[package]] -name = "getrandom" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" -dependencies = [ - "cfg-if", - "libc", - "wasi", -] - [[package]] name = "gimli" version = "0.31.0" @@ -640,6 +600,12 @@ dependencies = [ "allocator-api2", ] +[[package]] +name = "hashbrown" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a9bfc1af68b1726ea47d3d5109de126281def866b33970e10fbab11b5dafab3" + [[package]] name = "heck" version = "0.5.0" @@ -666,12 +632,12 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "indexmap" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ "equivalent", - "hashbrown", + "hashbrown 0.15.1", ] [[package]] @@ -744,7 +710,7 @@ version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37ee39891760e7d94734f6f63fedc29a2e4a152f836120753a72503f09fcf904" dependencies = [ - "hashbrown", + "hashbrown 0.14.5", ] [[package]] @@ -771,12 +737,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "minimal-lexical" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" - [[package]] name = "miniz_oxide" version = "0.8.0" @@ -823,16 +783,6 @@ dependencies = [ "memoffset", ] -[[package]] -name = "nom" -version = "7.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" -dependencies = [ - "memchr", - "minimal-lexical", -] - [[package]] name = "nu-ansi-term" version = "0.46.0" @@ -947,15 +897,6 @@ dependencies = [ "windows-sys 0.59.0", ] -[[package]] -name = "ppv-lite86" -version = "0.2.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" -dependencies = [ - "zerocopy", -] - [[package]] name = "proc-macro-crate" version = "3.2.0" @@ -985,9 +926,9 @@ dependencies = [ [[package]] name = "quick-xml" -version = "0.36.1" +version = "0.36.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96a05e2e8efddfa51a84ca47cec303fac86c8541b686d37cac5efc0e094417bc" +checksum = "f7649a7b4df05aed9ea7ec6f628c67c9953a43869b8bc50929569b2999d443fe" dependencies = [ "memchr", "serde", @@ -1002,36 +943,6 @@ dependencies = [ "proc-macro2", ] -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "libc", - "rand_chacha", - "rand_core", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom", -] - [[package]] name = "ratatui" version = "0.27.0" @@ -1114,9 +1025,9 @@ checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustix" -version = "0.38.36" +version = "0.38.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f55e80d50763938498dd5ebb18647174e0c76dc38c5505294bb224624f30f36" +checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811" dependencies = [ "bitflags", "errno", @@ -1186,17 +1097,6 @@ dependencies = [ "syn", ] -[[package]] -name = "sha1" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest", -] - [[package]] name = "sharded-slab" version = "0.1.7" @@ -1337,9 +1237,9 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.12.0" +version = "3.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" +checksum = "f0f2c9fc62d0beef6951ccffd757e241266a2c833136efbe35af6cd2567dca5b" dependencies = [ "cfg-if", "fastrand", @@ -1396,9 +1296,9 @@ checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" [[package]] name = "toml_edit" -version = "0.22.20" +version = "0.22.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d" +checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" dependencies = [ "indexmap", "toml_datetime", @@ -1521,12 +1421,6 @@ dependencies = [ "unicode-width", ] -[[package]] -name = "typenum" -version = "1.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" - [[package]] name = "uds_windows" version = "1.1.0" @@ -1763,9 +1657,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" -version = "0.6.18" +version = "0.6.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68a9bda4691f099d435ad181000724da8e5899daa10713c2d432552b9ccd3a6f" +checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" dependencies = [ "memchr", ] @@ -1782,30 +1676,35 @@ dependencies = [ [[package]] name = "zbus" -version = "4.4.0" -source = "git+https://github.com/dbus2/zbus.git?branch=main#60d0443ce1771559812af1f0945f0de1028a2f42" +version = "5.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e0c8d6fdd4c4ac401fd298fd169d538a386e9df3c32ff136e8745dfa443dbd8" dependencies = [ "async-broadcast", + "async-executor", + "async-fs", + "async-io", + "async-lock", "async-process", "async-recursion", + "async-task", "async-trait", + "blocking", "enumflags2", "event-listener", "futures-core", - "futures-sink", "futures-util", "hex", "nix", "ordered-stream", - "rand", "serde", "serde_repr", - "sha1", "static_assertions", "tokio", "tracing", "uds_windows", "windows-sys 0.59.0", + "winnow", "xdg-home", "zbus_macros", "zbus_names", @@ -1814,30 +1713,36 @@ dependencies = [ [[package]] name = "zbus_macros" -version = "4.4.0" -source = "git+https://github.com/dbus2/zbus.git?branch=main#60d0443ce1771559812af1f0945f0de1028a2f42" +version = "5.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed1f3cc6313cbefd539b4eee6de36a990897ab6cc2c30a82b3ac29ef9099e6c0" dependencies = [ "proc-macro-crate", "proc-macro2", "quote", "syn", + "zbus_names", + "zvariant", "zvariant_utils", ] [[package]] name = "zbus_names" -version = "3.0.0" -source = "git+https://github.com/dbus2/zbus.git?branch=main#60d0443ce1771559812af1f0945f0de1028a2f42" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "856b7a38811f71846fd47856ceee8bccaec8399ff53fb370247e66081ace647b" dependencies = [ "serde", "static_assertions", + "winnow", "zvariant", ] [[package]] name = "zbus_xml" -version = "4.0.0" -source = "git+https://github.com/dbus2/zbus.git?branch=main#60d0443ce1771559812af1f0945f0de1028a2f42" +version = "5.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c210addbcb424e91411ef782a5a1e264b5a5d268766faccd7d113c7c0440b9ab" dependencies = [ "quick-xml", "serde", @@ -1852,7 +1757,6 @@ version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ - "byteorder", "zerocopy-derive", ] @@ -1869,21 +1773,24 @@ dependencies = [ [[package]] name = "zvariant" -version = "4.2.0" -source = "git+https://github.com/dbus2/zbus.git?branch=main#60d0443ce1771559812af1f0945f0de1028a2f42" +version = "5.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1200ee6ac32f1e5a312e455a949a4794855515d34f9909f4a3e082d14e1a56f" dependencies = [ "endi", "enumflags2", "serde", "static_assertions", + "winnow", "zvariant_derive", "zvariant_utils", ] [[package]] name = "zvariant_derive" -version = "4.2.0" -source = "git+https://github.com/dbus2/zbus.git?branch=main#60d0443ce1771559812af1f0945f0de1028a2f42" +version = "5.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "687e3b97fae6c9104fbbd36c73d27d149abf04fb874e2efbd84838763daa8916" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -1894,13 +1801,14 @@ dependencies = [ [[package]] name = "zvariant_utils" -version = "2.2.0" -source = "git+https://github.com/dbus2/zbus.git?branch=main#60d0443ce1771559812af1f0945f0de1028a2f42" +version = "3.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20d1d011a38f12360e5fcccceeff5e2c42a8eb7f27f0dcba97a0862ede05c9c6" dependencies = [ - "nom", "proc-macro2", "quote", "serde", "static_assertions", "syn", + "winnow", ] diff --git a/Cargo.toml b/Cargo.toml index 54b93db..9787011 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,7 @@ authors = ["Troels Hoffmeyer "] description = "dBus TUI for introspecting your current dbus session/system" license = "MIT" repository = "https://github.com/Troels51/dtui" -rust-version = "1.75" +rust-version = "1.80" keywords = ["tui", "dbus"] categories = ["command-line-utilities"] exclude = [ @@ -17,18 +17,18 @@ exclude = [ [dependencies] tui-tree-widget = "0.21" -zbus = { git = "https://github.com/dbus2/zbus.git", branch = "main", default-features = false, features = ["tokio"] } crossterm = "0.27" tokio = { version = "1.32", features = ["full"] } async-recursion = "1.1.1" itertools = "0.11.0" clap = { version = "4.4.1", features = ["derive"] } ratatui = { version = "0.27", features = ["macros"] } -zbus_xml = { git = "https://github.com/dbus2/zbus.git", branch = "main", default-features = false } tracing-error = "0.2.0" tracing = "0.1.40" tracing-subscriber = { version = "0.3.18", features = ["env-filter", "json", "fmt"] } tracing-journald = "0.3.0" tui-textarea = "0.5.1" -zbus_names = { git = "https://github.com/dbus2/zbus.git", branch = "main", default-features = false } chumsky = "0.9.3" +zbus = {version = "5.1.0", features = ["tokio"]} +zbus_names = "4.1.0" +zbus_xml = "5.0.1" diff --git a/src/bin/dtui/app.rs b/src/bin/dtui/app.rs index a26280e..21508f4 100644 --- a/src/bin/dtui/app.rs +++ b/src/bin/dtui/app.rs @@ -2,7 +2,6 @@ use std::time::{Duration, Instant}; use chumsky::Parser; use crossterm::event::{self, Event, KeyCode}; -use itertools::Itertools; use ratatui::{backend::Backend, Terminal}; use tokio::sync::mpsc::Receiver; use tracing::Level; diff --git a/src/bin/dtui/main.rs b/src/bin/dtui/main.rs index 926f4a9..c8cb2c5 100644 --- a/src/bin/dtui/main.rs +++ b/src/bin/dtui/main.rs @@ -26,7 +26,7 @@ use tracing::level_filters::LevelFilter; use tracing_subscriber::layer::SubscriberExt; use tracing_subscriber::prelude::*; -use zbus::{Connection, ConnectionBuilder}; +use zbus::{conn, Connection}; #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, ValueEnum)] enum BusType { @@ -62,9 +62,7 @@ where BusType::Session => Connection::session().await?, }; if let Some(address) = args.address { - connection = ConnectionBuilder::address(address.as_str())? - .build() - .await?; + connection = conn::Builder::address(address.as_str())?.build().await?; } let (dbus_handler_sender, app_receiver) = mpsc::channel::(16); let dbus_handler = DbusActorHandle::new(dbus_handler_sender, connection); diff --git a/src/bin/dtui/parser.rs b/src/bin/dtui/parser.rs index 088a1b4..95af5bf 100644 --- a/src/bin/dtui/parser.rs +++ b/src/bin/dtui/parser.rs @@ -1,8 +1,8 @@ use chumsky::prelude::*; -use std::{collections::HashMap, u32}; -use zbus::zvariant::{self, parsed, ObjectPath, Signature, StructureBuilder}; +use std::{collections::HashMap, str::FromStr, u32}; +use zbus::zvariant::{self, ObjectPath, Signature, StructureBuilder}; -/// Create a parser from a parsed::Signature. +/// Create a parser from a Signature. /// The language that this parses is a human readable version of the dbus format. /// Arrays are delimited by [], with values seperated by "," /// Structure are delimited by (), with values seperated by "," @@ -13,36 +13,34 @@ use zbus::zvariant::{self, parsed, ObjectPath, Signature, StructureBuilder}; /// {"first": 1, "second": 2} is a dictionary with string as key type and key type of some number, it's signature is "a{su}" /// /// ``` -/// let signature = parsed::Signature::from_str("as").unwrap(); +/// let signature = Signature::from_str("as").unwrap(); /// let result = get_parser(signature).parse("[\"first\", \"second\"]"); /// assert_eq!(result, Ok(zvariant::Value::Array(vec!["first", "second"].into()))); /// ``` pub fn get_parser( - signature: parsed::Signature, + signature: Signature, ) -> impl Parser, Error = Simple> { match signature { - zvariant::parsed::Signature::Unit => todo!(), - zvariant::parsed::Signature::U8 => parser_u8().boxed(), - zvariant::parsed::Signature::Bool => parser_bool().boxed(), - zvariant::parsed::Signature::I16 => parser_i16().boxed(), - zvariant::parsed::Signature::U16 => parser_u16().boxed(), - zvariant::parsed::Signature::I32 => parser_i32().boxed(), - zvariant::parsed::Signature::U32 => parser_u32().boxed(), - zvariant::parsed::Signature::I64 => parser_i64().boxed(), - zvariant::parsed::Signature::U64 => parser_u64().boxed(), - zvariant::parsed::Signature::F64 => parser_f64().boxed(), - zvariant::parsed::Signature::Str => parser_string().boxed(), - zvariant::parsed::Signature::Signature => parser_signature().boxed(), - zvariant::parsed::Signature::ObjectPath => parser_object_path().boxed(), - zvariant::parsed::Signature::Variant => parser_variant().boxed(), - zvariant::parsed::Signature::Fd => parser_fd().boxed(), - zvariant::parsed::Signature::Array(array) => { - parser_array(array.signature().clone()).boxed() - } - zvariant::parsed::Signature::Dict { key, value } => { + zvariant::Signature::Unit => todo!(), + zvariant::Signature::U8 => parser_u8().boxed(), + zvariant::Signature::Bool => parser_bool().boxed(), + zvariant::Signature::I16 => parser_i16().boxed(), + zvariant::Signature::U16 => parser_u16().boxed(), + zvariant::Signature::I32 => parser_i32().boxed(), + zvariant::Signature::U32 => parser_u32().boxed(), + zvariant::Signature::I64 => parser_i64().boxed(), + zvariant::Signature::U64 => parser_u64().boxed(), + zvariant::Signature::F64 => parser_f64().boxed(), + zvariant::Signature::Str => parser_string().boxed(), + zvariant::Signature::Signature => parser_signature().boxed(), + zvariant::Signature::ObjectPath => parser_object_path().boxed(), + zvariant::Signature::Variant => parser_variant().boxed(), + zvariant::Signature::Fd => parser_fd().boxed(), + zvariant::Signature::Array(array) => parser_array(array.signature().clone()).boxed(), + zvariant::Signature::Dict { key, value } => { parser_dict(key.signature().clone(), value.signature().clone()).boxed() } - zvariant::parsed::Signature::Structure(structure) => parser_struct(structure).boxed(), + zvariant::Signature::Structure(structure) => parser_struct(structure).boxed(), } } @@ -58,11 +56,11 @@ fn parser_variant<'a>() -> impl Parser, Error = S } // fn parser_struct<'a>( - structure: parsed::FieldsSignatures, + structure: zvariant::signature::Fields, ) -> impl Parser, Error = Simple> { let mut element_parsers = structure .iter() - .map(|signature: &zbus::zvariant::parsed::Signature| get_parser(signature.clone())); + .map(|signature: &zbus::zvariant::Signature| get_parser(signature.clone())); let mut full_parser = just('(').map(|_| Vec::>::new()).boxed(); // The map is there to get types to match as the chain in the loop needs the parser to output a Vec full_parser = full_parser.chain(element_parsers.next().unwrap()).boxed(); // The first doesnt get a ',' the rest do for element_parser in element_parsers { @@ -80,8 +78,8 @@ fn parser_struct<'a>( }) } fn parser_dict<'a>( - key_type: parsed::Signature, - value_type: parsed::Signature, + key_type: Signature, + value_type: Signature, ) -> impl Parser, Error = Simple> { let key_parser = get_parser(key_type.clone()); let value_parser = get_parser(value_type.clone()); @@ -99,7 +97,7 @@ fn parser_dict<'a>( .map( move |m: HashMap, zvariant::Value<'_>>| { let mut dict = - zvariant::Dict::new(key_type.clone().into(), value_type.clone().into()); + zvariant::Dict::new(&key_type, &value_type); for (k, v) in m { dict.append(k, v).expect("Could not append to key value pair, this should not happen if types are correct"); } @@ -109,7 +107,7 @@ fn parser_dict<'a>( } fn parser_array<'a>( - signature: parsed::Signature, + signature: Signature, ) -> impl Parser, Error = Simple> { let element_parser = get_parser(signature.clone()).boxed(); element_parser @@ -119,7 +117,7 @@ fn parser_array<'a>( .flatten() .delimited_by(just('['), just(']')) .map(move |v: Vec>| { - let mut array: zvariant::Array<'_> = zvariant::Array::new(signature.clone().into()); + let mut array: zvariant::Array<'_> = zvariant::Array::new(&signature); for element in v { array .append(element) @@ -262,7 +260,7 @@ fn parser_signature() -> impl Parser, Error = Sim .then_ignore(just('"')) .collect::() .try_map(|digits, span| { - if let Ok(signature) = Signature::try_from(digits) { + if let Ok(signature) = Signature::from_str(digits.as_str()) { Ok(zvariant::Value::Signature(signature)) } else { Err(Simple::custom( @@ -331,7 +329,7 @@ fn parser_fd() -> impl Parser, Error = Simple) -> Vec = method .args() .iter() .filter(|arg| arg.direction().is_some_and(|s| s == ArgDirection::Out)) - .map(|arg| format!("{}: {}", arg.name().unwrap_or_default(), arg.ty())) + .map(|arg| { + format!( + "{}: {}", + arg.name().unwrap_or_default(), + arg.ty().to_string() + ) + }) .collect(); let return_arrow = if outputs.is_empty() { "" } else { "=>" }; // If we dont return anything, the arrow shouldnt be there let leaf_string: String = format!( @@ -146,7 +158,7 @@ fn node_to_treeitems(node: &zbus_xml::Node<'static>) -> Vec) -> Vec(frame: &mut Frame, app: &mut App) { Block::default() .borders(Borders::ALL) .title(format!("name: {} | {}", arg.name().unwrap(), inout)) - .title_bottom(format!("type: {}", arg.ty())), + .title_bottom(format!("type: {}", arg.ty().to_string())), ); let parser = get_parser( - zvariant::parsed::Signature::from_str(arg.ty().signature().as_str()) + zvariant::Signature::from_str(arg.ty().to_string().as_str()) .expect("The type description for the method we got was not good"), ); let input = match arg.direction().unwrap_or(zbus_xml::ArgDirection::In) {