From 4fb6ae82af59916f3b210199f5a64bd3edb48e5e Mon Sep 17 00:00:00 2001 From: Himadri Bhattacharjee <107522312+lavafroth@users.noreply.github.com> Date: Wed, 26 Jun 2024 10:14:26 +0530 Subject: [PATCH 01/11] feat: sweet parser scaffolding --- Cargo.lock | 636 +++++++++++++++++++++++++++++--------------- swhkd/Cargo.toml | 1 + swhkd/src/config.rs | 277 +++++-------------- 3 files changed, 487 insertions(+), 427 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7c58ee0..b75efa8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10,17 +10,27 @@ dependencies = [ "env_logger", "evdev", "flate2", - "itertools", + "itertools 0.10.5", "log", "nix", "signal-hook", "signal-hook-tokio", + "sweet", "sysinfo", "tokio", "tokio-stream", "tokio-udev", ] +[[package]] +name = "addr2line" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" +dependencies = [ + "gimli", +] + [[package]] name = "adler" version = "1.0.2" @@ -29,77 +39,99 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "aho-corasick" -version = "0.7.20" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] [[package]] name = "anstream" -version = "0.6.13" +version = "0.6.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb" +checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", + "is_terminal_polyfill", "utf8parse", ] [[package]] name = "anstyle" -version = "1.0.6" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" +checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" [[package]] name = "anstyle-parse" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" +checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.0.2" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" +checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391" dependencies = [ "windows-sys 0.52.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.2" +version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" +checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" dependencies = [ "anstyle", "windows-sys 0.52.0", ] +[[package]] +name = "anyhow" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" + [[package]] name = "atty" version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ - "hermit-abi", + "hermit-abi 0.1.19", "libc", "winapi", ] [[package]] name = "autocfg" -version = "1.1.0" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" + +[[package]] +name = "backtrace" +version = "0.3.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] [[package]] name = "bitflags" @@ -107,6 +139,12 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + [[package]] name = "bitvec" version = "1.0.1" @@ -119,17 +157,26 @@ dependencies = [ "wyz", ] +[[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 = "bytes" -version = "1.3.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfb24e866b15a1af2a1b663f10c6b6b8f397a84aadb828f12e5b289ec23a3a3c" +checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" [[package]] name = "cc" -version = "1.0.78" +version = "1.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a20104e2335ce8a659d6dd92a51a767a0c062599c73b343fd152cb401e828c3d" +checksum = "ac367972e516d45567c7eafc73d24e1c193dcf200a8d94e9db7b3d38b349572d" [[package]] name = "cfg-if" @@ -139,9 +186,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "4.5.1" +version = "4.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c918d541ef2913577a0f9566e9ce27cb35b6df072075769e0b26cb5a554520da" +checksum = "5db83dced34638ad474f39f250d7fea9598bdd239eaced1bdf45d597da0f433f" dependencies = [ "clap_builder", "clap_derive", @@ -149,9 +196,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.1" +version = "4.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f3e7391dad68afb0c2ede1bf619f579a3dc9c2ec67f089baa397123a2f3d1eb" +checksum = "f7e204572485eb3fbf28f871612191521df159bc3e15a9f5064c66dba3a8c05f" dependencies = [ "anstream", "anstyle", @@ -161,91 +208,102 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.0" +version = "4.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "307bc0538d5f0f83b8248db3087aa92fe504e4691294d0c96c0eabc33f47ba47" +checksum = "c780290ccf4fb26629baa7a1081e68ced113f1d3ec302fa5948f1c381ebf06c6" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.52", + "syn", ] [[package]] name = "clap_lex" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" +checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70" [[package]] name = "colorchoice" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" [[package]] name = "core-foundation-sys" -version = "0.8.3" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" [[package]] -name = "crc32fast" -version = "1.3.2" +name = "cpufeatures" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" dependencies = [ - "cfg-if", + "libc", ] [[package]] -name = "crossbeam-channel" -version = "0.5.6" +name = "crc32fast" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" dependencies = [ "cfg-if", - "crossbeam-utils", ] [[package]] name = "crossbeam-deque" -version = "0.8.2" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" dependencies = [ - "cfg-if", "crossbeam-epoch", "crossbeam-utils", ] [[package]] name = "crossbeam-epoch" -version = "0.9.13" +version = "0.9.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01a9af1f4c2ef74bb8aa1f7e19706bc72d03598c8a570bb5de72243c7a9d9d5a" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" dependencies = [ - "autocfg", - "cfg-if", "crossbeam-utils", - "memoffset 0.7.1", - "scopeguard", ] [[package]] name = "crossbeam-utils" -version = "0.8.14" +version = "0.8.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" + +[[package]] +name = "crypto-common" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ - "cfg-if", + "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 = "either" -version = "1.8.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" [[package]] name = "env_logger" @@ -262,9 +320,9 @@ dependencies = [ [[package]] name = "evdev" -version = "0.12.1" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bed59fcc8cfd6b190814a509018388462d3b203cf6dd10db5c00087e72a83f3" +checksum = "ab6055a93a963297befb0f4f6e18f314aec9767a4bbe88b151126df2433610a7" dependencies = [ "bitvec", "cfg-if", @@ -277,9 +335,9 @@ dependencies = [ [[package]] name = "flate2" -version = "1.0.25" +version = "1.0.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841" +checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae" dependencies = [ "crc32fast", "miniz_oxide", @@ -293,15 +351,31 @@ checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" [[package]] name = "futures-core" -version = "0.3.25" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" + +[[package]] +name = "generic-array" +version = "0.14.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04909a7a7e4633ae6c4a9ab280aeb86da1236243a77b694a49eacd659a4bd3ac" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "gimli" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" [[package]] name = "heck" -version = "0.4.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "hermit-abi" @@ -312,12 +386,24 @@ dependencies = [ "libc", ] +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + [[package]] name = "humantime" version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" +[[package]] +name = "is_terminal_polyfill" +version = "1.70.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" + [[package]] name = "itertools" version = "0.10.5" @@ -327,11 +413,20 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + [[package]] name = "libc" -version = "0.2.138" +version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" [[package]] name = "libudev-sys" @@ -345,9 +440,9 @@ dependencies = [ [[package]] name = "lock_api" -version = "0.4.9" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" dependencies = [ "autocfg", "scopeguard", @@ -355,18 +450,15 @@ dependencies = [ [[package]] name = "log" -version = "0.4.17" +version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" -dependencies = [ - "cfg-if", -] +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" [[package]] name = "memchr" -version = "2.5.0" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "memoffset" @@ -377,34 +469,24 @@ dependencies = [ "autocfg", ] -[[package]] -name = "memoffset" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" -dependencies = [ - "autocfg", -] - [[package]] name = "miniz_oxide" -version = "0.6.2" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" +checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" dependencies = [ "adler", ] [[package]] name = "mio" -version = "0.8.5" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5d732bc30207a6423068df043e3d02e0735b155ad7ce1a6f76fe2baa5b158de" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ "libc", - "log", "wasi", - "windows-sys 0.42.0", + "windows-sys 0.48.0", ] [[package]] @@ -413,11 +495,11 @@ version = "0.23.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f3790c00a0150112de0f4cd161e3d7fc4b2d8a5542ffc35f099a2562aecb35c" dependencies = [ - "bitflags", + "bitflags 1.3.2", "cc", "cfg-if", "libc", - "memoffset 0.6.5", + "memoffset", ] [[package]] @@ -431,25 +513,34 @@ dependencies = [ [[package]] name = "num_cpus" -version = "1.14.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6058e64324c71e02bc2b150e4f3bc8286db6c83092132ffa3f6b1eab0f9def5" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi", + "hermit-abi 0.3.9", "libc", ] +[[package]] +name = "object" +version = "0.36.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "576dfe1fc8f9df304abb159d767a29d0476f7750fbf8aa7ad07816004a207434" +dependencies = [ + "memchr", +] + [[package]] name = "once_cell" -version = "1.16.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "parking_lot" -version = "0.12.1" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" dependencies = [ "lock_api", "parking_lot_core", @@ -457,43 +548,88 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.5" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ff9f3fef3968a3ec5945535ed654cb38ff72d7495a25619e2247fb15a2ed9ba" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", - "windows-sys 0.42.0", + "windows-targets 0.52.5", +] + +[[package]] +name = "pest" +version = "2.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "560131c633294438da9f7c4b08189194b20946c8274c6b9e38881a7874dc8ee8" +dependencies = [ + "memchr", + "thiserror", + "ucd-trie", +] + +[[package]] +name = "pest_derive" +version = "2.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26293c9193fbca7b1a3bf9b79dc1e388e927e6cacaa78b4a3ab705a1d3d41459" +dependencies = [ + "pest", + "pest_generator", +] + +[[package]] +name = "pest_generator" +version = "2.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ec22af7d3fb470a85dd2ca96b7c577a1eb4ef6f1683a9fe9a8c16e136c04687" +dependencies = [ + "pest", + "pest_meta", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "pest_meta" +version = "2.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7a240022f37c361ec1878d646fc5b7d7c4d28d5946e1a80ad5a7a4f4ca0bdcd" +dependencies = [ + "once_cell", + "pest", + "sha2", ] [[package]] name = "pin-project-lite" -version = "0.2.9" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" [[package]] name = "pkg-config" -version = "0.3.27" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" [[package]] name = "proc-macro2" -version = "1.0.78" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.35" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ "proc-macro2", ] @@ -506,9 +642,9 @@ checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" [[package]] name = "rayon" -version = "1.6.1" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db3a213adf02b3bcfd2d3846bb41cb22857d131789e01df434fb7e7bc0759b7" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" dependencies = [ "either", "rayon-core", @@ -516,30 +652,40 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.10.1" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cac410af5d00ab6884528b4ab69d1e8e146e8d471201800fa1b4524126de6ad3" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" dependencies = [ - "crossbeam-channel", "crossbeam-deque", "crossbeam-utils", - "num_cpus", ] [[package]] name = "redox_syscall" -version = "0.2.16" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +checksum = "c82cf8cff14456045f55ec4241383baeff27af886adb72ffb2162f99911de0fd" dependencies = [ - "bitflags", + "bitflags 2.6.0", ] [[package]] name = "regex" -version = "1.7.0" +version = "1.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" dependencies = [ "aho-corasick", "memchr", @@ -548,21 +694,38 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.6.28" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" + +[[package]] +name = "rustc-demangle" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "scopeguard" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] [[package]] name = "signal-hook" -version = "0.3.14" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a253b5e89e2698464fc26b545c9edceb338e18a89effeeecfea192c3025be29d" +checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801" dependencies = [ "libc", "signal-hook-registry", @@ -570,9 +733,9 @@ dependencies = [ [[package]] name = "signal-hook-registry" -version = "1.4.0" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" dependencies = [ "libc", ] @@ -591,25 +754,38 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.10.0" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "socket2" -version = "0.4.7" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" dependencies = [ "libc", - "winapi", + "windows-sys 0.52.0", ] [[package]] name = "strsim" -version = "0.11.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "sweet" +version = "0.1.0" +source = "git+https://github.com/lavafroth/sweet.git#361be3320068c21ad4db4a6ea7831ab3ad1aeacd" +dependencies = [ + "anyhow", + "bitflags 2.6.0", + "itertools 0.12.1", + "pest", + "pest_derive", + "thiserror", +] [[package]] name = "swhks" @@ -624,20 +800,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.107" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "syn" -version = "2.0.52" +version = "2.0.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07" +checksum = "901fa70d88b9d6c98022e23b4136f9f3e54e4662c3bc1bd1d84a42a9a0f0c1e9" dependencies = [ "proc-macro2", "quote", @@ -667,43 +832,42 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "termcolor" -version = "1.1.3" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" dependencies = [ "winapi-util", ] [[package]] name = "thiserror" -version = "1.0.38" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0" +checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.38" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f" +checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" dependencies = [ "proc-macro2", "quote", - "syn 1.0.107", + "syn", ] [[package]] name = "tokio" -version = "1.24.2" +version = "1.38.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a12a59981d9e3c38d216785b0c37399f6e415e8d0712047620f189371b0bb" +checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a" dependencies = [ - "autocfg", + "backtrace", "bytes", "libc", - "memchr", "mio", "num_cpus", "parking_lot", @@ -711,25 +875,25 @@ dependencies = [ "signal-hook-registry", "socket2", "tokio-macros", - "windows-sys 0.42.0", + "windows-sys 0.48.0", ] [[package]] name = "tokio-macros" -version = "1.8.2" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d266c00fde287f55d3f1c3e96c500c362a2b8c695076ec180f27918820bc6df8" +checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" dependencies = [ "proc-macro2", "quote", - "syn 1.0.107", + "syn", ] [[package]] name = "tokio-stream" -version = "0.1.11" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d660770404473ccd7bc9f8b28494a811bc18542b915c0855c51e8f419d5223ce" +checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" dependencies = [ "futures-core", "pin-project-lite", @@ -747,6 +911,18 @@ dependencies = [ "udev", ] +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "ucd-trie" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" + [[package]] name = "udev" version = "0.7.0" @@ -760,15 +936,21 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.6" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "utf8parse" -version = "0.2.1" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "version_check" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "wasi" @@ -794,11 +976,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.5" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" dependencies = [ - "winapi", + "windows-sys 0.52.0", ] [[package]] @@ -809,17 +991,11 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-sys" -version = "0.42.0" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows_aarch64_gnullvm 0.42.0", - "windows_aarch64_msvc 0.42.0", - "windows_i686_gnu 0.42.0", - "windows_i686_msvc 0.42.0", - "windows_x86_64_gnu 0.42.0", - "windows_x86_64_gnullvm 0.42.0", - "windows_x86_64_msvc 0.42.0", + "windows-targets 0.48.5", ] [[package]] @@ -828,107 +1004,129 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets", + "windows-targets 0.52.5", ] [[package]] name = "windows-targets" -version = "0.52.4" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ - "windows_aarch64_gnullvm 0.52.4", - "windows_aarch64_msvc 0.52.4", - "windows_i686_gnu 0.52.4", - "windows_i686_msvc 0.52.4", - "windows_x86_64_gnu 0.52.4", - "windows_x86_64_gnullvm 0.52.4", - "windows_x86_64_msvc 0.52.4", + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +dependencies = [ + "windows_aarch64_gnullvm 0.52.5", + "windows_aarch64_msvc 0.52.5", + "windows_i686_gnu 0.52.5", + "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", ] [[package]] name = "windows_aarch64_gnullvm" -version = "0.42.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" [[package]] name = "windows_aarch64_msvc" -version = "0.42.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" [[package]] name = "windows_i686_gnu" -version = "0.42.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.4" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" [[package]] name = "windows_i686_msvc" -version = "0.42.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" [[package]] name = "windows_x86_64_gnu" -version = "0.42.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" [[package]] name = "windows_x86_64_gnullvm" -version = "0.42.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" [[package]] name = "windows_x86_64_msvc" -version = "0.42.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" [[package]] name = "wyz" diff --git a/swhkd/Cargo.toml b/swhkd/Cargo.toml index d9fc31e..cb6370a 100644 --- a/swhkd/Cargo.toml +++ b/swhkd/Cargo.toml @@ -21,6 +21,7 @@ log = "0.4.14" nix = "0.23.1" signal-hook = "0.3.13" signal-hook-tokio = { version = "0.3.1", features = ["futures-v0_3"] } +sweet = { git = "https://github.com/lavafroth/sweet.git", version = "0.1.0" } sysinfo = "0.23.5" tokio = { version = "1.24.2", features = ["full"] } tokio-stream = "0.1.8" diff --git a/swhkd/src/config.rs b/swhkd/src/config.rs index 1923a58..db54b51 100644 --- a/swhkd/src/config.rs +++ b/swhkd/src/config.rs @@ -5,6 +5,8 @@ use std::{ fmt, path::{Path, PathBuf}, }; +use sweet::token::KeyAttribute; +use sweet::SwhkdParser; #[derive(Debug)] pub enum Error { @@ -67,80 +69,10 @@ pub const MODE_ESCAPE_STATEMENT: &str = "@escape"; pub const MODE_SWALLOW_STATEMENT: &str = "swallow"; pub const MODE_ONEOFF_STATEMENT: &str = "oneoff"; -#[derive(Debug, PartialEq, Clone, Eq)] -pub struct Config { - pub path: PathBuf, - pub contents: String, - pub imports: Vec, -} - -impl Config { - pub fn get_imports(contents: &str) -> Result, Error> { - let mut imports = Vec::new(); - for line in contents.lines() { - if line.split(' ').next().unwrap() == IMPORT_STATEMENT { - if let Some(import_path) = line.split(' ').nth(1) { - imports.push(Path::new(import_path).to_path_buf()); - } - } - } - Ok(imports) - } - - pub fn new(path: &Path) -> Result { - let contents = fs::read_to_string(path)?; - let imports = Self::get_imports(&contents)?; - Ok(Config { path: path.to_path_buf(), contents, imports }) - } - - pub fn load_to_configs(&self) -> Result, Error> { - let mut configs = Vec::new(); - for import in &self.imports { - configs.push(Self::new(import)?) - } - Ok(configs) - } - - pub fn load_and_merge(config: Self) -> Result, Error> { - let mut configs = vec![config]; - let mut prev_count = 0; - let mut current_count = configs.len(); - while prev_count != current_count { - prev_count = configs.len(); - for config in configs.clone() { - for import in Self::load_to_configs(&config)? { - if !configs.contains(&import) { - configs.push(import); - } - } - } - current_count = configs.len(); - } - Ok(configs) - } -} - pub fn load(path: &Path) -> Result, Error> { - let config_self = Config::new(path)?; - let mut configs: Vec = Config::load_and_merge(config_self.clone())?; - configs.remove(0); - configs.push(config_self); + let config_self = sweet::SwhkdParser::from(sweet::ParserInput::Path(path)).unwrap(); let mut modes: Vec = vec![Mode::default()]; - for config in configs { - let mut output = parse_contents(path.to_path_buf(), config.contents)?; - for hotkey in output[0].hotkeys.drain(..) { - modes[0].hotkeys.retain(|hk| hk.keybinding != hotkey.keybinding); - modes[0].hotkeys.push(hotkey); - } - for unbind in output[0].unbinds.drain(..) { - modes[0].hotkeys.retain(|hk| hk.keybinding != unbind); - } - output.remove(0); - for mut mode in output { - mode.hotkeys.retain(|x| !mode.unbinds.contains(&x.keybinding)); - modes.push(mode); - } - } + let mut output = parse_contents(config_self)?; Ok(modes) } @@ -262,7 +194,7 @@ impl Value for &Hotkey { } } -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, Default)] pub struct Mode { pub name: String, pub hotkeys: Vec, @@ -286,7 +218,7 @@ impl Mode { } } -pub fn parse_contents(path: PathBuf, contents: String) -> Result, Error> { +pub fn parse_contents(contents: SwhkdParser) -> Result, Error> { // Don't forget to update valid key list on the man page if you do change this list. let key_to_evdev_key: HashMap<&str, evdev::Key> = HashMap::from([ ("q", evdev::Key::KEY_Q), @@ -451,145 +383,74 @@ pub fn parse_contents(path: PathBuf, contents: String) -> Result, Erro ("any", Modifier::Any), ]); - let lines: Vec<&str> = contents.split('\n').collect(); let mut modes: Vec = vec![Mode::default()]; let mut current_mode: usize = 0; - // Go through each line, ignore comments and empty lines, mark lines starting with whitespace - // as commands, and mark the other lines as keysyms. Mark means storing a line's type and the - // line number in a vector. - let mut lines_with_types: Vec<(&str, u32)> = Vec::new(); - for (line_number, line) in lines.iter().enumerate() { - if line.trim().starts_with('#') - || line.split(' ').next().unwrap() == IMPORT_STATEMENT - || line.trim().is_empty() - { - continue; - } - if line.starts_with(' ') || line.starts_with('\t') { - lines_with_types.push(("command", line_number as u32)); - } else if line.starts_with(UNBIND_STATEMENT) { - lines_with_types.push(("unbind", line_number as u32)); - } else if line.starts_with(MODE_STATEMENT) { - lines_with_types.push(("modestart", line_number as u32)); - } else if line.starts_with(MODE_END_STATEMENT) { - lines_with_types.push(("modeend", line_number as u32)); - } else { - lines_with_types.push(("keysym", line_number as u32)); - } - } - - // Edge case: return a blank vector if no lines detected - if lines_with_types.is_empty() { - return Ok(modes); - } - - let mut actual_lines: Vec<(&str, u32, String)> = Vec::new(); - - if contents.contains('\\') { - // Go through lines_with_types, and add the next line over and over until the current line no - // longer ends with backslash. (Only if the lines have the same type) - let mut current_line_type = lines_with_types[0].0; - let mut current_line_number = lines_with_types[0].1; - let mut current_line_string = String::new(); - let mut continue_backslash; - - for (line_type, line_number) in lines_with_types { - if line_type != current_line_type { - current_line_type = line_type; - current_line_number = line_number; - current_line_string = String::new(); - } - - let line_to_add = lines[line_number as usize].trim(); - continue_backslash = line_to_add.ends_with('\\'); - - let line_to_add = line_to_add.strip_suffix('\\').unwrap_or(line_to_add); - - current_line_string.push_str(line_to_add); - - if !continue_backslash { - actual_lines.push((current_line_type, current_line_number, current_line_string)); - current_line_type = line_type; - current_line_number = line_number; - current_line_string = String::new(); - } - } - } else { - for (line_type, line_number) in lines_with_types { - actual_lines.push(( - line_type, - line_number, - lines[line_number as usize].trim().to_string(), - )); - } - } - - drop(lines); - - for (i, item) in actual_lines.iter().enumerate() { - let line_type = item.0; - let line_number = item.1; - let line = &item.2; - - if line_type == "unbind" { - let to_unbind = line.trim_start_matches(UNBIND_STATEMENT).trim(); - modes[current_mode].unbinds.push(parse_keybind( - path.clone(), - to_unbind, - line_number + 1, - &key_to_evdev_key, - &mod_to_mod_enum, - )?); - } - - if line_type == "modestart" { - let tokens = line.split(' ').collect_vec(); - let modename = tokens[1]; - let mut mode = Mode::new(modename.to_string()); - mode.options.swallow = tokens.contains(&MODE_SWALLOW_STATEMENT); - mode.options.oneoff = tokens.contains(&MODE_ONEOFF_STATEMENT); - modes.push(mode); - current_mode = modes.len() - 1; - } - - if line_type == "modeend" { - current_mode = 0; - } - - if line_type != "keysym" { - continue; - } - - let next_line = actual_lines.get(i + 1); - if next_line.is_none() { - break; - } - let next_line = next_line.unwrap(); - - if next_line.0 != "command" { - continue; // this should ignore keysyms that are not followed by a command - } - - let extracted_keys = extract_curly_brace(line); - let extracted_commands = extract_curly_brace(&next_line.2); - - for (key, command) in extracted_keys.iter().zip(extracted_commands.iter()) { - let keybinding = parse_keybind( - path.clone(), - key, - line_number + 1, - &key_to_evdev_key, - &mod_to_mod_enum, - )?; - let hotkey = Hotkey::from_keybinding(keybinding, command.to_string()); - - // Override latter - modes[current_mode].hotkeys.retain(|h| h.keybinding != hotkey.keybinding); - modes[current_mode].hotkeys.push(hotkey); + for binding in &contents.bindings { + let keysym = key_to_evdev_key + .get(binding.definition.key.key.to_lowercase().as_str()) + .cloned() + .unwrap(); + let modifiers = binding + .definition + .modifiers + .iter() + .map(|sweet::token::Modifier(modifier)| { + mod_to_mod_enum.get(modifier.to_lowercase().as_str()).cloned().unwrap() + }) + .collect(); + let send = binding.definition.key.attribute == KeyAttribute::Send; + let on_release = binding.definition.key.attribute == KeyAttribute::OnRelease; + modes[current_mode].hotkeys.push(Hotkey { + keybinding: KeyBinding { keysym, modifiers, send, on_release }, + command: binding.command.clone(), + }); + } + for unbind in contents.unbinds { + let keysym = key_to_evdev_key.get(unbind.key.key.to_lowercase().as_str()).cloned().unwrap(); + let modifiers = unbind + .modifiers + .iter() + .map(|sweet::token::Modifier(modifier)| { + mod_to_mod_enum.get(modifier.to_lowercase().as_str()).cloned().unwrap() + }) + .collect(); + let send = unbind.key.attribute == KeyAttribute::Send; + let on_release = unbind.key.attribute == KeyAttribute::OnRelease; + modes[current_mode].unbinds.push(KeyBinding { keysym, modifiers, send, on_release }); + } + + // shadowing current_mode + for mode in contents.modes.iter() { + let mut pushmode = Mode { + name: mode.name.clone(), + options: ModeOptions { swallow: mode.swallow, oneoff: mode.oneoff }, + ..Default::default() + }; + for binding in &contents.bindings { + let keysym = key_to_evdev_key + .get(binding.definition.key.key.to_lowercase().as_str()) + .cloned() + .unwrap(); + let modifiers = binding + .definition + .modifiers + .iter() + .map(|sweet::token::Modifier(modifier)| { + mod_to_mod_enum.get(modifier.to_lowercase().as_str()).cloned().unwrap() + }) + .collect(); + let send = binding.definition.key.attribute == KeyAttribute::Send; + let on_release = binding.definition.key.attribute == KeyAttribute::OnRelease; + let hotkey = Hotkey { + keybinding: KeyBinding { keysym, modifiers, send, on_release }, + command: binding.command.clone(), + }; + pushmode.hotkeys.retain(|h| h.keybinding != hotkey.keybinding); + pushmode.hotkeys.push(hotkey); } + modes.push(pushmode); } - Ok(modes) } From 3ea47512a67eee4544f9ec482fbdfded9ad31e69 Mon Sep 17 00:00:00 2001 From: Himadri Bhattacharjee <107522312+lavafroth@users.noreply.github.com> Date: Wed, 26 Jun 2024 10:42:38 +0530 Subject: [PATCH 02/11] refactor: remove redundant code, offloading work to parser crate --- swhkd/src/config.rs | 329 ++++++++------------------------------------ 1 file changed, 57 insertions(+), 272 deletions(-) diff --git a/swhkd/src/config.rs b/swhkd/src/config.rs index db54b51..0d4b908 100644 --- a/swhkd/src/config.rs +++ b/swhkd/src/config.rs @@ -1,12 +1,10 @@ -use itertools::Itertools; use std::collections::HashMap; -use std::fs; use std::{ fmt, path::{Path, PathBuf}, }; use sweet::token::KeyAttribute; -use sweet::SwhkdParser; +use sweet::{Definition, SwhkdParser}; #[derive(Debug)] pub enum Error { @@ -60,20 +58,13 @@ impl fmt::Display for Error { } } -pub const IMPORT_STATEMENT: &str = "include"; -pub const UNBIND_STATEMENT: &str = "ignore"; -pub const MODE_STATEMENT: &str = "mode"; -pub const MODE_END_STATEMENT: &str = "endmode"; +/// TODO: implement these in the parser crate pub const MODE_ENTER_STATEMENT: &str = "@enter"; pub const MODE_ESCAPE_STATEMENT: &str = "@escape"; -pub const MODE_SWALLOW_STATEMENT: &str = "swallow"; -pub const MODE_ONEOFF_STATEMENT: &str = "oneoff"; pub fn load(path: &Path) -> Result, Error> { let config_self = sweet::SwhkdParser::from(sweet::ParserInput::Path(path)).unwrap(); - let mut modes: Vec = vec![Mode::default()]; - let mut output = parse_contents(config_self)?; - Ok(modes) + parse_contents(config_self) } #[derive(Debug, Clone)] @@ -194,7 +185,7 @@ impl Value for &Hotkey { } } -#[derive(Debug, Clone, PartialEq, Default)] +#[derive(Debug, Clone, PartialEq)] pub struct Mode { pub name: String, pub hotkeys: Vec, @@ -202,23 +193,61 @@ pub struct Mode { pub options: ModeOptions, } +impl Default for Mode { + fn default() -> Self { + Self { + name: "normal".to_string(), + hotkeys: vec![], + unbinds: vec![], + options: ModeOptions::default(), + } + } +} + #[derive(Debug, Clone, PartialEq, Default)] pub struct ModeOptions { pub swallow: bool, pub oneoff: bool, } -impl Mode { - pub fn new(name: String) -> Self { - Self { name, hotkeys: Vec::new(), unbinds: Vec::new(), options: ModeOptions::default() } +pub fn parse_contents(contents: SwhkdParser) -> Result, Error> { + let mut default_mode = Mode::default(); + + for binding in &contents.bindings { + default_mode.hotkeys.push(Hotkey { + keybinding: sweet_def_to_kb(&binding.definition), + command: binding.command.clone(), + }); + } + for unbind in contents.unbinds { + default_mode.unbinds.push(sweet_def_to_kb(&unbind)); } - pub fn default() -> Self { - Self::new("normal".to_string()) + let mut modes = vec![default_mode]; + + for sweet::Mode { name, oneoff, swallow, bindings, unbinds } in contents.modes { + let mut pushmode = + Mode { name, options: ModeOptions { swallow, oneoff }, ..Default::default() }; + for binding in bindings { + let hotkey = Hotkey { + keybinding: sweet_def_to_kb(&binding.definition), + command: binding.command, + }; + pushmode.hotkeys.retain(|h| h.keybinding != hotkey.keybinding); + pushmode.hotkeys.push(hotkey); + } + for unbind in unbinds { + pushmode.unbinds.push(sweet_def_to_kb(&unbind)); + } + modes.push(pushmode); } + Ok(modes) } -pub fn parse_contents(contents: SwhkdParser) -> Result, Error> { +/// This is a temporary function as glue code between +/// the SWEET parser and the structures here. +/// TODO: Bake this into the parser itself. +fn sweet_def_to_kb(def: &Definition) -> KeyBinding { // Don't forget to update valid key list on the man page if you do change this list. let key_to_evdev_key: HashMap<&str, evdev::Key> = HashMap::from([ ("q", evdev::Key::KEY_Q), @@ -383,259 +412,15 @@ pub fn parse_contents(contents: SwhkdParser) -> Result, Error> { ("any", Modifier::Any), ]); - let mut modes: Vec = vec![Mode::default()]; - let mut current_mode: usize = 0; - - for binding in &contents.bindings { - let keysym = key_to_evdev_key - .get(binding.definition.key.key.to_lowercase().as_str()) - .cloned() - .unwrap(); - let modifiers = binding - .definition - .modifiers - .iter() - .map(|sweet::token::Modifier(modifier)| { - mod_to_mod_enum.get(modifier.to_lowercase().as_str()).cloned().unwrap() - }) - .collect(); - let send = binding.definition.key.attribute == KeyAttribute::Send; - let on_release = binding.definition.key.attribute == KeyAttribute::OnRelease; - modes[current_mode].hotkeys.push(Hotkey { - keybinding: KeyBinding { keysym, modifiers, send, on_release }, - command: binding.command.clone(), - }); - } - for unbind in contents.unbinds { - let keysym = key_to_evdev_key.get(unbind.key.key.to_lowercase().as_str()).cloned().unwrap(); - let modifiers = unbind - .modifiers - .iter() - .map(|sweet::token::Modifier(modifier)| { - mod_to_mod_enum.get(modifier.to_lowercase().as_str()).cloned().unwrap() - }) - .collect(); - let send = unbind.key.attribute == KeyAttribute::Send; - let on_release = unbind.key.attribute == KeyAttribute::OnRelease; - modes[current_mode].unbinds.push(KeyBinding { keysym, modifiers, send, on_release }); - } - - // shadowing current_mode - for mode in contents.modes.iter() { - let mut pushmode = Mode { - name: mode.name.clone(), - options: ModeOptions { swallow: mode.swallow, oneoff: mode.oneoff }, - ..Default::default() - }; - for binding in &contents.bindings { - let keysym = key_to_evdev_key - .get(binding.definition.key.key.to_lowercase().as_str()) - .cloned() - .unwrap(); - let modifiers = binding - .definition - .modifiers - .iter() - .map(|sweet::token::Modifier(modifier)| { - mod_to_mod_enum.get(modifier.to_lowercase().as_str()).cloned().unwrap() - }) - .collect(); - let send = binding.definition.key.attribute == KeyAttribute::Send; - let on_release = binding.definition.key.attribute == KeyAttribute::OnRelease; - let hotkey = Hotkey { - keybinding: KeyBinding { keysym, modifiers, send, on_release }, - command: binding.command.clone(), - }; - pushmode.hotkeys.retain(|h| h.keybinding != hotkey.keybinding); - pushmode.hotkeys.push(hotkey); - } - modes.push(pushmode); - } - Ok(modes) -} - -// We need to get the reference to key_to_evdev_key -// and mod_to_mod enum instead of recreating them -// after each function call because it's too expensive -fn parse_keybind( - path: PathBuf, - line: &str, - line_nr: u32, - key_to_evdev_key: &HashMap<&str, evdev::Key>, - mod_to_mod_enum: &HashMap<&str, Modifier>, -) -> Result { - let line = line.split('#').next().unwrap(); - let tokens: Vec = - line.split('+').map(|s| s.trim().to_lowercase()).filter(|s| s != "_").collect(); - - let mut tokens_new = Vec::new(); - for mut token in tokens { - while token.trim().starts_with('_') { - token = token.trim().strip_prefix('_').unwrap().to_string(); - } - tokens_new.push(token.trim().to_string()); - } - - let last_token = tokens_new.last().unwrap().trim(); - - // Check if last_token is prefixed with @ or ~ or even both. - // If prefixed @, on_release = true; if prefixed ~, send = true - let send = last_token.starts_with('~') || last_token.starts_with("@~"); - let on_release = last_token.starts_with('@') || last_token.starts_with("~@"); - - // Delete the @ and ~ in the last token - fn strip_at(token: &str) -> &str { - token.trim_start_matches(['@', '~']) - } - - let last_token = strip_at(last_token); - let tokens_no_at: Vec<_> = tokens_new.iter().map(|token| strip_at(token)).collect(); - - // Check if each token is valid - for token in &tokens_no_at { - if key_to_evdev_key.contains_key(token) { - // Can't have a keysym that's like a modifier - if *token != last_token { - return Err(Error::InvalidConfig(ParseError::InvalidModifier(path, line_nr))); - } - } else if mod_to_mod_enum.contains_key(token) { - // Can't have a modifier that's like a keysym - if *token == last_token { - return Err(Error::InvalidConfig(ParseError::InvalidKeysym(path, line_nr))); - } - } else { - return Err(Error::InvalidConfig(ParseError::UnknownSymbol(path, line_nr))); - } - } - - // Translate keypress into evdev key - let keysym = key_to_evdev_key.get(last_token).unwrap(); - - let modifiers: Vec = tokens_no_at[0..(tokens_no_at.len() - 1)] + let keysym = key_to_evdev_key.get(def.key.key.to_lowercase().as_str()).cloned().unwrap(); + let modifiers = def + .modifiers .iter() - .map(|token| *mod_to_mod_enum.get(token).unwrap()) + .map(|sweet::token::Modifier(modifier)| { + mod_to_mod_enum.get(modifier.to_lowercase().as_str()).cloned().unwrap() + }) .collect(); - - let mut keybinding = KeyBinding::new(*keysym, modifiers); - if send { - keybinding = keybinding.send(); - } - if on_release { - keybinding = keybinding.on_release(); - } - Ok(keybinding) -} - -pub fn extract_curly_brace(line: &str) -> Vec { - if !line.contains('{') || !line.contains('}') || !line.is_ascii() { - return vec![line.to_string()]; - } - - // go through each character in the line and mark the position of each { and } - // if a { is not followed by a }, return the line as is - let mut brace_positions: Vec = Vec::new(); - let mut flag = false; - for (i, c) in line.chars().enumerate() { - if c == '{' { - if flag { - return vec![line.to_string()]; - } - brace_positions.push(i); - flag = true; - } else if c == '}' { - if !flag { - return vec![line.to_string()]; - } - brace_positions.push(i); - flag = false; - } - } - - // now we have a list of positions of { and } - // we should extract the items between each pair of braces and store them in a vector - let mut items: Vec = Vec::new(); - let mut remaining_line: Vec = Vec::new(); - let mut start_index = 0; - for i in brace_positions.chunks(2) { - items.push(line[i[0] + 1..i[1]].to_string()); - remaining_line.push(line[start_index..i[0]].to_string()); - start_index = i[1] + 1; - } - - // now we have a list of items between each pair of braces - // we should extract the items between each comma and store them in a vector - let mut tokens_vec: Vec> = Vec::new(); - for item in items { - // Edge case: escape periods - // example: - // ``` - // super + {\,, .} - // riverctl focus-output {previous, next} - // ``` - let item = item.replace("\\,", "comma"); - - let items: Vec = item.split(',').map(|s| s.trim().to_string()).collect(); - tokens_vec.push(handle_ranges(items)); - } - - fn handle_ranges(items: Vec) -> Vec { - let mut output: Vec = Vec::new(); - for item in items { - if !item.contains('-') { - output.push(item); - continue; - } - let mut range = item.split('-').map(|s| s.trim()); - - let begin_char: &str = if let Some(b) = range.next() { - b - } else { - output.push(item); - continue; - }; - - let end_char: &str = if let Some(e) = range.next() { - e - } else { - output.push(item); - continue; - }; - - // Do not accept range values that are longer than one char - // Example invalid: {ef-p} {3-56} - // Beginning of the range cannot be greater than end - // Example invalid: {9-4} {3-2} - if begin_char.len() != 1 || end_char.len() != 1 || begin_char > end_char { - output.push(item); - continue; - } - - // In swhkd we will parse the full range using ASCII values. - - let begin_ascii_val = begin_char.parse::().unwrap() as u8; - let end_ascii_val = end_char.parse::().unwrap() as u8; - - for ascii_number in begin_ascii_val..=end_ascii_val { - output.push((ascii_number as char).to_string()); - } - } - output - } - - // now write the tokens back to the line and output a vector - let mut output: Vec = Vec::new(); - // generate a cartesian product iterator for all the vectors in tokens_vec - let cartesian_product_iter = tokens_vec.iter().multi_cartesian_product(); - for tokens in cartesian_product_iter.collect_vec() { - let mut line_to_push = String::new(); - for i in 0..remaining_line.len() { - line_to_push.push_str(&remaining_line[i]); - line_to_push.push_str(tokens[i]); - } - if brace_positions[brace_positions.len() - 1] < line.len() - 1 { - line_to_push.push_str(&line[brace_positions[brace_positions.len() - 1] + 1..]); - } - output.push(line_to_push); - } - output + let send = def.key.attribute == KeyAttribute::Send; + let on_release = def.key.attribute == KeyAttribute::OnRelease; + KeyBinding { keysym, modifiers, send, on_release } } From ebd4cd30a21ec34d36cbf3e74576b7c1661d4317 Mon Sep 17 00:00:00 2001 From: Himadri Bhattacharjee <107522312+lavafroth@users.noreply.github.com> Date: Sat, 29 Jun 2024 18:00:21 +0530 Subject: [PATCH 03/11] feat: move modifier validation to parser --- Cargo.lock | 27 ++--- flake.lock | 6 +- swhkd/src/config.rs | 240 +++----------------------------------------- 3 files changed, 31 insertions(+), 242 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b75efa8..ec1453e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -174,9 +174,9 @@ checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" [[package]] name = "cc" -version = "1.0.101" +version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac367972e516d45567c7eafc73d24e1c193dcf200a8d94e9db7b3d38b349572d" +checksum = "779e6b7d17797c0b42023d417228c02889300190e700cb074c3438d9c541d332" [[package]] name = "cfg-if" @@ -186,9 +186,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "4.5.7" +version = "4.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5db83dced34638ad474f39f250d7fea9598bdd239eaced1bdf45d597da0f433f" +checksum = "84b3edb18336f4df585bc9aa31dd99c036dfa5dc5e9a2939a722a188f3a8970d" dependencies = [ "clap_builder", "clap_derive", @@ -196,9 +196,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.7" +version = "4.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7e204572485eb3fbf28f871612191521df159bc3e15a9f5064c66dba3a8c05f" +checksum = "c1c09dd5ada6c6c78075d6fd0da3f90d8080651e2d6cc8eb2f1aaa4034ced708" dependencies = [ "anstream", "anstyle", @@ -208,9 +208,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.5" +version = "4.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c780290ccf4fb26629baa7a1081e68ced113f1d3ec302fa5948f1c381ebf06c6" +checksum = "2bac35c6dafb060fd4d275d9a4ffae97917c13a6327903a8be2153cd964f7085" dependencies = [ "heck", "proc-macro2", @@ -450,9 +450,9 @@ 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 = "memchr" @@ -523,9 +523,9 @@ dependencies = [ [[package]] name = "object" -version = "0.36.0" +version = "0.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "576dfe1fc8f9df304abb159d767a29d0476f7750fbf8aa7ad07816004a207434" +checksum = "081b846d1d56ddfc18fdf1a922e4f6e07a11768ea1b92dec44e42b72712ccfce" dependencies = [ "memchr", ] @@ -777,10 +777,11 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "sweet" version = "0.1.0" -source = "git+https://github.com/lavafroth/sweet.git#361be3320068c21ad4db4a6ea7831ab3ad1aeacd" +source = "git+https://github.com/lavafroth/sweet.git#30e44f4f1a765507203a9b5e869893d7422f3130" dependencies = [ "anyhow", "bitflags 2.6.0", + "evdev", "itertools 0.12.1", "pest", "pest_derive", diff --git a/flake.lock b/flake.lock index 900ef5a..b80c063 100644 --- a/flake.lock +++ b/flake.lock @@ -2,11 +2,11 @@ "nodes": { "nixpkgs": { "locked": { - "lastModified": 1687977148, - "narHash": "sha256-gUcXiU2GgjYIc65GOIemdBJZ+lkQxuyIh7OkR9j0gCo=", + "lastModified": 1715499532, + "narHash": "sha256-9UJLb8rdi2VokYcfOBQHUzP3iNxOPNWcbK++ENElpk0=", "owner": "nixos", "repo": "nixpkgs", - "rev": "60a783e00517fce85c42c8c53fe0ed05ded5b2a4", + "rev": "af8b9db5c00f1a8e4b83578acc578ff7d823b786", "type": "github" }, "original": { diff --git a/swhkd/src/config.rs b/swhkd/src/config.rs index 0d4b908..189d863 100644 --- a/swhkd/src/config.rs +++ b/swhkd/src/config.rs @@ -1,68 +1,13 @@ -use std::collections::HashMap; -use std::{ - fmt, - path::{Path, PathBuf}, -}; +use std::path::Path; use sweet::token::KeyAttribute; +use sweet::ParseError; use sweet::{Definition, SwhkdParser}; -#[derive(Debug)] -pub enum Error { - ConfigNotFound, - Io(std::io::Error), - InvalidConfig(ParseError), -} - -#[derive(Debug, PartialEq, Eq)] -pub enum ParseError { - // u32 is the line number where an error occured - UnknownSymbol(PathBuf, u32), - InvalidModifier(PathBuf, u32), - InvalidKeysym(PathBuf, u32), -} - -impl From for Error { - fn from(val: std::io::Error) -> Self { - if val.kind() == std::io::ErrorKind::NotFound { - Error::ConfigNotFound - } else { - Error::Io(val) - } - } -} - -impl fmt::Display for Error { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Error::ConfigNotFound => "Config file not found.".fmt(f), - - Error::Io(io_err) => format!("I/O Error while parsing config file: {}", io_err).fmt(f), - Error::InvalidConfig(parse_err) => match parse_err { - ParseError::UnknownSymbol(path, line_nr) => format!( - "Error parsing config file {:?}. Unknown symbol at line {}.", - path, line_nr - ) - .fmt(f), - ParseError::InvalidKeysym(path, line_nr) => format!( - "Error parsing config file {:?}. Invalid keysym at line {}.", - path, line_nr - ) - .fmt(f), - ParseError::InvalidModifier(path, line_nr) => format!( - "Error parsing config file {:?}. Invalid modifier at line {}.", - path, line_nr - ) - .fmt(f), - }, - } - } -} - -/// TODO: implement these in the parser crate +/// TODO: implement these in the code side of the parser crate pub const MODE_ENTER_STATEMENT: &str = "@enter"; pub const MODE_ESCAPE_STATEMENT: &str = "@escape"; -pub fn load(path: &Path) -> Result, Error> { +pub fn load(path: &Path) -> Result, ParseError> { let config_self = sweet::SwhkdParser::from(sweet::ParserInput::Path(path)).unwrap(); parse_contents(config_self) } @@ -210,7 +155,7 @@ pub struct ModeOptions { pub oneoff: bool, } -pub fn parse_contents(contents: SwhkdParser) -> Result, Error> { +pub fn parse_contents(contents: SwhkdParser) -> Result, ParseError> { let mut default_mode = Mode::default(); for binding in &contents.bindings { @@ -248,179 +193,22 @@ pub fn parse_contents(contents: SwhkdParser) -> Result, Error> { /// the SWEET parser and the structures here. /// TODO: Bake this into the parser itself. fn sweet_def_to_kb(def: &Definition) -> KeyBinding { - // Don't forget to update valid key list on the man page if you do change this list. - let key_to_evdev_key: HashMap<&str, evdev::Key> = HashMap::from([ - ("q", evdev::Key::KEY_Q), - ("w", evdev::Key::KEY_W), - ("e", evdev::Key::KEY_E), - ("r", evdev::Key::KEY_R), - ("t", evdev::Key::KEY_T), - ("y", evdev::Key::KEY_Y), - ("u", evdev::Key::KEY_U), - ("i", evdev::Key::KEY_I), - ("o", evdev::Key::KEY_O), - ("p", evdev::Key::KEY_P), - ("a", evdev::Key::KEY_A), - ("s", evdev::Key::KEY_S), - ("d", evdev::Key::KEY_D), - ("f", evdev::Key::KEY_F), - ("g", evdev::Key::KEY_G), - ("h", evdev::Key::KEY_H), - ("j", evdev::Key::KEY_J), - ("k", evdev::Key::KEY_K), - ("l", evdev::Key::KEY_L), - ("z", evdev::Key::KEY_Z), - ("x", evdev::Key::KEY_X), - ("c", evdev::Key::KEY_C), - ("v", evdev::Key::KEY_V), - ("b", evdev::Key::KEY_B), - ("n", evdev::Key::KEY_N), - ("m", evdev::Key::KEY_M), - ("1", evdev::Key::KEY_1), - ("2", evdev::Key::KEY_2), - ("3", evdev::Key::KEY_3), - ("4", evdev::Key::KEY_4), - ("5", evdev::Key::KEY_5), - ("6", evdev::Key::KEY_6), - ("7", evdev::Key::KEY_7), - ("8", evdev::Key::KEY_8), - ("9", evdev::Key::KEY_9), - ("0", evdev::Key::KEY_0), - ("escape", evdev::Key::KEY_ESC), - ("backspace", evdev::Key::KEY_BACKSPACE), - ("capslock", evdev::Key::KEY_CAPSLOCK), - ("return", evdev::Key::KEY_ENTER), - ("enter", evdev::Key::KEY_ENTER), - ("tab", evdev::Key::KEY_TAB), - ("space", evdev::Key::KEY_SPACE), - ("plus", evdev::Key::KEY_KPPLUS), // Shouldn't this be kpplus? - ("kp0", evdev::Key::KEY_KP0), - ("kp1", evdev::Key::KEY_KP1), - ("kp2", evdev::Key::KEY_KP2), - ("kp3", evdev::Key::KEY_KP3), - ("kp4", evdev::Key::KEY_KP4), - ("kp5", evdev::Key::KEY_KP5), - ("kp6", evdev::Key::KEY_KP6), - ("kp7", evdev::Key::KEY_KP7), - ("kp8", evdev::Key::KEY_KP8), - ("kp9", evdev::Key::KEY_KP9), - ("kpasterisk", evdev::Key::KEY_KPASTERISK), - ("kpcomma", evdev::Key::KEY_KPCOMMA), - ("kpdot", evdev::Key::KEY_KPDOT), - ("kpenter", evdev::Key::KEY_KPENTER), - ("kpequal", evdev::Key::KEY_KPEQUAL), - ("kpjpcomma", evdev::Key::KEY_KPJPCOMMA), - ("kpleftparen", evdev::Key::KEY_KPLEFTPAREN), - ("kpminus", evdev::Key::KEY_KPMINUS), - ("kpplusminus", evdev::Key::KEY_KPPLUSMINUS), - ("kprightparen", evdev::Key::KEY_KPRIGHTPAREN), - ("minus", evdev::Key::KEY_MINUS), - ("-", evdev::Key::KEY_MINUS), - ("equal", evdev::Key::KEY_EQUAL), - ("=", evdev::Key::KEY_EQUAL), - ("grave", evdev::Key::KEY_GRAVE), - ("`", evdev::Key::KEY_GRAVE), - ("print", evdev::Key::KEY_SYSRQ), - ("volumeup", evdev::Key::KEY_VOLUMEUP), - ("xf86audioraisevolume", evdev::Key::KEY_VOLUMEUP), - ("volumedown", evdev::Key::KEY_VOLUMEDOWN), - ("xf86audiolowervolume", evdev::Key::KEY_VOLUMEDOWN), - ("mute", evdev::Key::KEY_MUTE), - ("xf86audiomute", evdev::Key::KEY_MUTE), - ("brightnessup", evdev::Key::KEY_BRIGHTNESSUP), - ("xf86monbrightnessup", evdev::Key::KEY_BRIGHTNESSUP), - ("brightnessdown", evdev::Key::KEY_BRIGHTNESSDOWN), - ("xf86audiomedia", evdev::Key::KEY_MEDIA), - ("xf86audiomicmute", evdev::Key::KEY_MICMUTE), - ("micmute", evdev::Key::KEY_MICMUTE), - ("xf86audionext", evdev::Key::KEY_NEXTSONG), - ("xf86audioplay", evdev::Key::KEY_PLAYPAUSE), - ("xf86audioprev", evdev::Key::KEY_PREVIOUSSONG), - ("xf86audiostop", evdev::Key::KEY_STOP), - ("xf86monbrightnessdown", evdev::Key::KEY_BRIGHTNESSDOWN), - (",", evdev::Key::KEY_COMMA), - ("comma", evdev::Key::KEY_COMMA), - (".", evdev::Key::KEY_DOT), - ("dot", evdev::Key::KEY_DOT), - ("period", evdev::Key::KEY_DOT), - ("/", evdev::Key::KEY_SLASH), - ("question", evdev::Key::KEY_QUESTION), - ("slash", evdev::Key::KEY_SLASH), - ("backslash", evdev::Key::KEY_BACKSLASH), - ("leftbrace", evdev::Key::KEY_LEFTBRACE), - ("[", evdev::Key::KEY_LEFTBRACE), - ("bracketleft", evdev::Key::KEY_LEFTBRACE), - ("rightbrace", evdev::Key::KEY_RIGHTBRACE), - ("]", evdev::Key::KEY_RIGHTBRACE), - ("bracketright", evdev::Key::KEY_RIGHTBRACE), - (";", evdev::Key::KEY_SEMICOLON), - ("scroll_lock", evdev::Key::KEY_SCROLLLOCK), - ("semicolon", evdev::Key::KEY_SEMICOLON), - ("'", evdev::Key::KEY_APOSTROPHE), - ("apostrophe", evdev::Key::KEY_APOSTROPHE), - ("left", evdev::Key::KEY_LEFT), - ("right", evdev::Key::KEY_RIGHT), - ("up", evdev::Key::KEY_UP), - ("down", evdev::Key::KEY_DOWN), - ("pause", evdev::Key::KEY_PAUSE), - ("home", evdev::Key::KEY_HOME), - ("delete", evdev::Key::KEY_DELETE), - ("insert", evdev::Key::KEY_INSERT), - ("end", evdev::Key::KEY_END), - ("pause", evdev::Key::KEY_PAUSE), - ("prior", evdev::Key::KEY_PAGEDOWN), - ("next", evdev::Key::KEY_PAGEUP), - ("pagedown", evdev::Key::KEY_PAGEDOWN), - ("pageup", evdev::Key::KEY_PAGEUP), - ("f1", evdev::Key::KEY_F1), - ("f2", evdev::Key::KEY_F2), - ("f3", evdev::Key::KEY_F3), - ("f4", evdev::Key::KEY_F4), - ("f5", evdev::Key::KEY_F5), - ("f6", evdev::Key::KEY_F6), - ("f7", evdev::Key::KEY_F7), - ("f8", evdev::Key::KEY_F8), - ("f9", evdev::Key::KEY_F9), - ("f10", evdev::Key::KEY_F10), - ("f11", evdev::Key::KEY_F11), - ("f12", evdev::Key::KEY_F12), - ("f13", evdev::Key::KEY_F13), - ("f14", evdev::Key::KEY_F14), - ("f15", evdev::Key::KEY_F15), - ("f16", evdev::Key::KEY_F16), - ("f17", evdev::Key::KEY_F17), - ("f18", evdev::Key::KEY_F18), - ("f19", evdev::Key::KEY_F19), - ("f20", evdev::Key::KEY_F20), - ("f21", evdev::Key::KEY_F21), - ("f22", evdev::Key::KEY_F22), - ("f23", evdev::Key::KEY_F23), - ("f24", evdev::Key::KEY_F24), - ]); - // Don't forget to update modifier list on the man page if you do change this list. - let mod_to_mod_enum: HashMap<&str, Modifier> = HashMap::from([ - ("ctrl", Modifier::Control), - ("control", Modifier::Control), - ("super", Modifier::Super), - ("mod4", Modifier::Super), - ("alt", Modifier::Alt), - ("mod1", Modifier::Alt), - ("altgr", Modifier::Altgr), - ("mod5", Modifier::Altgr), - ("shift", Modifier::Shift), - ("any", Modifier::Any), - ]); - let keysym = key_to_evdev_key.get(def.key.key.to_lowercase().as_str()).cloned().unwrap(); let modifiers = def .modifiers .iter() - .map(|sweet::token::Modifier(modifier)| { - mod_to_mod_enum.get(modifier.to_lowercase().as_str()).cloned().unwrap() + .map(|m| match m { + sweet::token::Modifier::Super => Modifier::Super, + sweet::token::Modifier::Any => Modifier::Any, + sweet::token::Modifier::Control => Modifier::Control, + sweet::token::Modifier::Alt => Modifier::Alt, + sweet::token::Modifier::Altgr => Modifier::Altgr, + sweet::token::Modifier::Shift => Modifier::Shift, }) .collect(); + let send = def.key.attribute == KeyAttribute::Send; let on_release = def.key.attribute == KeyAttribute::OnRelease; - KeyBinding { keysym, modifiers, send, on_release } + KeyBinding { keysym: def.key.key, modifiers, send, on_release } } From 8d169edcfcf6f89647a8fde1808d6330ac1b0848 Mon Sep 17 00:00:00 2001 From: Himadri Bhattacharjee <107522312+lavafroth@users.noreply.github.com> Date: Sat, 6 Jul 2024 14:04:18 +0530 Subject: [PATCH 04/11] feat: use readily available mode instructions from parser --- swhkd/Cargo.toml | 2 +- swhkd/src/config.rs | 13 ++++++++++--- swhkd/src/daemon.rs | 37 +++++++++++-------------------------- 3 files changed, 22 insertions(+), 30 deletions(-) diff --git a/swhkd/Cargo.toml b/swhkd/Cargo.toml index cb6370a..78a1555 100644 --- a/swhkd/Cargo.toml +++ b/swhkd/Cargo.toml @@ -21,7 +21,7 @@ log = "0.4.14" nix = "0.23.1" signal-hook = "0.3.13" signal-hook-tokio = { version = "0.3.1", features = ["futures-v0_3"] } -sweet = { git = "https://github.com/lavafroth/sweet.git", version = "0.1.0" } +sweet = { git = "https://github.com/lavafroth/sweet.git", version = "0.2.0" } sysinfo = "0.23.5" tokio = { version = "1.24.2", features = ["full"] } tokio-stream = "0.1.8" diff --git a/swhkd/src/config.rs b/swhkd/src/config.rs index 189d863..271bbb3 100644 --- a/swhkd/src/config.rs +++ b/swhkd/src/config.rs @@ -1,7 +1,7 @@ use std::path::Path; use sweet::token::KeyAttribute; -use sweet::ParseError; use sweet::{Definition, SwhkdParser}; +use sweet::{ModeInstruction, ParseError}; /// TODO: implement these in the code side of the parser crate pub const MODE_ENTER_STATEMENT: &str = "@enter"; @@ -82,6 +82,7 @@ impl Value for KeyBinding { pub struct Hotkey { pub keybinding: KeyBinding, pub command: String, + pub mode_instructions: Vec, } #[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)] @@ -96,11 +97,15 @@ pub enum Modifier { impl Hotkey { pub fn from_keybinding(keybinding: KeyBinding, command: String) -> Self { - Hotkey { keybinding, command } + Hotkey { keybinding, command, mode_instructions: vec![] } } #[cfg(test)] pub fn new(keysym: evdev::Key, modifiers: Vec, command: String) -> Self { - Hotkey { keybinding: KeyBinding::new(keysym, modifiers), command } + Hotkey { + keybinding: KeyBinding::new(keysym, modifiers), + command, + mode_instructions: vec![], + } } } @@ -162,6 +167,7 @@ pub fn parse_contents(contents: SwhkdParser) -> Result, ParseError> { default_mode.hotkeys.push(Hotkey { keybinding: sweet_def_to_kb(&binding.definition), command: binding.command.clone(), + mode_instructions: binding.mode_instructions.clone(), }); } for unbind in contents.unbinds { @@ -177,6 +183,7 @@ pub fn parse_contents(contents: SwhkdParser) -> Result, ParseError> { let hotkey = Hotkey { keybinding: sweet_def_to_kb(&binding.definition), command: binding.command, + mode_instructions: binding.mode_instructions.clone(), }; pushmode.hotkeys.retain(|h| h.keybinding != hotkey.keybinding); pushmode.hotkeys.push(hotkey); diff --git a/swhkd/src/daemon.rs b/swhkd/src/daemon.rs index 4c67f36..628223f 100644 --- a/swhkd/src/daemon.rs +++ b/swhkd/src/daemon.rs @@ -502,38 +502,23 @@ pub fn send_command( ) { log::info!("Hotkey pressed: {:#?}", hotkey); let command = hotkey.command; - let mut commands_to_send = String::new(); - if modes[mode_stack[mode_stack.len() - 1]].options.oneoff { + if modes[*mode_stack.last().unwrap()].options.oneoff { mode_stack.pop(); } - if command.contains('@') { - let commands = command.split("&&").map(|s| s.trim()).collect::>(); - for cmd in commands { - let mut words = cmd.split_whitespace(); - match words.next().unwrap() { - config::MODE_ENTER_STATEMENT => { - let enter_mode = cmd.split(' ').nth(1).unwrap(); - for (i, mode) in modes.iter().enumerate() { - if mode.name == enter_mode { - mode_stack.push(i); - break; - } - } - log::info!("Entering mode: {}", modes[mode_stack[mode_stack.len() - 1]].name); - } - config::MODE_ESCAPE_STATEMENT => { - mode_stack.pop(); + for mode in hotkey.mode_instructions.iter() { + match mode { + sweet::ModeInstruction::Enter(name) => { + if let Some(mode_index) = modes.iter().position(|modename| modename.name.eq(name)) { + mode_stack.push(mode_index); + log::info!("Entering mode: {}", name); } - _ => commands_to_send.push_str(format!("{cmd} &&").as_str()), + } + sweet::ModeInstruction::Escape => { + mode_stack.pop(); } } - } else { - commands_to_send = command; - } - if commands_to_send.ends_with(" &&") { - commands_to_send = commands_to_send.strip_suffix(" &&").unwrap().to_string(); } - if let Err(e) = socket_write(&commands_to_send, socket_path.to_path_buf()) { + if let Err(e) = socket_write(&command, socket_path.to_path_buf()) { log::error!("Failed to send command to swhks through IPC."); log::error!("Please make sure that swhks is running."); log::error!("Err: {:#?}", e) From ae2dc77b0ba48ce5652aaf51af16bc0f6dcfb3ee Mon Sep 17 00:00:00 2001 From: Himadri Bhattacharjee <107522312+lavafroth@users.noreply.github.com> Date: Sun, 14 Jul 2024 21:55:23 +0530 Subject: [PATCH 05/11] deps: bump sweet version --- swhkd/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/swhkd/Cargo.toml b/swhkd/Cargo.toml index 78a1555..30e1dd4 100644 --- a/swhkd/Cargo.toml +++ b/swhkd/Cargo.toml @@ -21,7 +21,7 @@ log = "0.4.14" nix = "0.23.1" signal-hook = "0.3.13" signal-hook-tokio = { version = "0.3.1", features = ["futures-v0_3"] } -sweet = { git = "https://github.com/lavafroth/sweet.git", version = "0.2.0" } +sweet = { git = "https://github.com/lavafroth/sweet.git", version = "0.3.0" } sysinfo = "0.23.5" tokio = { version = "1.24.2", features = ["full"] } tokio-stream = "0.1.8" From 57b79043bb96577805928341979841381d66dd3d Mon Sep 17 00:00:00 2001 From: Himadri Bhattacharjee <107522312+lavafroth@users.noreply.github.com> Date: Wed, 17 Jul 2024 07:49:40 +0530 Subject: [PATCH 06/11] chore: remove unused grammar constants --- swhkd/src/config.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/swhkd/src/config.rs b/swhkd/src/config.rs index 271bbb3..0fcf2e9 100644 --- a/swhkd/src/config.rs +++ b/swhkd/src/config.rs @@ -3,10 +3,6 @@ use sweet::token::KeyAttribute; use sweet::{Definition, SwhkdParser}; use sweet::{ModeInstruction, ParseError}; -/// TODO: implement these in the code side of the parser crate -pub const MODE_ENTER_STATEMENT: &str = "@enter"; -pub const MODE_ESCAPE_STATEMENT: &str = "@escape"; - pub fn load(path: &Path) -> Result, ParseError> { let config_self = sweet::SwhkdParser::from(sweet::ParserInput::Path(path)).unwrap(); parse_contents(config_self) From 5fc74c5e34b47e91101b2472dde9dfa4e531b1da Mon Sep 17 00:00:00 2001 From: Himadri Bhattacharjee <107522312+lavafroth@users.noreply.github.com> Date: Wed, 17 Jul 2024 07:50:10 +0530 Subject: [PATCH 07/11] docs: update docs for `sweet_def_to_kb` function --- swhkd/src/config.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/swhkd/src/config.rs b/swhkd/src/config.rs index 0fcf2e9..15b5f91 100644 --- a/swhkd/src/config.rs +++ b/swhkd/src/config.rs @@ -192,12 +192,8 @@ pub fn parse_contents(contents: SwhkdParser) -> Result, ParseError> { Ok(modes) } -/// This is a temporary function as glue code between -/// the SWEET parser and the structures here. -/// TODO: Bake this into the parser itself. +/// A small function to convert a `sweet::token::Modifier` into the local `Modifier` enum fn sweet_def_to_kb(def: &Definition) -> KeyBinding { - // Don't forget to update modifier list on the man page if you do change this list. - let modifiers = def .modifiers .iter() From 6866e6a886705b79189187c9f3fd0a5cde2bf70f Mon Sep 17 00:00:00 2001 From: Himadri Bhattacharjee <107522312+lavafroth@users.noreply.github.com> Date: Mon, 29 Jul 2024 14:42:15 +0530 Subject: [PATCH 08/11] tests: finished porting all tests --- Cargo.lock | 252 ++++----- swhkd/src/config.rs | 15 +- swhkd/src/tests.rs | 1231 ------------------------------------------- 3 files changed, 96 insertions(+), 1402 deletions(-) delete mode 100644 swhkd/src/tests.rs diff --git a/Cargo.lock b/Cargo.lock index ec1453e..379d082 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -48,9 +48,9 @@ dependencies = [ [[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", @@ -63,36 +63,36 @@ 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", + "windows-sys", ] [[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", + "windows-sys", ] [[package]] @@ -168,15 +168,15 @@ dependencies = [ [[package]] name = "bytes" -version = "1.6.0" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" +checksum = "a12916984aab3fa6e39d655a33e09c0071eb36d6ab3aea5c2d78551f1df6d952" [[package]] name = "cc" -version = "1.0.102" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "779e6b7d17797c0b42023d417228c02889300190e700cb074c3438d9c541d332" +checksum = "2aba8f4e9906c7ce3c73463f62a7f0c65183ada1a2d47e397cc8810827f9694f" [[package]] name = "cfg-if" @@ -186,9 +186,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "4.5.8" +version = "4.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84b3edb18336f4df585bc9aa31dd99c036dfa5dc5e9a2939a722a188f3a8970d" +checksum = "35723e6a11662c2afb578bcf0b88bf6ea8e21282a953428f240574fcc3a2b5b3" dependencies = [ "clap_builder", "clap_derive", @@ -196,9 +196,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.8" +version = "4.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1c09dd5ada6c6c78075d6fd0da3f90d8080651e2d6cc8eb2f1aaa4034ced708" +checksum = "49eb96cbfa7cfa35017b7cd548c75b14c3118c98b423041d70562665e07fb0fa" dependencies = [ "anstream", "anstyle", @@ -208,9 +208,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.8" +version = "4.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bac35c6dafb060fd4d275d9a4ffae97917c13a6327903a8be2153cd964f7085" +checksum = "5d029b67f89d30bbb547c89fd5161293c0aec155fc691d7924b64550662db93e" dependencies = [ "heck", "proc-macro2", @@ -220,15 +220,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 = "core-foundation-sys" @@ -400,9 +400,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[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" @@ -480,13 +480,14 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.11" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" +checksum = "4569e456d394deccd22ce1c1913e6ea0e54519f577285001215d33557431afe4" dependencies = [ + "hermit-abi 0.3.9", "libc", "wasi", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] @@ -511,21 +512,11 @@ dependencies = [ "winapi", ] -[[package]] -name = "num_cpus" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" -dependencies = [ - "hermit-abi 0.3.9", - "libc", -] - [[package]] name = "object" -version = "0.36.1" +version = "0.36.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "081b846d1d56ddfc18fdf1a922e4f6e07a11768ea1b92dec44e42b72712ccfce" +checksum = "3f203fa8daa7bb185f760ae12bd8e097f63d17041dcdcaf675ac54cdf863170e" dependencies = [ "memchr", ] @@ -556,14 +547,14 @@ dependencies = [ "libc", "redox_syscall", "smallvec", - "windows-targets 0.52.5", + "windows-targets", ] [[package]] name = "pest" -version = "2.7.10" +version = "2.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "560131c633294438da9f7c4b08189194b20946c8274c6b9e38881a7874dc8ee8" +checksum = "cd53dff83f26735fdc1ca837098ccf133605d794cdae66acfc2bfac3ec809d95" dependencies = [ "memchr", "thiserror", @@ -572,9 +563,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.7.10" +version = "2.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26293c9193fbca7b1a3bf9b79dc1e388e927e6cacaa78b4a3ab705a1d3d41459" +checksum = "2a548d2beca6773b1c244554d36fcf8548a8a58e74156968211567250e48e49a" dependencies = [ "pest", "pest_generator", @@ -582,9 +573,9 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.7.10" +version = "2.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ec22af7d3fb470a85dd2ca96b7c577a1eb4ef6f1683a9fe9a8c16e136c04687" +checksum = "3c93a82e8d145725dcbaf44e5ea887c8a869efdcc28706df2d08c69e17077183" dependencies = [ "pest", "pest_meta", @@ -595,9 +586,9 @@ dependencies = [ [[package]] name = "pest_meta" -version = "2.7.10" +version = "2.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7a240022f37c361ec1878d646fc5b7d7c4d28d5946e1a80ad5a7a4f4ca0bdcd" +checksum = "a941429fea7e08bedec25e4f6785b6ffaacc6b755da98df5ef3e7dcf4a124c4f" dependencies = [ "once_cell", "pest", @@ -662,9 +653,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c82cf8cff14456045f55ec4241383baeff27af886adb72ffb2162f99911de0fd" +checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" dependencies = [ "bitflags 2.6.0", ] @@ -765,7 +756,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys", ] [[package]] @@ -776,8 +767,8 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "sweet" -version = "0.1.0" -source = "git+https://github.com/lavafroth/sweet.git#30e44f4f1a765507203a9b5e869893d7422f3130" +version = "0.3.0" +source = "git+https://github.com/lavafroth/sweet.git#6146627ee75be8bda87dc443c2f1d153590d3610" dependencies = [ "anyhow", "bitflags 2.6.0", @@ -801,9 +792,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.68" +version = "2.0.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "901fa70d88b9d6c98022e23b4136f9f3e54e4662c3bc1bd1d84a42a9a0f0c1e9" +checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af" dependencies = [ "proc-macro2", "quote", @@ -842,18 +833,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.61" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" +checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.61" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" +checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" dependencies = [ "proc-macro2", "quote", @@ -862,28 +853,27 @@ dependencies = [ [[package]] name = "tokio" -version = "1.38.0" +version = "1.39.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a" +checksum = "daa4fb1bc778bd6f04cbfc4bb2d06a7396a8f299dc33ea1900cedaa316f467b1" dependencies = [ "backtrace", "bytes", "libc", "mio", - "num_cpus", "parking_lot", "pin-project-lite", "signal-hook-registry", "socket2", "tokio-macros", - "windows-sys 0.48.0", + "windows-sys", ] [[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", @@ -949,9 +939,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[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" @@ -981,7 +971,7 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" dependencies = [ - "windows-sys 0.52.0", + "windows-sys", ] [[package]] @@ -990,144 +980,78 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets 0.48.5", -] - [[package]] name = "windows-sys" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.5", + "windows-targets", ] [[package]] name = "windows-targets" -version = "0.48.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.48.5", - "windows_aarch64_msvc 0.48.5", - "windows_i686_gnu 0.48.5", - "windows_i686_msvc 0.48.5", - "windows_x86_64_gnu 0.48.5", - "windows_x86_64_gnullvm 0.48.5", - "windows_x86_64_msvc 0.48.5", -] - -[[package]] -name = "windows-targets" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" -dependencies = [ - "windows_aarch64_gnullvm 0.52.5", - "windows_aarch64_msvc 0.52.5", - "windows_i686_gnu 0.52.5", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", "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", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] [[package]] name = "windows_aarch64_gnullvm" -version = "0.48.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" -version = "0.48.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" -version = "0.48.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnullvm" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" - -[[package]] -name = "windows_i686_msvc" -version = "0.48.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[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" -version = "0.48.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[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 = "wyz" diff --git a/swhkd/src/config.rs b/swhkd/src/config.rs index 15b5f91..2c87db1 100644 --- a/swhkd/src/config.rs +++ b/swhkd/src/config.rs @@ -197,13 +197,14 @@ fn sweet_def_to_kb(def: &Definition) -> KeyBinding { let modifiers = def .modifiers .iter() - .map(|m| match m { - sweet::token::Modifier::Super => Modifier::Super, - sweet::token::Modifier::Any => Modifier::Any, - sweet::token::Modifier::Control => Modifier::Control, - sweet::token::Modifier::Alt => Modifier::Alt, - sweet::token::Modifier::Altgr => Modifier::Altgr, - sweet::token::Modifier::Shift => Modifier::Shift, + .filter_map(|m| match m { + sweet::token::Modifier::Super => Some(Modifier::Super), + sweet::token::Modifier::Any => Some(Modifier::Any), + sweet::token::Modifier::Control => Some(Modifier::Control), + sweet::token::Modifier::Alt => Some(Modifier::Alt), + sweet::token::Modifier::Altgr => Some(Modifier::Altgr), + sweet::token::Modifier::Shift => Some(Modifier::Shift), + sweet::token::Modifier::Omission => None, }) .collect(); diff --git a/swhkd/src/tests.rs b/swhkd/src/tests.rs deleted file mode 100644 index fe7d93a..0000000 --- a/swhkd/src/tests.rs +++ /dev/null @@ -1,1231 +0,0 @@ -mod test_config { - use crate::config::{ - extract_curly_brace, load, parse_contents, Error, Hotkey, Modifier, ParseError, Prefix, - }; - use std::fs; - use std::io::Write; - use std::{fs::File, path::PathBuf}; - - // Implement a struct for a path used in tests - // so that the test file will be automatically removed - // no matter how the test goes - struct TestPath { - path: PathBuf, - } - - impl TestPath { - fn new(path: &str) -> Self { - TestPath { path: PathBuf::from(path) } - } - - // Create a path method for a more succinct way - // to deal with borrowing the path value - fn path(&self) -> PathBuf { - self.path.clone() - } - } - - impl Drop for TestPath { - fn drop(self: &mut TestPath) { - if self.path.exists() { - fs::remove_file(self.path()).unwrap(); - } - } - } - - // Wrapper for config tests - fn eval_config_test(contents: &str, expected_hotkeys: Vec) -> std::io::Result<()> { - let result = parse_contents(PathBuf::new(), contents.to_string()); - - let mut expected_hotkeys_mut = expected_hotkeys; - - if result.is_err() { - panic!("Expected Ok config, found Err {:?}", result.unwrap_err()); - } - - let result = &result.unwrap()[0]; - let actual_hotkeys = &result.hotkeys; - - assert_eq!(actual_hotkeys.len(), expected_hotkeys_mut.len()); - - // Go through each actual hotkey, and pop a corresponding - // hotkey from the expected hotkeys - // to make sure that order does not matter - for hotkey in actual_hotkeys { - if let Some(index) = expected_hotkeys_mut.iter().position(|key| { - key.keybinding == hotkey.keybinding && key.command == hotkey.command - }) { - expected_hotkeys_mut.remove(index); - } else { - panic!( - "unexpected hotkey {:#?} found in result\nExpected result:\n{:#?}", - hotkey, expected_hotkeys_mut - ); - } - } - - if !expected_hotkeys_mut.is_empty() { - panic!( - "Some hotkeys were not returned by the actual result:\n{:#?}", - expected_hotkeys_mut - ); - } - - Ok(()) - } - - // Wrapper for the many error tests - fn eval_invalid_config_test( - contents: &str, - parse_error_type: ParseError, - ) -> std::io::Result<()> { - let result = parse_contents(PathBuf::new(), contents.to_string()); - - assert!(result.is_err()); - let result = result.unwrap_err(); - - // Check if the Error type is InvalidConfig - let result = match result { - Error::InvalidConfig(parse_err) => parse_err, - _ => panic!(), - }; - - // Check the ParseError enum type - if result != parse_error_type { - panic!("ParseError: Expected `{:?}`, found `{:?}`", parse_error_type, result); - } - - Ok(()) - } - - #[test] - fn test_existing_file() -> std::io::Result<()> { - let setup = TestPath::new("/tmp/swhkd-test-file1"); - // Build a dummy file in /tmp - let mut f = File::create(setup.path())?; - f.write_all( - b" -x - dmenu_run - -q - bspc node -q", - )?; - - let result = fs::read_to_string(&setup.path()); - assert!(result.is_ok()); - Ok(()) - } - - #[test] - fn test_load_multiple_config() -> std::io::Result<()> { - let setup = TestPath::new("/tmp/swhkd-test-file2"); - let mut f = File::create(setup.path())?; - f.write_all( - b" -include /tmp/swhkd-test-file3 -super + b - firefox", - )?; - - let setup2 = TestPath::new("/tmp/swhkd-test-file3"); - let mut f2 = File::create(setup2.path())?; - f2.write_all( - b" -super + c - hello", - )?; - - let hotkeys = &load(&setup.path()).unwrap()[0].hotkeys; - assert_eq!( - *hotkeys, - vec!( - Hotkey::new(evdev::Key::KEY_C, vec![Modifier::Super], String::from("hello")), - Hotkey::new(evdev::Key::KEY_B, vec![Modifier::Super], String::from("firefox")) - ) - ); - Ok(()) - } - - #[test] - fn test_relative_import() -> std::io::Result<()> { - let setup = TestPath::new("/tmp/swhkd-relative-file1"); - let mut f = File::create(setup.path())?; - f.write_all( - b" -include swhkd-relative-file2 -super + b - firefox", - )?; - - let setup2 = TestPath::new("swhkd-relative-file2"); - let mut f2 = File::create(setup2.path())?; - f2.write_all( - b" -super + c - hello", - )?; - - let hotkeys = &load(&setup.path()).unwrap()[0].hotkeys; - assert_eq!( - *hotkeys, - vec!( - Hotkey::new(evdev::Key::KEY_C, vec![Modifier::Super], String::from("hello")), - Hotkey::new(evdev::Key::KEY_B, vec![Modifier::Super], String::from("firefox")) - ) - ); - Ok(()) - } - - #[test] - fn test_more_multiple_configs() -> std::io::Result<()> { - let setup = TestPath::new("/tmp/swhkd-test-file4"); - let mut f = File::create(setup.path())?; - f.write_all( - b" -a - a", - )?; - - let setup2 = TestPath::new("/tmp/swhkd-test-file5"); - let mut f2 = File::create(setup2.path())?; - f2.write_all( - b" -include /tmp/swhkd-test-file4 -b - b", - )?; - let setup3 = TestPath::new("/tmp/swhkd-test-file6"); - let mut f3 = File::create(setup3.path())?; - f3.write_all( - b" -include /tmp/swhkd-test-file4 -include /tmp/swhkd-test-file5 -include /tmp/swhkd-test-file6 -include /tmp/swhkd-test-file7 -c - c", - )?; - let setup4 = TestPath::new("/tmp/swhkd-test-file7"); - let mut f4 = File::create(setup4.path())?; - f4.write_all( - b" -include /tmp/swhkd-test-file6 -d - d", - )?; - - let hotkeys = &load(&setup4.path()).unwrap()[0].hotkeys; - assert_eq!( - *hotkeys, - vec!( - Hotkey::new(evdev::Key::KEY_C, vec![], String::from("c")), - Hotkey::new(evdev::Key::KEY_A, vec![], String::from("a")), - Hotkey::new(evdev::Key::KEY_B, vec![], String::from("b")), - Hotkey::new(evdev::Key::KEY_D, vec![], String::from("d")), - ) - ); - Ok(()) - } - #[test] - fn test_include_and_unbind() -> std::io::Result<()> { - let setup = TestPath::new("/tmp/swhkd-test-file8"); - let mut f = File::create(setup.path())?; - f.write_all( - b" -include /tmp/swhkd-test-file9 -super + b - firefox -ignore super + d", - )?; - - let setup2 = TestPath::new("/tmp/swhkd-test-file9"); - let mut f2 = File::create(setup2.path())?; - f2.write_all( - b" -super + c - hello -super + d - world", - )?; - - let hotkeys = &load(&setup.path()).unwrap()[0].hotkeys; - assert_eq!( - *hotkeys, - vec!( - Hotkey::new(evdev::Key::KEY_C, vec![Modifier::Super], String::from("hello")), - Hotkey::new(evdev::Key::KEY_B, vec![Modifier::Super], String::from("firefox")) - ) - ); - Ok(()) - } - - #[test] - fn test_basic_keybind() -> std::io::Result<()> { - let contents = " -r - alacritty - "; - - eval_config_test( - contents, - vec![Hotkey::new(evdev::Key::KEY_R, vec![], String::from("alacritty"))], - ) - } - - #[test] - fn test_multiple_keybinds() -> std::io::Result<()> { - let contents = " -r - alacritty - -w - kitty - -t - /bin/firefox - "; - - let hotkey_1 = Hotkey::new(evdev::Key::KEY_R, vec![], String::from("alacritty")); - let hotkey_2 = Hotkey::new(evdev::Key::KEY_W, vec![], String::from("kitty")); - let hotkey_3 = Hotkey::new(evdev::Key::KEY_T, vec![], String::from("/bin/firefox")); - - eval_config_test(contents, vec![hotkey_1, hotkey_2, hotkey_3]) - } - - #[test] - fn test_comments() -> std::io::Result<()> { - let contents = " -r - alacritty - -w - kitty - -#t - #/bin/firefox - "; - - let expected_keybinds = vec![ - Hotkey::new(evdev::Key::KEY_R, vec![], String::from("alacritty")), - Hotkey::new(evdev::Key::KEY_W, vec![], String::from("kitty")), - ]; - - eval_config_test(contents, expected_keybinds) - } - - #[test] - fn test_multiple_keypress() -> std::io::Result<()> { - let contents = " -super + 5 - alacritty - "; - - let expected_keybinds = - vec![Hotkey::new(evdev::Key::KEY_5, vec![Modifier::Super], String::from("alacritty"))]; - - eval_config_test(contents, expected_keybinds) - } - - #[test] - fn test_keysym_instead_of_modifier() -> std::io::Result<()> { - let contents = " -shift + k + m - notify-send 'Hello world!' - "; - - eval_invalid_config_test(contents, ParseError::InvalidModifier(PathBuf::new(), 2)) - } - - #[test] - fn test_modifier_instead_of_keysym() -> std::io::Result<()> { - let contents = " -shift + k + alt - notify-send 'Hello world!' - "; - - eval_invalid_config_test(contents, ParseError::InvalidModifier(PathBuf::new(), 2)) - } - - #[test] - fn test_unfinished_plus_sign() -> std::io::Result<()> { - let contents = " - - -shift + alt + - notify-send 'Hello world!' - "; - - eval_invalid_config_test(contents, ParseError::UnknownSymbol(PathBuf::new(), 4)) - } - - #[test] - fn test_plus_sign_at_start() -> std::io::Result<()> { - let contents = " -+ shift + k - notify-send 'Hello world!' - "; - - eval_invalid_config_test(contents, ParseError::UnknownSymbol(PathBuf::new(), 2)) - } - - #[test] - fn test_common_modifiers() -> std::io::Result<()> { - let contents = " -shift + k - notify-send 'Hello world!' - -control + 5 - notify-send 'Hello world!' - -alt + 2 - notify-send 'Hello world!' - -altgr + i - notify-send 'Hello world!' - -super + z - notify-send 'Hello world!' - "; - - let expected_hotkeys = vec![ - Hotkey::new( - evdev::Key::KEY_K, - vec![Modifier::Shift], - "notify-send 'Hello world!'".to_string(), - ), - Hotkey::new( - evdev::Key::KEY_5, - vec![Modifier::Control], - "notify-send 'Hello world!'".to_string(), - ), - Hotkey::new( - evdev::Key::KEY_2, - vec![Modifier::Alt], - "notify-send 'Hello world!'".to_string(), - ), - Hotkey::new( - evdev::Key::KEY_I, - vec![Modifier::Altgr], - "notify-send 'Hello world!'".to_string(), - ), - Hotkey::new( - evdev::Key::KEY_Z, - vec![Modifier::Super], - "notify-send 'Hello world!'".to_string(), - ), - ]; - - eval_config_test(contents, expected_hotkeys) - } - - #[test] - fn test_command_with_many_spaces() -> std::io::Result<()> { - let contents = " -p - xbacklight -inc 10 -fps 30 -time 200 - "; - - let expected_keybinds = vec![Hotkey::new( - evdev::Key::KEY_P, - vec![], - String::from("xbacklight -inc 10 -fps 30 -time 200"), - )]; - - eval_config_test(contents, expected_keybinds) - } - - #[test] - fn test_invalid_keybinding() -> std::io::Result<()> { - let contents = " -p - xbacklight -inc 10 -fps 30 -time 200 - -pesto - xterm - "; - - eval_invalid_config_test(contents, ParseError::UnknownSymbol(PathBuf::new(), 5)) - } - - #[test] - // keysyms not followed by command should be ignored - fn test_no_command() -> std::io::Result<()> { - let contents = " -k - xbacklight -inc 10 -fps 30 -time 200 - -w - - "; - - eval_config_test( - contents, - vec![Hotkey::new( - evdev::Key::KEY_K, - vec![], - "xbacklight -inc 10 -fps 30 -time 200".to_string(), - )], - ) - } - - #[test] - fn test_real_config_snippet() -> std::io::Result<()> { - let contents = " -# reloads sxhkd configuration: -super + Escape - pkill -USR1 -x sxhkd ; sxhkd & - -# Launch Terminal -super + Return - alacritty -t \"Terminal\" -e \"$HOME/.config/sxhkd/new_tmux_terminal.sh\" - -# terminal emulator (no tmux) -super + shift + Return - alacritty -t \"Terminal\" - -# terminal emulator (new tmux session) -alt + Return - alacritty -t \"Terminal\" -e \"tmux\" - -ctrl + 0 - play-song.sh - -super + minus - play-song.sh album - "; - - let expected_result: Vec = vec![ - Hotkey::new( - evdev::Key::KEY_ESC, - vec![Modifier::Super], - String::from("pkill -USR1 -x sxhkd ; sxhkd &"), - ), - Hotkey::new( - evdev::Key::KEY_ENTER, - vec![Modifier::Super], - String::from( - "alacritty -t \"Terminal\" -e \"$HOME/.config/sxhkd/new_tmux_terminal.sh\"", - ), - ), - Hotkey::new( - evdev::Key::KEY_ENTER, - vec![Modifier::Super, Modifier::Shift], - String::from("alacritty -t \"Terminal\""), - ), - Hotkey::new( - evdev::Key::KEY_ENTER, - vec![Modifier::Alt], - String::from("alacritty -t \"Terminal\" -e \"tmux\""), - ), - Hotkey::new(evdev::Key::KEY_0, vec![Modifier::Control], String::from("play-song.sh")), - Hotkey::new( - evdev::Key::KEY_MINUS, - vec![Modifier::Super], - String::from("play-song.sh album"), - ), - ]; - - eval_config_test(contents, expected_result) - } - - #[test] - fn test_multiline_command() -> std::io::Result<()> { - let contents = " -k - mpc ls | dmenu | \\ - sed -i 's/foo/bar/g' - "; - - let expected_keybind = Hotkey::new( - evdev::Key::KEY_K, - vec![], - String::from("mpc ls | dmenu | sed -i 's/foo/bar/g'"), - ); - - eval_config_test(contents, vec![expected_keybind]) - } - - #[test] - fn test_commented_out_keybind() -> std::io::Result<()> { - let contents = " -#w - gimp - "; - - eval_config_test(contents, vec![]) - } - - // TODO: Write these tests as needed. - - #[test] - fn test_all_alphanumeric() -> std::io::Result<()> { - let symbols: [&str; 36] = [ - "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", - "r", "s", "t", "u", "v", "w", "x", "y", "z", "0", "1", "2", "3", "4", "5", "6", "7", - "8", "9", - ]; - let keysyms: [evdev::Key; 36] = [ - evdev::Key::KEY_A, - evdev::Key::KEY_B, - evdev::Key::KEY_C, - evdev::Key::KEY_D, - evdev::Key::KEY_E, - evdev::Key::KEY_F, - evdev::Key::KEY_G, - evdev::Key::KEY_H, - evdev::Key::KEY_I, - evdev::Key::KEY_J, - evdev::Key::KEY_K, - evdev::Key::KEY_L, - evdev::Key::KEY_M, - evdev::Key::KEY_N, - evdev::Key::KEY_O, - evdev::Key::KEY_P, - evdev::Key::KEY_Q, - evdev::Key::KEY_R, - evdev::Key::KEY_S, - evdev::Key::KEY_T, - evdev::Key::KEY_U, - evdev::Key::KEY_V, - evdev::Key::KEY_W, - evdev::Key::KEY_X, - evdev::Key::KEY_Y, - evdev::Key::KEY_Z, - evdev::Key::KEY_0, - evdev::Key::KEY_1, - evdev::Key::KEY_2, - evdev::Key::KEY_3, - evdev::Key::KEY_4, - evdev::Key::KEY_5, - evdev::Key::KEY_6, - evdev::Key::KEY_7, - evdev::Key::KEY_8, - evdev::Key::KEY_9, - ]; - - let mut contents = String::new(); - for symbol in &symbols { - contents.push_str(&format!("{}\n st\n", symbol)); - } - let contents = &contents; - - let expected_result: Vec = - keysyms.iter().map(|keysym| Hotkey::new(*keysym, vec![], "st".to_string())).collect(); - - eval_config_test(contents, expected_result) - } - - #[test] - fn test_homerow_special_keys_top() -> std::io::Result<()> { - let symbols: [&str; 7] = - ["Escape", "BackSpace", "Return", "Tab", "minus", "equal", "grave"]; - - let keysyms: [evdev::Key; 7] = [ - evdev::Key::KEY_ESC, - evdev::Key::KEY_BACKSPACE, - evdev::Key::KEY_ENTER, - evdev::Key::KEY_TAB, - evdev::Key::KEY_MINUS, - evdev::Key::KEY_EQUAL, - evdev::Key::KEY_GRAVE, - ]; - - let mut contents = String::new(); - for symbol in &symbols { - contents.push_str(&format!("{}\n st\n", symbol)); - } - let contents = &contents; - - let expected_result: Vec = - keysyms.iter().map(|keysym| Hotkey::new(*keysym, vec![], "st".to_string())).collect(); - - eval_config_test(contents, expected_result) - } - - #[test] - fn test_case_insensitive() -> std::io::Result<()> { - let contents = " -Super + SHIFT + alt + a - st -ReTurn - ts - "; - eval_config_test( - contents, - vec![ - Hotkey::new( - evdev::Key::KEY_A, - vec![Modifier::Super, Modifier::Shift, Modifier::Alt], - "st".to_string(), - ), - Hotkey::new(evdev::Key::KEY_ENTER, vec![], "ts".to_string()), - ], - ) - } - - #[test] - fn test_duplicate_hotkeys() -> std::io::Result<()> { - let contents = " -super + shift + a - st -shift + suPer + A - ts -b - st -B - ts -"; - eval_config_test( - contents, - vec![ - Hotkey::new( - evdev::Key::KEY_A, - vec![Modifier::Super, Modifier::Shift], - "ts".to_string(), - ), - Hotkey::new(evdev::Key::KEY_B, vec![], "ts".to_string()), - ], - ) - } - - #[test] - fn test_inline_comment() -> std::io::Result<()> { - let contents = " -super + a #comment and comment super - st -super + shift + b - ts #this comment should be handled by shell -" - .to_string(); - eval_config_test( - &contents, - vec![ - Hotkey::new(evdev::Key::KEY_A, vec![Modifier::Super], "st".to_string()), - Hotkey::new( - evdev::Key::KEY_B, - vec![Modifier::Super, Modifier::Shift], - "ts #this comment should be handled by shell".to_string(), - ), - ], - ) - } - - #[test] - fn test_blank_config() -> std::io::Result<()> { - let contents = ""; - - eval_config_test(contents, vec![]) - } - - #[test] - fn test_blank_config_with_whitespace() -> std::io::Result<()> { - let contents = " - - - "; - - eval_config_test(contents, vec![]) - } - - #[test] - fn test_extract_curly_brace() -> std::io::Result<()> { - let keybind_with_curly_brace = "super + {a,b,c}"; - assert_eq!( - extract_curly_brace(keybind_with_curly_brace), - vec!["super + a", "super + b", "super + c",] - ); - let command_with_curly_brace = "bspc node -p {west,south,north,west}"; - assert_eq!( - extract_curly_brace(command_with_curly_brace), - vec![ - "bspc node -p west", - "bspc node -p south", - "bspc node -p north", - "bspc node -p west", - ] - ); - let wrong_format = "super + }a, b, c{"; - assert_eq!(extract_curly_brace(wrong_format), vec![wrong_format]); - let single_sym = "super + {a}"; - assert_eq!(extract_curly_brace(single_sym), vec!["super + a"]); - Ok(()) - } - - #[test] - fn test_curly_brace() -> std::io::Result<()> { - let contents = " -super + {a,b,c} - {firefox, brave, chrome}"; - eval_config_test( - contents, - vec![ - Hotkey::new(evdev::Key::KEY_A, vec![Modifier::Super], "firefox".to_string()), - Hotkey::new(evdev::Key::KEY_B, vec![Modifier::Super], "brave".to_string()), - Hotkey::new(evdev::Key::KEY_C, vec![Modifier::Super], "chrome".to_string()), - ], - ) - } - - #[test] - fn test_curly_brace_less_commands() -> std::io::Result<()> { - let contents = " -super + {a,b,c} - {firefox, brave}"; - eval_config_test( - contents, - vec![ - Hotkey::new(evdev::Key::KEY_A, vec![Modifier::Super], "firefox".to_string()), - Hotkey::new(evdev::Key::KEY_B, vec![Modifier::Super], "brave".to_string()), - ], - ) - } - - #[test] - fn test_curly_brace_less_keysyms() -> std::io::Result<()> { - let contents = " -super + {a, b} - {firefox, brave, chrome}"; - eval_config_test( - contents, - vec![ - Hotkey::new(evdev::Key::KEY_A, vec![Modifier::Super], "firefox".to_string()), - Hotkey::new(evdev::Key::KEY_B, vec![Modifier::Super], "brave".to_string()), - ], - ) - } - - #[test] - fn test_range_syntax() -> std::io::Result<()> { - let contents = " -super + {1-9,0} - bspc desktop -f '{1-9,0}'"; - eval_config_test( - contents, - vec![ - Hotkey::new( - evdev::Key::KEY_1, - vec![Modifier::Super], - "bspc desktop -f '1'".to_string(), - ), - Hotkey::new( - evdev::Key::KEY_2, - vec![Modifier::Super], - "bspc desktop -f '2'".to_string(), - ), - Hotkey::new( - evdev::Key::KEY_3, - vec![Modifier::Super], - "bspc desktop -f '3'".to_string(), - ), - Hotkey::new( - evdev::Key::KEY_4, - vec![Modifier::Super], - "bspc desktop -f '4'".to_string(), - ), - Hotkey::new( - evdev::Key::KEY_5, - vec![Modifier::Super], - "bspc desktop -f '5'".to_string(), - ), - Hotkey::new( - evdev::Key::KEY_6, - vec![Modifier::Super], - "bspc desktop -f '6'".to_string(), - ), - Hotkey::new( - evdev::Key::KEY_7, - vec![Modifier::Super], - "bspc desktop -f '7'".to_string(), - ), - Hotkey::new( - evdev::Key::KEY_8, - vec![Modifier::Super], - "bspc desktop -f '8'".to_string(), - ), - Hotkey::new( - evdev::Key::KEY_9, - vec![Modifier::Super], - "bspc desktop -f '9'".to_string(), - ), - Hotkey::new( - evdev::Key::KEY_0, - vec![Modifier::Super], - "bspc desktop -f '0'".to_string(), - ), - ], - ) - } - - #[test] - fn test_range_syntax_ascii_character() -> std::io::Result<()> { - let contents = " -super + {a-c} - {firefox, brave, chrome}"; - eval_config_test( - contents, - vec![ - Hotkey::new(evdev::Key::KEY_A, vec![Modifier::Super], "firefox".to_string()), - Hotkey::new(evdev::Key::KEY_B, vec![Modifier::Super], "brave".to_string()), - Hotkey::new(evdev::Key::KEY_C, vec![Modifier::Super], "chrome".to_string()), - ], - ) - } - - #[test] - fn test_range_syntax_not_ascii() -> std::io::Result<()> { - let contents = " -super + {a-是} - {firefox, brave} - "; - eval_invalid_config_test(contents, ParseError::UnknownSymbol(PathBuf::new(), 2)) - } - - #[test] - fn test_range_syntax_invalid_range() -> std::io::Result<()> { - let contents = " -super + {bc-ad} - {firefox, brave} - "; - eval_invalid_config_test(contents, ParseError::UnknownSymbol(PathBuf::new(), 2)) - } - - #[test] - fn test_ranger_syntax_not_full_range() -> std::io::Result<()> { - let contents = " -super + {a-} - {firefox, brave}"; - eval_invalid_config_test(contents, ParseError::UnknownSymbol(PathBuf::new(), 2)) - } - - #[test] - fn test_none() -> std::io::Result<()> { - let contents = " -super + {_, shift} + b - {firefox, brave}"; - eval_config_test( - contents, - vec![ - Hotkey::new(evdev::Key::KEY_B, vec![Modifier::Super], "firefox".to_string()), - Hotkey::new( - evdev::Key::KEY_B, - vec![Modifier::Super, Modifier::Shift], - "brave".to_string(), - ), - ], - ) - } - - #[test] - fn test_multiple_ranges() -> std::io::Result<()> { - let contents = " -super + {shift,alt} + {c,d} - {librewolf, firefox} {--sync, --help} - "; - - eval_config_test( - contents, - vec![ - Hotkey::new( - evdev::Key::KEY_C, - vec![Modifier::Super, Modifier::Shift], - "librewolf --sync".to_string(), - ), - Hotkey::new( - evdev::Key::KEY_D, - vec![Modifier::Super, Modifier::Shift], - "librewolf --help".to_string(), - ), - Hotkey::new( - evdev::Key::KEY_C, - vec![Modifier::Super, Modifier::Alt], - "firefox --sync".to_string(), - ), - Hotkey::new( - evdev::Key::KEY_D, - vec![Modifier::Super, Modifier::Alt], - "firefox --help".to_string(), - ), - ], - ) - } - - #[test] - fn test_multiple_ranges_numbers() -> std::io::Result<()> { - let contents = " -{control,super} + {1-3} - {notify-send, echo} {hello,how,are} - "; - - eval_config_test( - contents, - vec![ - Hotkey::new( - evdev::Key::KEY_1, - vec![Modifier::Control], - "notify-send hello".to_string(), - ), - Hotkey::new( - evdev::Key::KEY_2, - vec![Modifier::Control], - "notify-send how".to_string(), - ), - Hotkey::new( - evdev::Key::KEY_3, - vec![Modifier::Control], - "notify-send are".to_string(), - ), - Hotkey::new(evdev::Key::KEY_1, vec![Modifier::Super], "echo hello".to_string()), - Hotkey::new(evdev::Key::KEY_2, vec![Modifier::Super], "echo how".to_string()), - Hotkey::new(evdev::Key::KEY_3, vec![Modifier::Super], "echo are".to_string()), - ], - ) - } - - #[test] - fn test_bspwm_multiple_curly_brace() -> std::io::Result<()> { - let contents = " -super + {_,shift + }{h,j,k,l} - bspc node -{f,s} {west,south,north,east}"; - - eval_config_test( - contents, - vec![ - Hotkey::new( - evdev::Key::KEY_H, - vec![Modifier::Super], - "bspc node -f west".to_string(), - ), - Hotkey::new( - evdev::Key::KEY_J, - vec![Modifier::Super], - "bspc node -f south".to_string(), - ), - Hotkey::new( - evdev::Key::KEY_K, - vec![Modifier::Super], - "bspc node -f north".to_string(), - ), - Hotkey::new( - evdev::Key::KEY_L, - vec![Modifier::Super], - "bspc node -f east".to_string(), - ), - Hotkey::new( - evdev::Key::KEY_H, - vec![Modifier::Super, Modifier::Shift], - "bspc node -s west".to_string(), - ), - Hotkey::new( - evdev::Key::KEY_J, - vec![Modifier::Super, Modifier::Shift], - "bspc node -s south".to_string(), - ), - Hotkey::new( - evdev::Key::KEY_K, - vec![Modifier::Super, Modifier::Shift], - "bspc node -s north".to_string(), - ), - Hotkey::new( - evdev::Key::KEY_L, - vec![Modifier::Super, Modifier::Shift], - "bspc node -s east".to_string(), - ), - ], - ) - } - - #[test] - fn test_longer_multiple_curly_brace() -> std::io::Result<()> { - let contents = " -super + {_, ctrl +} {_, shift +} {1-2} - riverctl {set, toggle}-{focused, view}-tags {1-2}"; - eval_config_test( - contents, - vec![ - Hotkey::new( - evdev::Key::KEY_1, - vec![Modifier::Super], - "riverctl set-focused-tags 1".to_string(), - ), - Hotkey::new( - evdev::Key::KEY_2, - vec![Modifier::Super], - "riverctl set-focused-tags 2".to_string(), - ), - Hotkey::new( - evdev::Key::KEY_1, - vec![Modifier::Super, Modifier::Control], - "riverctl toggle-focused-tags 1".to_string(), - ), - Hotkey::new( - evdev::Key::KEY_2, - vec![Modifier::Super, Modifier::Control], - "riverctl toggle-focused-tags 2".to_string(), - ), - Hotkey::new( - evdev::Key::KEY_1, - vec![Modifier::Super, Modifier::Shift], - "riverctl set-view-tags 1".to_string(), - ), - Hotkey::new( - evdev::Key::KEY_2, - vec![Modifier::Super, Modifier::Shift], - "riverctl set-view-tags 2".to_string(), - ), - Hotkey::new( - evdev::Key::KEY_1, - vec![Modifier::Super, Modifier::Control, Modifier::Shift], - "riverctl toggle-view-tags 1".to_string(), - ), - Hotkey::new( - evdev::Key::KEY_2, - vec![Modifier::Super, Modifier::Control, Modifier::Shift], - "riverctl toggle-view-tags 2".to_string(), - ), - ], - ) - } - - #[test] - fn test_period_binding() -> std::io::Result<()> { - let contents = " -super + {comma, period} - riverctl focus-output {previous, next}"; - - eval_config_test( - contents, - vec![ - Hotkey::new( - evdev::Key::KEY_COMMA, - vec![Modifier::Super], - "riverctl focus-output previous".to_string(), - ), - Hotkey::new( - evdev::Key::KEY_DOT, - vec![Modifier::Super], - "riverctl focus-output next".to_string(), - ), - ], - ) - } - - #[test] - fn test_period_escape_binding() -> std::io::Result<()> { - let contents = " -super + {\\,, .} - riverctl focus-output {previous, next}"; - - eval_config_test( - contents, - vec![ - Hotkey::new( - evdev::Key::KEY_COMMA, - vec![Modifier::Super], - "riverctl focus-output previous".to_string(), - ), - Hotkey::new( - evdev::Key::KEY_DOT, - vec![Modifier::Super], - "riverctl focus-output next".to_string(), - ), - ], - ) - } - - #[test] - fn test_prefix() -> std::io::Result<()> { - let contents = " -super + @1 - 1 -super + ~2 - 2 -super + ~@3 - 3 -super + @~4 - 4"; - - eval_config_test( - contents, - vec![ - Hotkey::new(evdev::Key::KEY_1, vec![Modifier::Super], "1".to_string()).on_release(), - Hotkey::new(evdev::Key::KEY_2, vec![Modifier::Super], "2".to_string()).send(), - Hotkey::new(evdev::Key::KEY_3, vec![Modifier::Super], "3".to_string()) - .on_release() - .send(), - Hotkey::new(evdev::Key::KEY_4, vec![Modifier::Super], "4".to_string()) - .on_release() - .send(), - ], - ) - } - - #[test] - fn test_override() -> std::io::Result<()> { - let contents = " -super + a - 1 -super + a - 2"; - eval_config_test( - contents, - vec![Hotkey::new(evdev::Key::KEY_A, vec![Modifier::Super], "2".to_string())], - ) - } - - #[test] - fn test_any_modifier() -> std::io::Result<()> { - let contents = " -any + a - 1"; - eval_config_test( - contents, - vec![Hotkey::new(evdev::Key::KEY_A, vec![Modifier::Any], "1".to_string())], - ) - } -} - -mod test_config_display { - use crate::config::{Error, ParseError}; - use std::io; - use std::path::PathBuf; - - #[test] - fn test_display_io_error() { - let error = Error::Io(io::Error::from(io::ErrorKind::UnexpectedEof)); - - if !format!("{}", error).contains("unexpected end of file") { - panic!("Error message was '{}", error); - } - } - - #[test] - fn test_display_unknown_symbol_error() { - let error = Error::InvalidConfig(ParseError::UnknownSymbol(PathBuf::new(), 10)); - - assert_eq!( - format!("{}", error), - "Error parsing config file \"\". Unknown symbol at line 10." - ); - } - - #[test] - fn test_display_invalid_modifier_error() { - let error = Error::InvalidConfig(ParseError::InvalidModifier(PathBuf::new(), 25)); - - assert_eq!( - format!("{}", error), - "Error parsing config file \"\". Invalid modifier at line 25." - ); - } - - #[test] - fn test_invalid_keysm_error() { - let error = Error::InvalidConfig(ParseError::InvalidKeysym(PathBuf::new(), 7)); - - assert_eq!( - format!("{}", error), - "Error parsing config file \"\". Invalid keysym at line 7." - ); - } -} From 0ee964e77b451da368610383883a5f30637b5322 Mon Sep 17 00:00:00 2001 From: Himadri Bhattacharjee <107522312+lavafroth@users.noreply.github.com> Date: Mon, 29 Jul 2024 14:49:57 +0530 Subject: [PATCH 09/11] fix: there are no swhkd tests --- swhkd/src/daemon.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/swhkd/src/daemon.rs b/swhkd/src/daemon.rs index 628223f..d155b3c 100644 --- a/swhkd/src/daemon.rs +++ b/swhkd/src/daemon.rs @@ -31,9 +31,6 @@ mod environ; mod perms; mod uinput; -#[cfg(test)] -mod tests; - struct KeyboardState { state_modifiers: HashSet, state_keysyms: AttributeSet, From ca276ee0aa14e2f0d93bc00ab57278aca223c36f Mon Sep 17 00:00:00 2001 From: Himadri Bhattacharjee <107522312+lavafroth@users.noreply.github.com> Date: Sun, 25 Aug 2024 16:42:07 +0530 Subject: [PATCH 10/11] fix: change sweet source url to in-tree repo --- Cargo.lock | 2 +- swhkd/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 379d082..5335674 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -768,7 +768,7 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "sweet" version = "0.3.0" -source = "git+https://github.com/lavafroth/sweet.git#6146627ee75be8bda87dc443c2f1d153590d3610" +source = "git+https://github.com/waycrate/sweet.git#a91d1ab6fb7988578ce359cfbf55e75b813d84db" dependencies = [ "anyhow", "bitflags 2.6.0", diff --git a/swhkd/Cargo.toml b/swhkd/Cargo.toml index 30e1dd4..14ef242 100644 --- a/swhkd/Cargo.toml +++ b/swhkd/Cargo.toml @@ -21,7 +21,7 @@ log = "0.4.14" nix = "0.23.1" signal-hook = "0.3.13" signal-hook-tokio = { version = "0.3.1", features = ["futures-v0_3"] } -sweet = { git = "https://github.com/lavafroth/sweet.git", version = "0.3.0" } +sweet = { git = "https://github.com/waycrate/sweet.git", version = "0.3.0" } sysinfo = "0.23.5" tokio = { version = "1.24.2", features = ["full"] } tokio-stream = "0.1.8" From d56a9cf3a03a55035cb260b090d3bc17a6e0b5c1 Mon Sep 17 00:00:00 2001 From: Himadri Bhattacharjee <107522312+lavafroth@users.noreply.github.com> Date: Sun, 25 Aug 2024 16:52:27 +0530 Subject: [PATCH 11/11] chore: `sweet` use re-exported modules from crate root --- swhkd/src/config.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/swhkd/src/config.rs b/swhkd/src/config.rs index 2c87db1..d64517f 100644 --- a/swhkd/src/config.rs +++ b/swhkd/src/config.rs @@ -1,5 +1,5 @@ use std::path::Path; -use sweet::token::KeyAttribute; +use sweet::KeyAttribute; use sweet::{Definition, SwhkdParser}; use sweet::{ModeInstruction, ParseError}; @@ -192,19 +192,19 @@ pub fn parse_contents(contents: SwhkdParser) -> Result, ParseError> { Ok(modes) } -/// A small function to convert a `sweet::token::Modifier` into the local `Modifier` enum +/// A small function to convert a `sweet::Modifier` into the local `Modifier` enum fn sweet_def_to_kb(def: &Definition) -> KeyBinding { let modifiers = def .modifiers .iter() .filter_map(|m| match m { - sweet::token::Modifier::Super => Some(Modifier::Super), - sweet::token::Modifier::Any => Some(Modifier::Any), - sweet::token::Modifier::Control => Some(Modifier::Control), - sweet::token::Modifier::Alt => Some(Modifier::Alt), - sweet::token::Modifier::Altgr => Some(Modifier::Altgr), - sweet::token::Modifier::Shift => Some(Modifier::Shift), - sweet::token::Modifier::Omission => None, + sweet::Modifier::Super => Some(Modifier::Super), + sweet::Modifier::Any => Some(Modifier::Any), + sweet::Modifier::Control => Some(Modifier::Control), + sweet::Modifier::Alt => Some(Modifier::Alt), + sweet::Modifier::Altgr => Some(Modifier::Altgr), + sweet::Modifier::Shift => Some(Modifier::Shift), + sweet::Modifier::Omission => None, }) .collect();