Compare commits
No commits in common. "37a0834aa0808330725a01018b89be6ab027001e" and "196c392f59fd63370267b678c3e7eb75ab139320" have entirely different histories.
37a0834aa0
...
196c392f59
|
@ -188,7 +188,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.39",
|
"syn 2.0.38",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -199,7 +199,7 @@ checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.39",
|
"syn 2.0.38",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -460,7 +460,7 @@ dependencies = [
|
||||||
"heck",
|
"heck",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.39",
|
"syn 2.0.38",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -771,7 +771,7 @@ checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.39",
|
"syn 2.0.38",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -831,9 +831,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "errno"
|
name = "errno"
|
||||||
version = "0.3.6"
|
version = "0.3.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7c18ee0ed65a5f1f81cac6b1d213b69c35fa47d4252ad41f1486dbd8226fe36e"
|
checksum = "ac3e13f66a2f95e32a39eaa81f6b95d42878ca0e1db0c7543723dfe12557e860"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"windows-sys",
|
"windows-sys",
|
||||||
|
@ -959,7 +959,7 @@ checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.39",
|
"syn 2.0.38",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1033,7 +1033,7 @@ checksum = "913dce4c5f06c2ea40fc178c06f777ac89fc6b1383e90c254fafb1abe4ba3c82"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.39",
|
"syn 2.0.38",
|
||||||
"uuid 1.5.0",
|
"uuid 1.5.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -1270,9 +1270,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "indexmap"
|
name = "indexmap"
|
||||||
version = "2.1.0"
|
version = "2.0.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f"
|
checksum = "8adf3ddd720272c6ea8bf59463c04e0f93d0bbf7c5439b691bca2987e0270897"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"equivalent",
|
"equivalent",
|
||||||
"hashbrown 0.14.2",
|
"hashbrown 0.14.2",
|
||||||
|
@ -1323,9 +1323,9 @@ checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "js-sys"
|
name = "js-sys"
|
||||||
version = "0.3.65"
|
version = "0.3.64"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "54c0c35952f67de54bb584e9fd912b3023117cbafc0a77d8f3dee1fb5f572fe8"
|
checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
|
@ -1348,17 +1348,6 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "keymaps"
|
|
||||||
version = "0.1.0"
|
|
||||||
dependencies = [
|
|
||||||
"crossterm",
|
|
||||||
"log",
|
|
||||||
"pest",
|
|
||||||
"pest_derive",
|
|
||||||
"thiserror",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "language_macros"
|
name = "language_macros"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
@ -1366,7 +1355,7 @@ dependencies = [
|
||||||
"convert_case",
|
"convert_case",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.39",
|
"syn 2.0.38",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1377,20 +1366,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.150"
|
version = "0.2.149"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c"
|
checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "libredox"
|
|
||||||
version = "0.0.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8"
|
|
||||||
dependencies = [
|
|
||||||
"bitflags 2.4.1",
|
|
||||||
"libc",
|
|
||||||
"redox_syscall 0.4.1",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "linux-raw-sys"
|
name = "linux-raw-sys"
|
||||||
|
@ -1738,9 +1716,9 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "openssl"
|
name = "openssl"
|
||||||
version = "0.10.59"
|
version = "0.10.57"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7a257ad03cd8fb16ad4172fedf8094451e1af1c4b70097636ef2eac9a5f0cc33"
|
checksum = "bac25ee399abb46215765b1cb35bc0212377e58a061560d8b29b024fd0430e7c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.4.1",
|
"bitflags 2.4.1",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
|
@ -1759,7 +1737,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.39",
|
"syn 2.0.38",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1770,9 +1748,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "openssl-sys"
|
name = "openssl-sys"
|
||||||
version = "0.9.95"
|
version = "0.9.93"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "40a4130519a360279579c2053038317e40eff64d13fd3f004f9e1b72b8a6aaf9"
|
checksum = "db4d56a4c0478783083cfafcc42493dd4a981d41669da64b4572a2a089b51b1d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
"libc",
|
"libc",
|
||||||
|
@ -1872,51 +1850,6 @@ version = "2.3.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94"
|
checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "pest"
|
|
||||||
version = "2.7.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ae9cee2a55a544be8b89dc6848072af97a20f2422603c10865be2a42b580fff5"
|
|
||||||
dependencies = [
|
|
||||||
"memchr",
|
|
||||||
"thiserror",
|
|
||||||
"ucd-trie",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "pest_derive"
|
|
||||||
version = "2.7.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "81d78524685f5ef2a3b3bd1cafbc9fcabb036253d9b1463e726a91cd16e2dfc2"
|
|
||||||
dependencies = [
|
|
||||||
"pest",
|
|
||||||
"pest_generator",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "pest_generator"
|
|
||||||
version = "2.7.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "68bd1206e71118b5356dae5ddc61c8b11e28b09ef6a31acbd15ea48a28e0c227"
|
|
||||||
dependencies = [
|
|
||||||
"pest",
|
|
||||||
"pest_meta",
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn 2.0.39",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "pest_meta"
|
|
||||||
version = "2.7.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "7c747191d4ad9e4a4ab9c8798f1e82a39affe7ef9648390b7e5548d18e099de6"
|
|
||||||
dependencies = [
|
|
||||||
"once_cell",
|
|
||||||
"pest",
|
|
||||||
"sha2 0.10.8",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pin-project"
|
name = "pin-project"
|
||||||
version = "1.1.3"
|
version = "1.1.3"
|
||||||
|
@ -1934,7 +1867,7 @@ checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.39",
|
"syn 2.0.38",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -2143,12 +2076,12 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "redox_users"
|
name = "redox_users"
|
||||||
version = "0.4.4"
|
version = "0.4.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4"
|
checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"getrandom 0.2.10",
|
"getrandom 0.2.10",
|
||||||
"libredox",
|
"redox_syscall 0.2.16",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -2389,9 +2322,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.192"
|
version = "1.0.190"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bca2a08484b285dcb282d0f67b26cadc0df8b19f8c12502c13d966bf9482f001"
|
checksum = "91d3c334ca1ee894a2c6f6ad698fe8c435b76d504b13d436f0685d648d6d96f7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
]
|
]
|
||||||
|
@ -2417,13 +2350,13 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.192"
|
version = "1.0.190"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d6c7207fbec9faa48073f3e3074cbe553af6ea512d7c21ba46e434e70ea9fbc1"
|
checksum = "67c5609f394e5c2bd7fc51efda478004ea80ef42fee983d5c67a65e34f32c0e3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.39",
|
"syn 2.0.38",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -2594,9 +2527,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.39"
|
version = "2.0.38"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a"
|
checksum = "e96b79aaa137db8f61e26363a0c9b47d8b4ec75da28b7d1d614c2303e232408b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
@ -2654,7 +2587,7 @@ checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.39",
|
"syn 2.0.38",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -2697,7 +2630,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.39",
|
"syn 2.0.38",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -2745,7 +2678,7 @@ version = "0.19.15"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421"
|
checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"indexmap 2.1.0",
|
"indexmap 2.0.2",
|
||||||
"toml_datetime",
|
"toml_datetime",
|
||||||
"winnow",
|
"winnow",
|
||||||
]
|
]
|
||||||
|
@ -2775,7 +2708,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.39",
|
"syn 2.0.38",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -2796,8 +2729,7 @@ dependencies = [
|
||||||
"cli-log",
|
"cli-log",
|
||||||
"crossterm",
|
"crossterm",
|
||||||
"directories",
|
"directories",
|
||||||
"indexmap 2.1.0",
|
"indexmap 2.0.2",
|
||||||
"keymaps",
|
|
||||||
"language_macros",
|
"language_macros",
|
||||||
"matrix-sdk",
|
"matrix-sdk",
|
||||||
"mlua",
|
"mlua",
|
||||||
|
@ -2846,12 +2778,6 @@ version = "1.17.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
|
checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "ucd-trie"
|
|
||||||
version = "0.1.6"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-bidi"
|
name = "unicode-bidi"
|
||||||
version = "0.3.13"
|
version = "0.3.13"
|
||||||
|
@ -2991,9 +2917,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen"
|
name = "wasm-bindgen"
|
||||||
version = "0.2.88"
|
version = "0.2.87"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7daec296f25a1bae309c0cd5c29c4b260e510e6d813c286b19eaadf409d40fce"
|
checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"serde",
|
"serde",
|
||||||
|
@ -3003,24 +2929,24 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-backend"
|
name = "wasm-bindgen-backend"
|
||||||
version = "0.2.88"
|
version = "0.2.87"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e397f4664c0e4e428e8313a469aaa58310d302159845980fd23b0f22a847f217"
|
checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bumpalo",
|
"bumpalo",
|
||||||
"log",
|
"log",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.39",
|
"syn 2.0.38",
|
||||||
"wasm-bindgen-shared",
|
"wasm-bindgen-shared",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-futures"
|
name = "wasm-bindgen-futures"
|
||||||
version = "0.4.38"
|
version = "0.4.37"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9afec9963e3d0994cac82455b2b3502b81a7f40f9a0d32181f7528d9f4b43e02"
|
checksum = "c02dbc21516f9f1f04f187958890d7e6026df8d16540b7ad9492bc34a67cea03"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
|
@ -3030,9 +2956,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-macro"
|
name = "wasm-bindgen-macro"
|
||||||
version = "0.2.88"
|
version = "0.2.87"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5961017b3b08ad5f3fe39f1e79877f8ee7c23c5e5fd5eb80de95abc41f1f16b2"
|
checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"quote",
|
"quote",
|
||||||
"wasm-bindgen-macro-support",
|
"wasm-bindgen-macro-support",
|
||||||
|
@ -3040,22 +2966,22 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-macro-support"
|
name = "wasm-bindgen-macro-support"
|
||||||
version = "0.2.88"
|
version = "0.2.87"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c5353b8dab669f5e10f5bd76df26a9360c748f054f862ff5f3f8aae0c7fb3907"
|
checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.39",
|
"syn 2.0.38",
|
||||||
"wasm-bindgen-backend",
|
"wasm-bindgen-backend",
|
||||||
"wasm-bindgen-shared",
|
"wasm-bindgen-shared",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-shared"
|
name = "wasm-bindgen-shared"
|
||||||
version = "0.2.88"
|
version = "0.2.87"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0d046c5d029ba91a1ed14da14dca44b68bf2f124cfbaf741c54151fdb3e0750b"
|
checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-timer"
|
name = "wasm-timer"
|
||||||
|
@ -3074,9 +3000,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "web-sys"
|
name = "web-sys"
|
||||||
version = "0.3.65"
|
version = "0.3.64"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5db499c5f66323272151db0e666cd34f78617522fb0c1604d31a27c50c206a85"
|
checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"js-sys",
|
"js-sys",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
|
@ -3187,9 +3113,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winnow"
|
name = "winnow"
|
||||||
version = "0.5.19"
|
version = "0.5.18"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "829846f3e3db426d4cee4510841b71a8e58aa2a76b1132579487ae430ccd9c7b"
|
checksum = "176b6138793677221d420fd2f0aeeced263f197688b36484660da767bca2fa32"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
|
@ -3239,5 +3165,5 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.39",
|
"syn 2.0.38",
|
||||||
]
|
]
|
||||||
|
|
|
@ -19,7 +19,6 @@ tokio = { version = "1.33", features = ["macros", "rt-multi-thread"] }
|
||||||
|
|
||||||
# lua stuff
|
# lua stuff
|
||||||
language_macros = { path = "./language_macros" }
|
language_macros = { path = "./language_macros" }
|
||||||
keymaps = { path = "./keymaps", features = ["crossterm"] }
|
|
||||||
mlua = { version = "0.9.1", features = ["lua54", "async", "send", "serialize"] }
|
mlua = { version = "0.9.1", features = ["lua54", "async", "send", "serialize"] }
|
||||||
once_cell = "1.18.0"
|
once_cell = "1.18.0"
|
||||||
|
|
||||||
|
@ -29,7 +28,7 @@ tui-textarea = { version = "0.2", features = ["crossterm"], optional = true }
|
||||||
crossterm = { version = "0.25", optional = true }
|
crossterm = { version = "0.25", optional = true }
|
||||||
tokio-util = { version = "0.7", optional = true }
|
tokio-util = { version = "0.7", optional = true }
|
||||||
serde = { version = "1.0", optional = true }
|
serde = { version = "1.0", optional = true }
|
||||||
indexmap = { version = "2.1.0", optional = true }
|
indexmap = { version = "2.0.2", optional = true }
|
||||||
directories = "5.0.1"
|
directories = "5.0.1"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
|
18
flake.lock
18
flake.lock
|
@ -7,11 +7,11 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1699218802,
|
"lastModified": 1698166613,
|
||||||
"narHash": "sha256-5l0W4Q7z7A4BCstaF5JuBqXOVrZ3Vqst5+hUnP7EdUc=",
|
"narHash": "sha256-y4rdN4flxRiROqNi1waMYIZj/Fs7L2OrszFk/1ry9vU=",
|
||||||
"owner": "ipetkov",
|
"owner": "ipetkov",
|
||||||
"repo": "crane",
|
"repo": "crane",
|
||||||
"rev": "2d6c2aaff5a05e443eb15efddc21f9c73720340c",
|
"rev": "b7db46f0f1751f7b1d1911f6be7daf568ad5bc65",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
@ -56,11 +56,11 @@
|
||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1699343069,
|
"lastModified": 1698553279,
|
||||||
"narHash": "sha256-s7BBhyLA6MI6FuJgs4F/SgpntHBzz40/qV0xLPW6A1Q=",
|
"narHash": "sha256-T/9P8yBSLcqo/v+FTOBK+0rjzjPMctVymZydbvR/Fak=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "ec750fd01963ab6b20ee1f0cb488754e8036d89d",
|
"rev": "90e85bc7c1a6fc0760a94ace129d3a1c61c3d035",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
@ -89,11 +89,11 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1699323235,
|
"lastModified": 1698726852,
|
||||||
"narHash": "sha256-ZFRItRv0dDSzsfpqSjj9qWM/SA1kRrOk6R04qhBZuxM=",
|
"narHash": "sha256-V1S4TTzg++GzPc96i/yy4jib+7/xU0LXHcggm9MllMM=",
|
||||||
"owner": "oxalica",
|
"owner": "oxalica",
|
||||||
"repo": "rust-overlay",
|
"repo": "rust-overlay",
|
||||||
"rev": "8a9d6f544c08ee898c7f3761cc9587be7565db5e",
|
"rev": "ec19bd20af08f3b004089cc12ab54c823ed899b7",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|
11
flake.nix
11
flake.nix
|
@ -52,17 +52,8 @@
|
||||||
extensions = ["rustc-codegen-cranelift-preview"];
|
extensions = ["rustc-codegen-cranelift-preview"];
|
||||||
}
|
}
|
||||||
else pkgs.rust-bin.stable.latest.default;
|
else pkgs.rust-bin.stable.latest.default;
|
||||||
rust_min =
|
|
||||||
if nightly
|
|
||||||
then
|
|
||||||
(pkgs.rust-bin.selectLatestNightlyWith (toolchain:
|
|
||||||
toolchain.minimal))
|
|
||||||
.override {
|
|
||||||
extensions = ["rustc-codegen-cranelift-preview"];
|
|
||||||
}
|
|
||||||
else pkgs.rust-bin.stable.latest.minimal;
|
|
||||||
|
|
||||||
craneLib = (crane.mkLib pkgs).overrideToolchain rust_min;
|
craneLib = (crane.mkLib pkgs).overrideToolchain rust;
|
||||||
|
|
||||||
nativeBuildInputs = with pkgs; [
|
nativeBuildInputs = with pkgs; [
|
||||||
pkg-config
|
pkg-config
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
# build
|
|
||||||
/target
|
|
||||||
/result
|
|
||||||
|
|
||||||
# lua_macros is a library
|
|
||||||
Cargo.lock
|
|
|
@ -1,20 +0,0 @@
|
||||||
[package]
|
|
||||||
name = "keymaps"
|
|
||||||
version = "0.1.0"
|
|
||||||
edition = "2021"
|
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
|
||||||
|
|
||||||
[features]
|
|
||||||
default = []
|
|
||||||
crossterm = ["dep:crossterm"]
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
crossterm = { version = "0.25", optional = true }
|
|
||||||
log = "0.4.20"
|
|
||||||
thiserror = "1.0.50"
|
|
||||||
pest = "2.7.5"
|
|
||||||
pest_derive = {version = "2.7.5", features = ["grammar-extras"]}
|
|
||||||
|
|
||||||
[dev-dependencies]
|
|
||||||
pretty_assertions = "1.4.0"
|
|
|
@ -1,46 +0,0 @@
|
||||||
use std::{fmt::Display, num::ParseIntError};
|
|
||||||
|
|
||||||
use thiserror::Error;
|
|
||||||
|
|
||||||
use crate::key_repr::{key, keys, Keys};
|
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
|
||||||
pub enum TrieInsertError<V: Display> {
|
|
||||||
#[error("The key ('{0}') contains nodes, which already have a value set!")]
|
|
||||||
KeyPathBlocked(Keys),
|
|
||||||
|
|
||||||
#[error("The key ('{key}') already has a value associatet with it, which is: '{value}'")]
|
|
||||||
KeyAlreadySet { key: Keys, value: V },
|
|
||||||
|
|
||||||
#[error("The node accessed by this key ('{0}') already has children! You can not set a value for it")]
|
|
||||||
NodeHasChildren(Keys),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
|
||||||
pub enum KeyParseError {
|
|
||||||
#[error("This key expression could not be parsed, see the error message for more: {0}")]
|
|
||||||
RawParseError(#[from] pest::error::Error<key::Rule>),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
|
||||||
pub enum KeysParseError {
|
|
||||||
#[error(
|
|
||||||
"This chain of key expressions could not be parsed, see the error message for more: {0}"
|
|
||||||
)]
|
|
||||||
RawParseError(#[from] pest::error::Error<keys::Rule>),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
|
||||||
pub enum KeyValueParseError {
|
|
||||||
#[error("The String ('{0}') is not a correct special key name!")]
|
|
||||||
NoMatch(String),
|
|
||||||
|
|
||||||
#[error("The number associate with the F key ('{0}') can't be parsed as u8!")]
|
|
||||||
CantParseFNumber(#[from] ParseIntError),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
|
||||||
pub enum KeyFromCrossterm {
|
|
||||||
#[error("Can not parse non Key event to a Key code: ('{0:?}')")]
|
|
||||||
OnlyKey(crossterm::event::Event),
|
|
||||||
}
|
|
|
@ -1,76 +0,0 @@
|
||||||
use crossterm::event::{Event, KeyCode, KeyEvent, KeyEventKind, KeyEventState, KeyModifiers};
|
|
||||||
|
|
||||||
use crate::{error, key_repr::KeyValue};
|
|
||||||
|
|
||||||
use super::Key;
|
|
||||||
|
|
||||||
impl Into<Event> for Key {
|
|
||||||
fn into(self) -> Event {
|
|
||||||
let mut modifiers;
|
|
||||||
{
|
|
||||||
modifiers = KeyModifiers::all();
|
|
||||||
if !self.alt {
|
|
||||||
modifiers.remove(KeyModifiers::ALT);
|
|
||||||
}
|
|
||||||
if !self.ctrl {
|
|
||||||
modifiers.remove(KeyModifiers::CONTROL);
|
|
||||||
}
|
|
||||||
if !self.meta {
|
|
||||||
modifiers.remove(KeyModifiers::META);
|
|
||||||
modifiers.remove(KeyModifiers::SUPER);
|
|
||||||
}
|
|
||||||
if !self.shift {
|
|
||||||
modifiers.remove(KeyModifiers::SHIFT);
|
|
||||||
}
|
|
||||||
modifiers.remove(KeyModifiers::HYPER);
|
|
||||||
modifiers.remove(KeyModifiers::META);
|
|
||||||
if self.alt || self.ctrl || self.meta || self.shift {
|
|
||||||
modifiers.remove(KeyModifiers::NONE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let output = Event::Key(KeyEvent {
|
|
||||||
code: {
|
|
||||||
if let Some(KeyValue::Char(char)) = self.value {
|
|
||||||
KeyCode::Char(char)
|
|
||||||
} else {
|
|
||||||
self.value.unwrap_or(KeyValue::Null).into()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
modifiers,
|
|
||||||
kind: KeyEventKind::Press,
|
|
||||||
state: KeyEventState::NONE,
|
|
||||||
});
|
|
||||||
output
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TryFrom<&Event> for Key {
|
|
||||||
type Error = error::KeyFromCrossterm;
|
|
||||||
|
|
||||||
fn try_from(value: &Event) -> std::result::Result<Self, Self::Error> {
|
|
||||||
let mut output_key: Key = Key::new();
|
|
||||||
match value {
|
|
||||||
Event::Key(key_event) => {
|
|
||||||
{
|
|
||||||
let key_mods = key_event.modifiers;
|
|
||||||
|
|
||||||
output_key.alt = KeyModifiers::intersects(&key_mods, KeyModifiers::ALT);
|
|
||||||
output_key.ctrl = KeyModifiers::intersects(&key_mods, KeyModifiers::CONTROL);
|
|
||||||
output_key.meta = KeyModifiers::intersects(&key_mods, KeyModifiers::META)
|
|
||||||
|| KeyModifiers::intersects(&key_mods, KeyModifiers::SUPER);
|
|
||||||
output_key.shift = KeyModifiers::intersects(&key_mods, KeyModifiers::SHIFT);
|
|
||||||
// let hyper = KeyModifiers::intersects(&key_mods, KeyModifiers::HYPER);
|
|
||||||
// let none = KeyModifiers::intersects(&key_mods, KeyModifiers::NONE);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
output_key.value = Some(key_event.code.into());
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(output_key)
|
|
||||||
}
|
|
||||||
event => Err(error::KeyFromCrossterm::OnlyKey(event.to_owned())),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,70 +0,0 @@
|
||||||
#[cfg(feature = "crossterm")]
|
|
||||||
mod crossterm;
|
|
||||||
|
|
||||||
mod parsing;
|
|
||||||
|
|
||||||
use std::fmt::Display;
|
|
||||||
|
|
||||||
use pest_derive::Parser;
|
|
||||||
|
|
||||||
use super::KeyValue;
|
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Default, Parser)]
|
|
||||||
#[grammar = "./key_repr/key_representation.pest"]
|
|
||||||
pub struct Key {
|
|
||||||
// Modifiers
|
|
||||||
pub(super) alt: bool,
|
|
||||||
pub(super) ctrl: bool,
|
|
||||||
pub(super) meta: bool,
|
|
||||||
pub(super) shift: bool,
|
|
||||||
|
|
||||||
pub(super) value: Option<KeyValue>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Key {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Self::default()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn value(&self) -> Option<&KeyValue> {
|
|
||||||
self.value.as_ref()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn to_string_repr(self) -> String {
|
|
||||||
let mut output = String::new();
|
|
||||||
if self.alt || self.ctrl || self.meta || self.shift {
|
|
||||||
output.push('<')
|
|
||||||
}
|
|
||||||
if self.alt {
|
|
||||||
output.push('A');
|
|
||||||
}
|
|
||||||
if self.ctrl {
|
|
||||||
output.push('C');
|
|
||||||
}
|
|
||||||
if self.meta {
|
|
||||||
output.push('M');
|
|
||||||
}
|
|
||||||
if self.shift {
|
|
||||||
output.push('S');
|
|
||||||
}
|
|
||||||
if self.alt || self.ctrl || self.meta || self.shift {
|
|
||||||
output.push('-')
|
|
||||||
}
|
|
||||||
output.push_str(
|
|
||||||
&self
|
|
||||||
.value
|
|
||||||
.expect("There can be no `None`s here, if the Key comes from the public api")
|
|
||||||
.to_string(),
|
|
||||||
);
|
|
||||||
if self.alt || self.ctrl || self.meta || self.shift {
|
|
||||||
output.push('>')
|
|
||||||
}
|
|
||||||
output
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Display for Key {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
||||||
f.write_str(&self.to_string_repr())
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,213 +0,0 @@
|
||||||
use std::{fmt::Debug, hash::Hash, marker, str::FromStr};
|
|
||||||
|
|
||||||
use pest::{iterators::Pair, Parser};
|
|
||||||
|
|
||||||
use crate::{error, key_repr::{KeyValue, key::Rule}};
|
|
||||||
|
|
||||||
use super::Key;
|
|
||||||
|
|
||||||
impl Key {
|
|
||||||
pub fn from_pair<R>(pair: Pair<R>) -> Self
|
|
||||||
where
|
|
||||||
R: marker::Copy + Debug + Hash + Ord,
|
|
||||||
{
|
|
||||||
let pairs = pair.into_inner();
|
|
||||||
let mut output = Self::default();
|
|
||||||
|
|
||||||
let modifiers: Vec<_> = pairs.clone().find_tagged("modifiers").collect();
|
|
||||||
let values: Vec<_> = pairs.clone().find_tagged("value").collect();
|
|
||||||
let special_keys: Vec<_> = pairs.find_tagged("special_key").collect();
|
|
||||||
|
|
||||||
for modifier in modifiers {
|
|
||||||
match modifier.as_span().as_str() {
|
|
||||||
"A" => output.alt = true,
|
|
||||||
"C" => output.ctrl = true,
|
|
||||||
"M" => output.meta = true,
|
|
||||||
"S" => output.shift = true,
|
|
||||||
_ => unreachable!("This modifier should not have been parsed"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if values.is_empty() {
|
|
||||||
// Check that we have parsed *something*
|
|
||||||
debug_assert!(!special_keys.is_empty());
|
|
||||||
// Check, that we have only parsed one special key
|
|
||||||
debug_assert_eq!(special_keys.len(), 1);
|
|
||||||
|
|
||||||
let special_key_value: KeyValue = special_keys
|
|
||||||
.first()
|
|
||||||
.expect("This should exist (and be the only value)")
|
|
||||||
.as_str()
|
|
||||||
.parse()
|
|
||||||
.expect("This was parsed, and should thus be a valid special_key");
|
|
||||||
output.value = Some(special_key_value);
|
|
||||||
} else {
|
|
||||||
// Check, that we have only parsed one key
|
|
||||||
debug_assert_eq!(values.len(), 1);
|
|
||||||
|
|
||||||
let key_str = values.first().expect("This should exist").as_str();
|
|
||||||
// Check that we really only have a one char &str
|
|
||||||
debug_assert_eq!(key_str.chars().count(), 1);
|
|
||||||
|
|
||||||
let key_value: KeyValue = KeyValue::Char(
|
|
||||||
key_str
|
|
||||||
.chars()
|
|
||||||
.nth(0)
|
|
||||||
.expect("This &str should have a length of exactly one char"),
|
|
||||||
);
|
|
||||||
|
|
||||||
output.value = Some(key_value);
|
|
||||||
}
|
|
||||||
output
|
|
||||||
}
|
|
||||||
// pub(super) fn parse_old(chars: &mut Chars) -> anyhow::Result<Self> {
|
|
||||||
// assert_eq!(chars.pop().expect("This is a developer error"), '<');
|
|
||||||
// let mut parse_buffer: Vec<char> = Vec::new();
|
|
||||||
//
|
|
||||||
// let mut reached_non_modifier = false;
|
|
||||||
// let mut output_key_filled = false;
|
|
||||||
// let mut output_key = Key::new();
|
|
||||||
// while let Some(char) = chars.pop() {
|
|
||||||
// if char == '>' {
|
|
||||||
// break;
|
|
||||||
// } else {
|
|
||||||
// if char.is_ascii_uppercase()
|
|
||||||
// || char.is_numeric() && !reached_non_modifier && !output_key_filled
|
|
||||||
// {
|
|
||||||
// parse_buffer.push(char);
|
|
||||||
// } else if char == '-' && !reached_non_modifier && !output_key_filled {
|
|
||||||
// // We moved to the modified char
|
|
||||||
// reached_non_modifier = true;
|
|
||||||
//
|
|
||||||
// // Our parse_buffer should only contain modifiers:
|
|
||||||
// let mut alt = false;
|
|
||||||
// let mut ctrl = false;
|
|
||||||
// let mut meta = false;
|
|
||||||
// let mut shift = false;
|
|
||||||
//
|
|
||||||
// for char in &parse_buffer {
|
|
||||||
// match char {
|
|
||||||
// 'A' => alt = true,
|
|
||||||
// 'C' => ctrl = true,
|
|
||||||
// 'M' => meta = true,
|
|
||||||
// 'S' => shift = true,
|
|
||||||
// char => bail!(
|
|
||||||
// "The char ('{}') is not a valid descriptor of a modifier",
|
|
||||||
// char
|
|
||||||
// ),
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// output_key = Key {
|
|
||||||
// alt,
|
|
||||||
// ctrl,
|
|
||||||
// meta,
|
|
||||||
// shift,
|
|
||||||
// value: None,
|
|
||||||
// };
|
|
||||||
// } else if reached_non_modifier && !output_key_filled {
|
|
||||||
// if char == '<' {
|
|
||||||
// chars.prepend('<');
|
|
||||||
// let key = Key::parse(chars)?;
|
|
||||||
// output_key = output_key.merge_with(key);
|
|
||||||
// } else {
|
|
||||||
// output_key.value = Some(KeyValue::Char(char));
|
|
||||||
// }
|
|
||||||
// output_key_filled = true;
|
|
||||||
// } else {
|
|
||||||
// bail!(
|
|
||||||
// "Your can not put a this char here!
|
|
||||||
// parse_buffer: '{}';
|
|
||||||
// char: '{}';
|
|
||||||
// chars: '{:#?}';
|
|
||||||
// output_key: '{:#?}' ",
|
|
||||||
// &parse_buffer.iter().collect::<String>(),
|
|
||||||
// &char,
|
|
||||||
// &chars,
|
|
||||||
// &output_key
|
|
||||||
// )
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// if output_key_filled {
|
|
||||||
// Ok(output_key)
|
|
||||||
// } else {
|
|
||||||
// let mut parse_buffer = Chars(parse_buffer.into());
|
|
||||||
// let get_output = |value: KeyValue| -> Key {
|
|
||||||
// let key = Key {
|
|
||||||
// alt: false,
|
|
||||||
// ctrl: false,
|
|
||||||
// meta: false,
|
|
||||||
// shift: false,
|
|
||||||
// value: Some(value),
|
|
||||||
// };
|
|
||||||
//
|
|
||||||
// return key.merge_with(output_key);
|
|
||||||
// };
|
|
||||||
// if let Some(char) = parse_buffer.peek() {
|
|
||||||
// if char == &'F' {
|
|
||||||
// let _f = parse_buffer.pop();
|
|
||||||
// let number: u8 = parse_buffer.to_string().parse().with_context(|| {
|
|
||||||
// format!("Failed to parse buffer ('{}') as u8", &parse_buffer)
|
|
||||||
// })?;
|
|
||||||
// Ok(get_output(KeyValue::F(number)))
|
|
||||||
// } else {
|
|
||||||
// match &parse_buffer.to_string()[..] {
|
|
||||||
// "BACKSPACE" => Ok(get_output(KeyValue::Backspace)),
|
|
||||||
// "ENTER" => Ok(get_output(KeyValue::Enter)),
|
|
||||||
// "LEFT" => Ok(get_output(KeyValue::Left)),
|
|
||||||
// "RIGHT" => Ok(get_output(KeyValue::Right)),
|
|
||||||
// "UP" => Ok(get_output(KeyValue::Up)),
|
|
||||||
// "DOWN" => Ok(get_output(KeyValue::Down)),
|
|
||||||
// "HOME" => Ok(get_output(KeyValue::Home)),
|
|
||||||
// "END" => Ok(get_output(KeyValue::End)),
|
|
||||||
// "PAGEUP" => Ok(get_output(KeyValue::PageUp)),
|
|
||||||
// "PAGEDOWN" => Ok(get_output(KeyValue::PageDown)),
|
|
||||||
// "TAB" => Ok(get_output(KeyValue::Tab)),
|
|
||||||
// "BACKTAB" => Ok(get_output(KeyValue::BackTab)),
|
|
||||||
// "DELETE" => Ok(get_output(KeyValue::Delete)),
|
|
||||||
// "INSERT" => Ok(get_output(KeyValue::Insert)),
|
|
||||||
// "ESC" => Ok(get_output(KeyValue::Esc)),
|
|
||||||
// "CAPSLOCK" => Ok(get_output(KeyValue::CapsLock)),
|
|
||||||
// "SCROLLlOCK" => Ok(get_output(KeyValue::ScrollLock)),
|
|
||||||
// "NUMLOCK" => Ok(get_output(KeyValue::NumLock)),
|
|
||||||
// "PRINTSCREEN" => Ok(get_output(KeyValue::PrintScreen)),
|
|
||||||
// "PAUSE" => Ok(get_output(KeyValue::Pause)),
|
|
||||||
// "MENU" => Ok(get_output(KeyValue::Menu)),
|
|
||||||
// "KEYPADBEGIN" => Ok(get_output(KeyValue::KeypadBegin)),
|
|
||||||
//
|
|
||||||
// "DASH" => Ok(get_output(KeyValue::Char('-'))),
|
|
||||||
// "ANGULAR_BRACKET_OPEN" | "ABO" => Ok(get_output(KeyValue::Char('<'))),
|
|
||||||
// "ANGULAR_BRACKET_CLOSE" | "ABC" => Ok(get_output(KeyValue::Char('>'))),
|
|
||||||
// other_str => bail!(
|
|
||||||
// "The String ('{}') is not a correct special key name!",
|
|
||||||
// other_str
|
|
||||||
// ),
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// bail!(
|
|
||||||
// "You need to put something into the angulare brackets (<>)
|
|
||||||
// parse_buffer: '{}';
|
|
||||||
// chars: '{:#?}';",
|
|
||||||
// &parse_buffer,
|
|
||||||
// &chars,
|
|
||||||
// )
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FromStr for Key {
|
|
||||||
type Err = error::KeyParseError;
|
|
||||||
|
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
||||||
let mut key_pairs: Vec<_> = Self::parse(Rule::key, s)?.find_tagged("key").collect();
|
|
||||||
debug_assert_eq!(key_pairs.len(), 1);
|
|
||||||
let key: Key = Self::from_pair::<Rule>(
|
|
||||||
key_pairs
|
|
||||||
.pop()
|
|
||||||
.expect("This should contain only this first (and last) element"),
|
|
||||||
);
|
|
||||||
Ok(key)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,60 +0,0 @@
|
||||||
angular_bracket_open = _{ "<" }
|
|
||||||
abo = _{ angular_bracket_open }
|
|
||||||
angular_bracket_close = _{ ">" }
|
|
||||||
abc = _{ angular_bracket_close }
|
|
||||||
|
|
||||||
special_key = {
|
|
||||||
"BACKSPACE"
|
|
||||||
| "ENTER"
|
|
||||||
| "LEFT"
|
|
||||||
| "RIGHT"
|
|
||||||
| "UP"
|
|
||||||
| "DOWN"
|
|
||||||
| "HOME"
|
|
||||||
| "END"
|
|
||||||
| "PAGEUP"
|
|
||||||
| "PAGEDOWN"
|
|
||||||
| "TAB"
|
|
||||||
| "BACKTAB"
|
|
||||||
| "DELETE"
|
|
||||||
| "INSERT"
|
|
||||||
| "ESC"
|
|
||||||
| "CAPSLOCK"
|
|
||||||
| "SCROLLlOCK"
|
|
||||||
| "NUMLOCK"
|
|
||||||
| "PRINTSCREEN"
|
|
||||||
| "PAUSE"
|
|
||||||
| "MENU"
|
|
||||||
| "KEYPADBEGIN"
|
|
||||||
| ("F" ~ ASCII_DIGIT+)
|
|
||||||
|
|
||||||
// Aliases to make using them easier, as they are also used in the notation
|
|
||||||
| "DASH"
|
|
||||||
| "ANGULAR_BRACKET_OPEN"
|
|
||||||
| "ABO"
|
|
||||||
| "ANGULAR_BRACKET_CLOSE"
|
|
||||||
| "ABC"
|
|
||||||
}
|
|
||||||
|
|
||||||
modifier = {
|
|
||||||
"A" | // Alt
|
|
||||||
"C" | // Ctrl
|
|
||||||
"M" | // Meta
|
|
||||||
"S" // Shift
|
|
||||||
}
|
|
||||||
|
|
||||||
value = {
|
|
||||||
!abo ~ ANY
|
|
||||||
}
|
|
||||||
|
|
||||||
raw_key = {
|
|
||||||
((abo ~ (#modifiers = modifier)+ ~ "-" ~ (#special_key = (abo ~ special_key ~ abc) | #value = value) ~ abc) | #special_key = (abo ~ special_key ~ abc) | #value = value)
|
|
||||||
}
|
|
||||||
|
|
||||||
// api
|
|
||||||
key = {
|
|
||||||
SOI ~ #key = raw_key ~ EOI
|
|
||||||
}
|
|
||||||
keys = {
|
|
||||||
SOI ~ (#keys = raw_key)+ ~ EOI
|
|
||||||
}
|
|
|
@ -1,123 +0,0 @@
|
||||||
#[cfg(feature = "crossterm")]
|
|
||||||
mod crossterm;
|
|
||||||
|
|
||||||
use std::{
|
|
||||||
fmt::{Display, Write},
|
|
||||||
str::FromStr,
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::error;
|
|
||||||
|
|
||||||
// taken directly from crossterm
|
|
||||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
|
|
||||||
pub enum KeyValue {
|
|
||||||
Backspace,
|
|
||||||
Enter,
|
|
||||||
Left,
|
|
||||||
Right,
|
|
||||||
Up,
|
|
||||||
Down,
|
|
||||||
Home,
|
|
||||||
End,
|
|
||||||
PageUp,
|
|
||||||
PageDown,
|
|
||||||
Tab,
|
|
||||||
BackTab,
|
|
||||||
Delete,
|
|
||||||
Insert,
|
|
||||||
F(u8),
|
|
||||||
Char(char),
|
|
||||||
Null, // TODO(@soispha): Should we keep this key (as it's effectively not a key)?<2023-10-15>
|
|
||||||
Esc,
|
|
||||||
CapsLock,
|
|
||||||
ScrollLock,
|
|
||||||
NumLock,
|
|
||||||
PrintScreen,
|
|
||||||
Pause,
|
|
||||||
Menu,
|
|
||||||
KeypadBegin,
|
|
||||||
// TODO(@soispha): We could add support for these: <2023-10-15>
|
|
||||||
// Media(MediaKeyCode),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FromStr for KeyValue {
|
|
||||||
type Err = error::KeyValueParseError;
|
|
||||||
|
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
||||||
match s {
|
|
||||||
"BACKSPACE" => Ok(Self::Backspace),
|
|
||||||
"ENTER" => Ok(Self::Enter),
|
|
||||||
"LEFT" => Ok(Self::Left),
|
|
||||||
"RIGHT" => Ok(Self::Right),
|
|
||||||
"UP" => Ok(Self::Up),
|
|
||||||
"DOWN" => Ok(Self::Down),
|
|
||||||
"HOME" => Ok(Self::Home),
|
|
||||||
"END" => Ok(Self::End),
|
|
||||||
"PAGEUP" => Ok(Self::PageUp),
|
|
||||||
"PAGEDOWN" => Ok(Self::PageDown),
|
|
||||||
"TAB" => Ok(Self::Tab),
|
|
||||||
"BACKTAB" => Ok(Self::BackTab),
|
|
||||||
"DELETE" => Ok(Self::Delete),
|
|
||||||
"INSERT" => Ok(Self::Insert),
|
|
||||||
"ESC" => Ok(Self::Esc),
|
|
||||||
"CAPSLOCK" => Ok(Self::CapsLock),
|
|
||||||
"SCROLLlOCK" => Ok(Self::ScrollLock),
|
|
||||||
"NUMLOCK" => Ok(Self::NumLock),
|
|
||||||
"PRINTSCREEN" => Ok(Self::PrintScreen),
|
|
||||||
"PAUSE" => Ok(Self::Pause),
|
|
||||||
"MENU" => Ok(Self::Menu),
|
|
||||||
"KEYPADBEGIN" => Ok(Self::KeypadBegin),
|
|
||||||
f_str
|
|
||||||
// FIXME(@soispha): This should check the full string, as something
|
|
||||||
// like 'FA12' would also match this case <2023-11-07>
|
|
||||||
if f_str.starts_with('F')
|
|
||||||
&& f_str.ends_with(['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']) =>
|
|
||||||
{
|
|
||||||
Ok(Self::F(f_str.trim_matches('F').parse()?))
|
|
||||||
}
|
|
||||||
|
|
||||||
"DASH" => Ok(Self::Char('-')),
|
|
||||||
"ANGULAR_BRACKET_OPEN" | "ABO" => Ok(Self::Char('<')),
|
|
||||||
"ANGULAR_BRACKET_CLOSE" | "ABC" => Ok(Self::Char('>')),
|
|
||||||
other_str => Err(Self::Err::NoMatch(other_str.to_owned())),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Display for KeyValue {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
||||||
let mut w = |str| f.write_str(str);
|
|
||||||
match self {
|
|
||||||
KeyValue::Backspace => w("<BACKSPACE>"),
|
|
||||||
KeyValue::Enter => w("<ENTER>"),
|
|
||||||
KeyValue::Left => w("<LEFT>"),
|
|
||||||
KeyValue::Right => w("<RIGHT>"),
|
|
||||||
KeyValue::Up => w("<UP>"),
|
|
||||||
KeyValue::Down => w("<DOWN>"),
|
|
||||||
KeyValue::Home => w("<HOME>"),
|
|
||||||
KeyValue::End => w("<END>"),
|
|
||||||
KeyValue::PageUp => w("<PAGEUP>"),
|
|
||||||
KeyValue::PageDown => w("<PAGEDOWN>"),
|
|
||||||
KeyValue::Tab => w("<TAB>"),
|
|
||||||
KeyValue::BackTab => w("<BACKTAB>"),
|
|
||||||
KeyValue::Delete => w("<DELETE>"),
|
|
||||||
KeyValue::Insert => w("<INSERT>"),
|
|
||||||
KeyValue::F(n) => f.write_fmt(format_args!("<F{}>", n)),
|
|
||||||
KeyValue::Char(c) => match c {
|
|
||||||
'<' => w("<ANGULAR_BRACKET_OPEN>"),
|
|
||||||
'>' => w("<ANGULAR_BRACKET_CLOSE>"),
|
|
||||||
'-' => w("<DASH>"),
|
|
||||||
c => f.write_char(*c),
|
|
||||||
},
|
|
||||||
KeyValue::Null => w("<NULL>"),
|
|
||||||
KeyValue::Esc => w("<ESC>"),
|
|
||||||
KeyValue::CapsLock => w("<CAPSLOCK>"),
|
|
||||||
KeyValue::ScrollLock => w("<SCROLLLOCK>"),
|
|
||||||
KeyValue::NumLock => w("<NUMLOCK>"),
|
|
||||||
KeyValue::PrintScreen => w("<PRINTSCREEN>"),
|
|
||||||
KeyValue::Pause => w("<PAUSE>"),
|
|
||||||
KeyValue::Menu => w("<MENU>"),
|
|
||||||
KeyValue::KeypadBegin => w("<KEYPADBEGIN>"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,3 +0,0 @@
|
||||||
pub mod key_repr;
|
|
||||||
pub mod trie;
|
|
||||||
pub mod error;
|
|
|
@ -10,4 +10,4 @@ proc-macro = true
|
||||||
convert_case = "0.6.0"
|
convert_case = "0.6.0"
|
||||||
proc-macro2 = "1.0.69"
|
proc-macro2 = "1.0.69"
|
||||||
quote = "1.0.33"
|
quote = "1.0.33"
|
||||||
syn = { version = "2.0.39", features = ["extra-traits", "full", "parsing"] }
|
syn = { version = "2.0.38", features = ["extra-traits", "full", "parsing"] }
|
||||||
|
|
|
@ -3,10 +3,6 @@ use std::{collections::HashMap, str::FromStr};
|
||||||
use anyhow::{Error, Result};
|
use anyhow::{Error, Result};
|
||||||
use cli_log::{info, trace, warn};
|
use cli_log::{info, trace, warn};
|
||||||
use crossterm::event::Event;
|
use crossterm::event::Event;
|
||||||
use keymaps::{
|
|
||||||
key_repr::{Key, Keys},
|
|
||||||
trie::Node,
|
|
||||||
};
|
|
||||||
use tokio::sync::oneshot;
|
use tokio::sync::oneshot;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -16,6 +12,10 @@ use crate::{
|
||||||
Api, Command, Debug, Keymaps, Raw, Trinitrix, Ui,
|
Api, Command, Debug, Keymaps, Raw, Trinitrix, Ui,
|
||||||
},
|
},
|
||||||
events::EventStatus,
|
events::EventStatus,
|
||||||
|
keymappings::{
|
||||||
|
key::{Key, Keys},
|
||||||
|
trie::Node,
|
||||||
|
},
|
||||||
status::State,
|
status::State,
|
||||||
App,
|
App,
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use cli_log::info;
|
use cli_log::info;
|
||||||
use crossterm::event::Event as CrosstermEvent;
|
use crossterm::event::Event as CrosstermEvent;
|
||||||
use keymaps::key_repr::{Key, Keys};
|
|
||||||
|
|
||||||
use crate::app::{
|
use crate::app::{
|
||||||
command_interface::{Api::Raw, Command, Raw::SendInputUnprocessed, Trinitrix::Api},
|
command_interface::{Api::Raw, Command, Raw::SendInputUnprocessed, Trinitrix::Api},
|
||||||
events::{Event, EventStatus},
|
events::{Event, EventStatus},
|
||||||
|
keymappings::key::{Key, Keys},
|
||||||
status::State,
|
status::State,
|
||||||
App,
|
App,
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
use std::{collections::VecDeque, fmt::Display};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub(super) struct Chars(pub(super) VecDeque<char>);
|
||||||
|
impl Chars {
|
||||||
|
pub(super) fn peek(&self) -> Option<&char> {
|
||||||
|
self.0.front()
|
||||||
|
}
|
||||||
|
pub(super) fn pop(&mut self) -> Option<char> {
|
||||||
|
self.0.pop_front()
|
||||||
|
}
|
||||||
|
pub(super) fn prepend(&mut self, char_to_prepend: char) {
|
||||||
|
let mut new_vec = VecDeque::with_capacity(self.0.len() + 1);
|
||||||
|
new_vec.push_back(char_to_prepend);
|
||||||
|
new_vec.append(&mut self.0);
|
||||||
|
|
||||||
|
self.0 = new_vec;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for Chars {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
f.write_str(&self.0.iter().collect::<String>()[..])
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,357 @@
|
||||||
|
use std::{fmt::Display, str::FromStr};
|
||||||
|
|
||||||
|
use anyhow::{bail, Context};
|
||||||
|
use cli_log::{debug, info};
|
||||||
|
use crossterm::event::{Event, KeyCode, KeyEvent, KeyEventKind, KeyEventState, KeyModifiers};
|
||||||
|
|
||||||
|
use super::{Chars, KeyValue, Keys};
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
|
||||||
|
pub struct Key {
|
||||||
|
// Modifiers
|
||||||
|
pub(super) alt: bool,
|
||||||
|
pub(super) ctrl: bool,
|
||||||
|
pub(super) meta: bool,
|
||||||
|
pub(super) shift: bool,
|
||||||
|
|
||||||
|
pub(super) value: Option<KeyValue>,
|
||||||
|
}
|
||||||
|
impl Key {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Key {
|
||||||
|
alt: false,
|
||||||
|
ctrl: false,
|
||||||
|
meta: false,
|
||||||
|
shift: false,
|
||||||
|
value: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn value(&self) -> Option<&KeyValue> {
|
||||||
|
self.value.as_ref()
|
||||||
|
}
|
||||||
|
pub fn to_string_repr(self) -> String {
|
||||||
|
let mut output = String::new();
|
||||||
|
if self.alt || self.ctrl || self.meta || self.shift {
|
||||||
|
output.push('<')
|
||||||
|
}
|
||||||
|
if self.alt {
|
||||||
|
output.push('A');
|
||||||
|
}
|
||||||
|
if self.ctrl {
|
||||||
|
output.push('C');
|
||||||
|
}
|
||||||
|
if self.meta {
|
||||||
|
output.push('M');
|
||||||
|
}
|
||||||
|
if self.shift {
|
||||||
|
output.push('S');
|
||||||
|
}
|
||||||
|
if self.alt || self.ctrl || self.meta || self.shift {
|
||||||
|
output.push('-')
|
||||||
|
}
|
||||||
|
output.push_str(
|
||||||
|
&self
|
||||||
|
.value
|
||||||
|
.expect("There can be no Nones here, if the Key comes from the public api")
|
||||||
|
.to_string(),
|
||||||
|
);
|
||||||
|
if self.alt || self.ctrl || self.meta || self.shift {
|
||||||
|
output.push('>')
|
||||||
|
}
|
||||||
|
output
|
||||||
|
}
|
||||||
|
fn merge_with(mut self, other: Key) -> Self {
|
||||||
|
// Modifiers
|
||||||
|
self.alt = self.alt || other.alt;
|
||||||
|
self.ctrl = self.ctrl || other.ctrl;
|
||||||
|
self.meta = self.meta || other.meta;
|
||||||
|
self.shift = self.shift || other.shift;
|
||||||
|
|
||||||
|
self.value = Some(self.value.unwrap_or(other.value.unwrap_or(KeyValue::Null)));
|
||||||
|
self
|
||||||
|
}
|
||||||
|
pub(super) fn parse(chars: &mut Chars) -> anyhow::Result<Self> {
|
||||||
|
assert_eq!(chars.pop().expect("This is a developer error"), '<');
|
||||||
|
let mut parse_buffer: Vec<char> = Vec::new();
|
||||||
|
|
||||||
|
let mut reached_non_modifier = false;
|
||||||
|
let mut output_key_filled = false;
|
||||||
|
let mut output_key = Key::new();
|
||||||
|
while let Some(char) = chars.pop() {
|
||||||
|
if char == '>' {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
if char.is_ascii_uppercase()
|
||||||
|
|| char.is_numeric() && !reached_non_modifier && !output_key_filled
|
||||||
|
{
|
||||||
|
parse_buffer.push(char);
|
||||||
|
} else if char == '-' && !reached_non_modifier && !output_key_filled {
|
||||||
|
// We moved to the modified char
|
||||||
|
reached_non_modifier = true;
|
||||||
|
|
||||||
|
// Our parse_buffer should only contain modifiers:
|
||||||
|
let mut alt = false;
|
||||||
|
let mut ctrl = false;
|
||||||
|
let mut meta = false;
|
||||||
|
let mut shift = false;
|
||||||
|
|
||||||
|
for char in &parse_buffer {
|
||||||
|
match char {
|
||||||
|
'A' => alt = true,
|
||||||
|
'C' => ctrl = true,
|
||||||
|
'M' => meta = true,
|
||||||
|
'S' => shift = true,
|
||||||
|
char => bail!(
|
||||||
|
"The char ('{}') is not a valid descriptor of a modifier",
|
||||||
|
char
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
output_key = Key {
|
||||||
|
alt,
|
||||||
|
ctrl,
|
||||||
|
meta,
|
||||||
|
shift,
|
||||||
|
value: None,
|
||||||
|
};
|
||||||
|
} else if reached_non_modifier && !output_key_filled {
|
||||||
|
if char == '<' {
|
||||||
|
chars.prepend('<');
|
||||||
|
let key = Key::parse(chars)?;
|
||||||
|
output_key = output_key.merge_with(key);
|
||||||
|
} else {
|
||||||
|
output_key.value = Some(KeyValue::Char(char));
|
||||||
|
}
|
||||||
|
output_key_filled = true;
|
||||||
|
} else {
|
||||||
|
bail!(
|
||||||
|
"Your can not put a this char here!
|
||||||
|
parse_buffer: '{}';
|
||||||
|
char: '{}';
|
||||||
|
chars: '{:#?}';
|
||||||
|
output_key: '{:#?}' ",
|
||||||
|
&parse_buffer.iter().collect::<String>(),
|
||||||
|
&char,
|
||||||
|
&chars,
|
||||||
|
&output_key
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if output_key_filled {
|
||||||
|
Ok(output_key)
|
||||||
|
} else {
|
||||||
|
let mut parse_buffer = Chars(parse_buffer.into());
|
||||||
|
let get_output = |value: KeyValue| -> Key {
|
||||||
|
let key = Key {
|
||||||
|
alt: false,
|
||||||
|
ctrl: false,
|
||||||
|
meta: false,
|
||||||
|
shift: false,
|
||||||
|
value: Some(value),
|
||||||
|
};
|
||||||
|
|
||||||
|
return key.merge_with(output_key);
|
||||||
|
};
|
||||||
|
if let Some(char) = parse_buffer.peek() {
|
||||||
|
if char == &'F' {
|
||||||
|
let _f = parse_buffer.pop();
|
||||||
|
let number: u8 = parse_buffer.to_string().parse().with_context(|| {
|
||||||
|
format!("Failed to parse buffer ('{}') as u8", &parse_buffer)
|
||||||
|
})?;
|
||||||
|
Ok(get_output(KeyValue::F(number)))
|
||||||
|
} else {
|
||||||
|
match &parse_buffer.to_string()[..] {
|
||||||
|
"BACKSPACE" => Ok(get_output(KeyValue::Backspace)),
|
||||||
|
"ENTER" => Ok(get_output(KeyValue::Enter)),
|
||||||
|
"LEFT" => Ok(get_output(KeyValue::Left)),
|
||||||
|
"RIGHT" => Ok(get_output(KeyValue::Right)),
|
||||||
|
"UP" => Ok(get_output(KeyValue::Up)),
|
||||||
|
"DOWN" => Ok(get_output(KeyValue::Down)),
|
||||||
|
"HOME" => Ok(get_output(KeyValue::Home)),
|
||||||
|
"END" => Ok(get_output(KeyValue::End)),
|
||||||
|
"PAGEUP" => Ok(get_output(KeyValue::PageUp)),
|
||||||
|
"PAGEDOWN" => Ok(get_output(KeyValue::PageDown)),
|
||||||
|
"TAB" => Ok(get_output(KeyValue::Tab)),
|
||||||
|
"BACKTAB" => Ok(get_output(KeyValue::BackTab)),
|
||||||
|
"DELETE" => Ok(get_output(KeyValue::Delete)),
|
||||||
|
"INSERT" => Ok(get_output(KeyValue::Insert)),
|
||||||
|
"ESC" => Ok(get_output(KeyValue::Esc)),
|
||||||
|
"CAPSLOCK" => Ok(get_output(KeyValue::CapsLock)),
|
||||||
|
"SCROLLlOCK" => Ok(get_output(KeyValue::ScrollLock)),
|
||||||
|
"NUMLOCK" => Ok(get_output(KeyValue::NumLock)),
|
||||||
|
"PRINTSCREEN" => Ok(get_output(KeyValue::PrintScreen)),
|
||||||
|
"PAUSE" => Ok(get_output(KeyValue::Pause)),
|
||||||
|
"MENU" => Ok(get_output(KeyValue::Menu)),
|
||||||
|
"KEYPADBEGIN" => Ok(get_output(KeyValue::KeypadBegin)),
|
||||||
|
|
||||||
|
"DASH" => Ok(get_output(KeyValue::Char('-'))),
|
||||||
|
"ANGULAR_BRACKET_OPEN" | "ABO" => Ok(get_output(KeyValue::Char('<'))),
|
||||||
|
"ANGULAR_BRACKET_CLOSE" | "ABC" => Ok(get_output(KeyValue::Char('>'))),
|
||||||
|
other_str => bail!(
|
||||||
|
"The String ('{}') is not a correct special key name!",
|
||||||
|
other_str
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
bail!(
|
||||||
|
"You need to put something into the angulare brackets (<>)
|
||||||
|
parse_buffer: '{}';
|
||||||
|
chars: '{:#?}';",
|
||||||
|
&parse_buffer,
|
||||||
|
&chars,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl Display for Key {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
f.write_str(&self.to_string_repr())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl Into<Event> for Key {
|
||||||
|
fn into(self) -> Event {
|
||||||
|
let mut modifiers;
|
||||||
|
{
|
||||||
|
modifiers = KeyModifiers::all();
|
||||||
|
if !self.alt {
|
||||||
|
modifiers.remove(KeyModifiers::ALT);
|
||||||
|
}
|
||||||
|
if !self.ctrl {
|
||||||
|
modifiers.remove(KeyModifiers::CONTROL);
|
||||||
|
}
|
||||||
|
if !self.meta {
|
||||||
|
modifiers.remove(KeyModifiers::META);
|
||||||
|
modifiers.remove(KeyModifiers::SUPER);
|
||||||
|
}
|
||||||
|
if !self.shift {
|
||||||
|
modifiers.remove(KeyModifiers::SHIFT);
|
||||||
|
}
|
||||||
|
modifiers.remove(KeyModifiers::HYPER);
|
||||||
|
modifiers.remove(KeyModifiers::META);
|
||||||
|
if self.alt || self.ctrl || self.meta || self.shift {
|
||||||
|
modifiers.remove(KeyModifiers::NONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let output = Event::Key(KeyEvent {
|
||||||
|
code: {
|
||||||
|
// We sorta hit a edge case here, if we have a shifted char we need to tell
|
||||||
|
// crossterm about that. Thus we need to manually apply the shift modifier on the
|
||||||
|
// value.
|
||||||
|
if self.shift {
|
||||||
|
if let Some(KeyValue::Char(char)) = self.value {
|
||||||
|
let upper_case_char: char = {
|
||||||
|
let chars = char.to_uppercase().collect::<Vec<char>>();
|
||||||
|
if chars.len() != 1 {
|
||||||
|
unimplemented!(
|
||||||
|
"
|
||||||
|
I have no idea how we handle this case,
|
||||||
|
we'll just have to hope, that it never comes up.
|
||||||
|
"
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
*chars.first().expect("We checked the length")
|
||||||
|
}
|
||||||
|
};
|
||||||
|
KeyCode::Char(upper_case_char)
|
||||||
|
} else {
|
||||||
|
self.value.unwrap_or(KeyValue::Null).into()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self.value.unwrap_or(KeyValue::Null).into()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
modifiers,
|
||||||
|
kind: KeyEventKind::Press,
|
||||||
|
state: KeyEventState::NONE,
|
||||||
|
});
|
||||||
|
output
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<&Event> for Key {
|
||||||
|
type Error = anyhow::Error;
|
||||||
|
|
||||||
|
fn try_from(value: &Event) -> std::result::Result<Self, Self::Error> {
|
||||||
|
let mut output_key: Key = Key::new();
|
||||||
|
match value {
|
||||||
|
Event::Key(key_event) => {
|
||||||
|
{
|
||||||
|
let key_mods = key_event.modifiers;
|
||||||
|
|
||||||
|
output_key.alt = KeyModifiers::intersects(&key_mods, KeyModifiers::ALT);
|
||||||
|
output_key.ctrl = KeyModifiers::intersects(&key_mods, KeyModifiers::CONTROL);
|
||||||
|
output_key.meta = KeyModifiers::intersects(&key_mods, KeyModifiers::META)
|
||||||
|
|| KeyModifiers::intersects(&key_mods, KeyModifiers::SUPER);
|
||||||
|
output_key.shift = KeyModifiers::intersects(&key_mods, KeyModifiers::SHIFT);
|
||||||
|
// let hyper = KeyModifiers::intersects(&key_mods, KeyModifiers::HYPER);
|
||||||
|
// let none = KeyModifiers::intersects(&key_mods, KeyModifiers::NONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let key_code = key_event.code;
|
||||||
|
if output_key.shift {
|
||||||
|
// We need to deal have an edge case for shift, as the value will be in the
|
||||||
|
// shifted form (for example 'A'). If we left that, we would get "<S-A>" as
|
||||||
|
// Key representation, which can't be parsed. So we simply unshift the 'A'
|
||||||
|
// here, turning the representation into: "<S-a>"
|
||||||
|
if let KeyCode::Char(char) = key_code {
|
||||||
|
let lower_case_char: char = {
|
||||||
|
let chars = char.to_lowercase().collect::<Vec<char>>();
|
||||||
|
if chars.len() != 1 {
|
||||||
|
unimplemented!(
|
||||||
|
"
|
||||||
|
I have no idea how we handle this case,
|
||||||
|
we'll just have to hope, that it never comes up.
|
||||||
|
"
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
*chars.first().expect("We checked the length")
|
||||||
|
}
|
||||||
|
};
|
||||||
|
info!(
|
||||||
|
"Had to translate key ('{}') to it's lowercase variant ('{}')",
|
||||||
|
char, lower_case_char
|
||||||
|
);
|
||||||
|
output_key.value = Some(KeyValue::Char(lower_case_char));
|
||||||
|
} else {
|
||||||
|
debug!(
|
||||||
|
"Key ('{}') is shifted but not a character!",
|
||||||
|
Into::<KeyValue>::into(key_code)
|
||||||
|
);
|
||||||
|
output_key.value = Some(key_code.into());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
output_key.value = Some(key_code.into());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(output_key)
|
||||||
|
}
|
||||||
|
Event::Mouse(_)
|
||||||
|
| Event::Paste(_)
|
||||||
|
| Event::Resize(_, _)
|
||||||
|
| Event::FocusGained
|
||||||
|
| Event::FocusLost => bail!("Only supports parsing from key event"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl FromStr for Key {
|
||||||
|
type Err = anyhow::Error;
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
|
let mut keys: Keys = s.parse().context("Failed to parse string as keys")?;
|
||||||
|
if keys.0.len() == 1 {
|
||||||
|
let key = keys
|
||||||
|
.0
|
||||||
|
.pop()
|
||||||
|
.expect("The vec should have exactly one element");
|
||||||
|
return Ok(key);
|
||||||
|
} else {
|
||||||
|
bail!("The string ('{}') contains more than one key", &s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,79 @@
|
||||||
|
use std::fmt::{Display, Write};
|
||||||
|
|
||||||
use crossterm::event::KeyCode;
|
use crossterm::event::KeyCode;
|
||||||
|
|
||||||
use super::KeyValue;
|
// taken directly from crossterm
|
||||||
|
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
|
||||||
|
pub enum KeyValue {
|
||||||
|
Backspace,
|
||||||
|
Enter,
|
||||||
|
Left,
|
||||||
|
Right,
|
||||||
|
Up,
|
||||||
|
Down,
|
||||||
|
Home,
|
||||||
|
End,
|
||||||
|
PageUp,
|
||||||
|
PageDown,
|
||||||
|
Tab,
|
||||||
|
BackTab,
|
||||||
|
Delete,
|
||||||
|
Insert,
|
||||||
|
F(u8),
|
||||||
|
Char(char),
|
||||||
|
Null, // TODO(@soispha): What is this key? <2023-10-15>
|
||||||
|
Esc,
|
||||||
|
CapsLock,
|
||||||
|
ScrollLock,
|
||||||
|
NumLock,
|
||||||
|
PrintScreen,
|
||||||
|
Pause,
|
||||||
|
Menu,
|
||||||
|
KeypadBegin,
|
||||||
|
// TODO(@soispha): We could add support for these: <2023-10-15>
|
||||||
|
// Media(MediaKeyCode),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for KeyValue {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
let mut w = |str| return f.write_str(str);
|
||||||
|
match self {
|
||||||
|
KeyValue::Backspace => w("<BACKSPACE>"),
|
||||||
|
KeyValue::Enter => w("<ENTER>"),
|
||||||
|
KeyValue::Left => w("<LEFT>"),
|
||||||
|
KeyValue::Right => w("<RIGHT>"),
|
||||||
|
KeyValue::Up => w("<UP>"),
|
||||||
|
KeyValue::Down => w("<DOWN>"),
|
||||||
|
KeyValue::Home => w("<HOME>"),
|
||||||
|
KeyValue::End => w("<END>"),
|
||||||
|
KeyValue::PageUp => w("<PAGEUP>"),
|
||||||
|
KeyValue::PageDown => w("<PAGEDOWN>"),
|
||||||
|
KeyValue::Tab => w("<TAB>"),
|
||||||
|
KeyValue::BackTab => w("<BACKTAB>"),
|
||||||
|
KeyValue::Delete => w("<DELETE>"),
|
||||||
|
KeyValue::Insert => w("<INSERT>"),
|
||||||
|
KeyValue::F(n) => f.write_fmt(format_args!("<F{}>", n)),
|
||||||
|
KeyValue::Char(c) => {
|
||||||
|
match c {
|
||||||
|
'<' => w("<ANGULAR_BRACKET_OPEN>"),
|
||||||
|
'>' => w("<ANGULAR_BRACKET_CLOSE>"),
|
||||||
|
'-' => w("<DASH>"),
|
||||||
|
c => f.write_char(*c),
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
KeyValue::Null => w("<NULL>"),
|
||||||
|
KeyValue::Esc => w("<ESC>"),
|
||||||
|
KeyValue::CapsLock => w("<CAPSLOCK>"),
|
||||||
|
KeyValue::ScrollLock => w("<SCROLLLOCK>"),
|
||||||
|
KeyValue::NumLock => w("<NUMLOCK>"),
|
||||||
|
KeyValue::PrintScreen => w("<PRINTSCREEN>"),
|
||||||
|
KeyValue::Pause => w("<PAUSE>"),
|
||||||
|
KeyValue::Menu => w("<MENU>"),
|
||||||
|
KeyValue::KeypadBegin => w("<KEYPADBEGIN>"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<KeyCode> for KeyValue {
|
impl From<KeyCode> for KeyValue {
|
||||||
fn from(value: KeyCode) -> Self {
|
fn from(value: KeyCode) -> Self {
|
|
@ -1,14 +1,10 @@
|
||||||
use pest::Parser;
|
use anyhow::Context;
|
||||||
use pest_derive::Parser;
|
|
||||||
|
|
||||||
use crate::error;
|
use super::{Chars, Key, KeyValue};
|
||||||
|
|
||||||
use super::Key;
|
|
||||||
|
|
||||||
use std::{fmt::Display, str::FromStr};
|
use std::{fmt::Display, str::FromStr};
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Default, Parser)]
|
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone)]
|
||||||
#[grammar = "./key_repr/key_representation.pest"]
|
|
||||||
pub struct Keys(pub(super) Vec<Key>);
|
pub struct Keys(pub(super) Vec<Key>);
|
||||||
|
|
||||||
impl Keys {
|
impl Keys {
|
||||||
|
@ -48,11 +44,12 @@ impl Iterator for KeysIter {
|
||||||
type Item = Key;
|
type Item = Key;
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
let output = if self.keys.0.len() <= self.index {
|
let output;
|
||||||
None
|
if self.keys.0.len() <= self.index {
|
||||||
|
output = None;
|
||||||
} else {
|
} else {
|
||||||
Some(self.keys.0[self.index])
|
output = Some(self.keys.0[self.index]);
|
||||||
};
|
}
|
||||||
self.index += 1;
|
self.index += 1;
|
||||||
output
|
output
|
||||||
}
|
}
|
||||||
|
@ -74,7 +71,8 @@ impl<'a> Iterator for KeysIterB<'a> {
|
||||||
type Item = &'a Key;
|
type Item = &'a Key;
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
let output = self.keys.0.get(self.index);
|
let output;
|
||||||
|
output = self.keys.0.get(self.index);
|
||||||
self.index += 1;
|
self.index += 1;
|
||||||
output
|
output
|
||||||
}
|
}
|
||||||
|
@ -92,37 +90,28 @@ impl Display for Keys {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromStr for Keys {
|
impl FromStr for Keys {
|
||||||
type Err = error::KeysParseError;
|
type Err = anyhow::Error;
|
||||||
|
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
let mut output: Vec<Key> = vec![];
|
let mut output: Vec<Key> = vec![];
|
||||||
let parsed = Self::parse(Rule::keys, s)?;
|
let mut chars = Chars(s.chars().collect());
|
||||||
|
while let Some(char) = chars.pop() {
|
||||||
let keys: Vec<_> = parsed.find_tagged("keys").collect();
|
match char {
|
||||||
|
'<' => {
|
||||||
for key in keys {
|
chars.prepend('<');
|
||||||
let output_key: Key = Key::from_pair(key);
|
let key = Key::parse(&mut chars)
|
||||||
output.push(output_key)
|
.with_context(|| format!("Failed to parse keymapping ('{}')", &chars))?;
|
||||||
|
output.push(key)
|
||||||
|
}
|
||||||
|
other_char => output.push(Key {
|
||||||
|
alt: false,
|
||||||
|
ctrl: false,
|
||||||
|
meta: false,
|
||||||
|
shift: false,
|
||||||
|
value: Some(KeyValue::Char(other_char)),
|
||||||
|
}),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// let mut chars = Chars(s.chars().collect());
|
|
||||||
// while let Some(char) = chars.pop() {
|
|
||||||
// match char {
|
|
||||||
// '<' => {
|
|
||||||
// chars.prepend('<');
|
|
||||||
// let key = Key::parse(&mut chars)
|
|
||||||
// .with_context(|| format!("Failed to parse keymapping ('{}')", &chars))?;
|
|
||||||
// output.push(key)
|
|
||||||
// }
|
|
||||||
// other_char => output.push(Key {
|
|
||||||
// alt: false,
|
|
||||||
// ctrl: false,
|
|
||||||
// meta: false,
|
|
||||||
// shift: false,
|
|
||||||
// value: Some(KeyValue::Char(other_char)),
|
|
||||||
// }),
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
Ok(Keys(output))
|
Ok(Keys(output))
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,14 +1,18 @@
|
||||||
pub mod key;
|
pub mod key;
|
||||||
pub mod key_value;
|
|
||||||
pub mod keys;
|
pub mod keys;
|
||||||
|
pub mod chars;
|
||||||
|
pub mod key_value;
|
||||||
|
|
||||||
pub use key::Key;
|
pub use key::*;
|
||||||
|
pub use keys::*;
|
||||||
|
pub(self) use chars::*;
|
||||||
pub use key_value::*;
|
pub use key_value::*;
|
||||||
pub use keys::Keys;
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use crate::key_repr::{Key, KeyValue};
|
use crate::app::keymappings::key::{Key, KeyValue};
|
||||||
|
use anyhow::Error;
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
|
|
||||||
use super::Keys;
|
use super::Keys;
|
||||||
|
@ -76,10 +80,7 @@ mod test {
|
||||||
shift: true,
|
shift: true,
|
||||||
value: Some(KeyValue::Char('<')),
|
value: Some(KeyValue::Char('<')),
|
||||||
};
|
};
|
||||||
assert_eq!(
|
assert_eq!("<AMS-<ANGULAR_BRACKET_OPEN>>".to_owned(), key.to_string_repr());
|
||||||
"<AMS-<ANGULAR_BRACKET_OPEN>>".to_owned(),
|
|
||||||
key.to_string_repr()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -123,28 +124,13 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_false_pattern() {
|
fn test_false_pattern() {
|
||||||
let keys: Result<Keys, _> = "<c->".parse();
|
let keys: Result<Keys, Error> = "<c->".parse();
|
||||||
assert!(keys.is_err())
|
assert!(keys.is_err())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_f_keys() {
|
|
||||||
let key: Key = "<C-<F255>>".parse().unwrap();
|
|
||||||
let expected = Key {
|
|
||||||
alt: false,
|
|
||||||
ctrl: true,
|
|
||||||
meta: false,
|
|
||||||
shift: false,
|
|
||||||
value: Some(KeyValue::F(255)),
|
|
||||||
};
|
|
||||||
assert_eq!(key, expected);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_complex() {
|
fn test_complex() {
|
||||||
let keys: Keys = "<C-a><ACMS-<ESC>>a 🙂"
|
let keys: Keys = "<C-a><ACMS-<ESC>>a 🙂".parse().unwrap();
|
||||||
.parse()
|
|
||||||
.unwrap_or_else(|e| panic!("{}", e));
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
keys,
|
keys,
|
||||||
Keys(vec![
|
Keys(vec![
|
|
@ -0,0 +1,2 @@
|
||||||
|
pub mod key;
|
||||||
|
pub mod trie;
|
|
@ -1,26 +1,19 @@
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use log::info;
|
use anyhow::bail;
|
||||||
|
use cli_log::info;
|
||||||
|
|
||||||
use crate::error;
|
use super::key::{Key, Keys};
|
||||||
|
|
||||||
use super::key_repr::{Key, Keys};
|
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
pub struct Node<V: std::fmt::Display + ToOwned<Owned = V>> {
|
pub struct Node<V: std::fmt::Display> {
|
||||||
children: HashMap<Key, Box<Node<V>>>,
|
children: HashMap<Key, Box<Node<V>>>,
|
||||||
value: Option<V>,
|
value: Option<V>,
|
||||||
is_terminal: bool,
|
is_terminal: bool,
|
||||||
is_child: bool,
|
is_child: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<V: std::fmt::Display + ToOwned<Owned = V>> Default for Node<V> {
|
impl<V: std::fmt::Display> Node<V> {
|
||||||
fn default() -> Self {
|
|
||||||
Self::new()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<V: std::fmt::Display + ToOwned<Owned = V>> Node<V> {
|
|
||||||
pub fn new() -> Node<V> {
|
pub fn new() -> Node<V> {
|
||||||
Node {
|
Node {
|
||||||
children: HashMap::new(),
|
children: HashMap::new(),
|
||||||
|
@ -50,7 +43,7 @@ impl<V: std::fmt::Display + ToOwned<Owned = V>> Node<V> {
|
||||||
/// empty vector
|
/// empty vector
|
||||||
/// The boolean denotes if the returned node is a true end or just a waypoint. It should be
|
/// The boolean denotes if the returned node is a true end or just a waypoint. It should be
|
||||||
/// called, when the bool is true
|
/// called, when the bool is true
|
||||||
pub fn get(&self, keys: &Keys) -> Option<(Vec<&Node<V>>, bool)> {
|
pub fn get(&self, keys: &Keys) -> Option<(Vec<&Box<Node<V>>>, bool)> {
|
||||||
let mut current_node = self;
|
let mut current_node = self;
|
||||||
let mut old_node = None;
|
let mut old_node = None;
|
||||||
for char in keys {
|
for char in keys {
|
||||||
|
@ -70,7 +63,7 @@ impl<V: std::fmt::Display + ToOwned<Owned = V>> Node<V> {
|
||||||
// r->a->a->c: Some([c]) -> c.is_child() && c.is_terminal() ? *call c* : key input pending
|
// r->a->a->c: Some([c]) -> c.is_child() && c.is_terminal() ? *call c* : key input pending
|
||||||
//
|
//
|
||||||
// r->a: Some([a, b]) -> key input pending
|
// r->a: Some([a, b]) -> key input pending
|
||||||
if let Some(node) = current_node.children.get(char) {
|
if let Some(node) = current_node.children.get(&char) {
|
||||||
old_node = Some((current_node, char));
|
old_node = Some((current_node, char));
|
||||||
current_node = node;
|
current_node = node;
|
||||||
} else {
|
} else {
|
||||||
|
@ -83,21 +76,18 @@ impl<V: std::fmt::Display + ToOwned<Owned = V>> Node<V> {
|
||||||
Some((
|
Some((
|
||||||
vec![on
|
vec![on
|
||||||
.children
|
.children
|
||||||
.get(char)
|
.get(&char)
|
||||||
.expect("This should be some, as this was checked above")],
|
.expect("This should be some, as this was checked above")],
|
||||||
true,
|
true,
|
||||||
))
|
))
|
||||||
} else {
|
} else {
|
||||||
Some((
|
Some((current_node.children.values().collect(), false))
|
||||||
current_node.children.values().map(|a| a.as_ref()).collect(),
|
|
||||||
false,
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Insert a key value pair into the trie. The key is supplied as a string to facilitate the
|
/// Insert a key value pair into the trie. The key is supplied as a string to facilitate the
|
||||||
/// creation of nested nodes.
|
/// creation of nested nodes.
|
||||||
pub fn insert(&mut self, keys: &Keys, value: V) -> Result<(), error::TrieInsertError<V>> {
|
pub fn insert(&mut self, keys: &Keys, value: V) -> anyhow::Result<()> {
|
||||||
let mut current_node = self;
|
let mut current_node = self;
|
||||||
for char in keys {
|
for char in keys {
|
||||||
let child_node = current_node
|
let child_node = current_node
|
||||||
|
@ -105,22 +95,25 @@ impl<V: std::fmt::Display + ToOwned<Owned = V>> Node<V> {
|
||||||
.entry(char.to_owned())
|
.entry(char.to_owned())
|
||||||
.or_insert(Box::new(Node::new_child()));
|
.or_insert(Box::new(Node::new_child()));
|
||||||
if current_node.value.is_some() {
|
if current_node.value.is_some() {
|
||||||
return Err(error::TrieInsertError::KeyPathBlocked(keys.to_owned()));
|
bail!(
|
||||||
|
"The key ('{}') contains nodes, which already have a value set!",
|
||||||
|
keys
|
||||||
|
);
|
||||||
}
|
}
|
||||||
current_node.is_terminal = false;
|
current_node.is_terminal = false;
|
||||||
current_node = child_node
|
current_node = child_node
|
||||||
}
|
}
|
||||||
if current_node.value.is_some() {
|
if current_node.value.is_some() {
|
||||||
return Err(error::TrieInsertError::KeyAlreadySet {
|
bail!(
|
||||||
key: keys.to_owned(),
|
"The key ('{}') is already set! The value is: '{}'",
|
||||||
value: current_node
|
keys,
|
||||||
.value
|
current_node.value.as_ref().expect("This should be set")
|
||||||
.as_ref()
|
)
|
||||||
.expect("This should be set")
|
} else if current_node.children.len() > 0 {
|
||||||
.to_owned(),
|
bail!(
|
||||||
});
|
"The node accessed by this key ('{}') has children! You can't set a value for it",
|
||||||
} else if !current_node.children.is_empty() {
|
keys
|
||||||
return Err(error::TrieInsertError::NodeHasChildren(keys.to_owned()));
|
)
|
||||||
} else {
|
} else {
|
||||||
current_node.value = Some(value);
|
current_node.value = Some(value);
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -142,7 +135,8 @@ impl<V: std::fmt::Display + ToOwned<Owned = V>> Node<V> {
|
||||||
let out: Vec<_> = self
|
let out: Vec<_> = self
|
||||||
.children
|
.children
|
||||||
.values()
|
.values()
|
||||||
.flat_map(|node| node.collect_values_all())
|
.map(|node| node.collect_values_all())
|
||||||
|
.flatten()
|
||||||
.collect();
|
.collect();
|
||||||
out
|
out
|
||||||
}
|
}
|
||||||
|
@ -151,7 +145,7 @@ impl<V: std::fmt::Display + ToOwned<Owned = V>> Node<V> {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use crate::key_repr::{Key, Keys};
|
use crate::app::keymappings::key::{Key, Keys};
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
|
|
||||||
use super::Node;
|
use super::Node;
|
||||||
|
@ -162,9 +156,7 @@ mod test {
|
||||||
fn k(str: &str) -> Key {
|
fn k(str: &str) -> Key {
|
||||||
str.parse::<Key>().unwrap()
|
str.parse::<Key>().unwrap()
|
||||||
}
|
}
|
||||||
fn collect<V: std::fmt::Display + ToOwned<Owned = V>>(
|
fn collect<V: std::fmt::Display>(nodes: Option<(Vec<&Box<Node<V>>>, bool)>) -> Vec<&V> {
|
||||||
nodes: Option<(Vec<&Node<V>>, bool)>,
|
|
||||||
) -> Vec<&V> {
|
|
||||||
let (nodes, _should_call) = nodes.unwrap();
|
let (nodes, _should_call) = nodes.unwrap();
|
||||||
nodes
|
nodes
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -216,8 +208,8 @@ mod test {
|
||||||
let mut output: Node<bool> = Node::new();
|
let mut output: Node<bool> = Node::new();
|
||||||
|
|
||||||
trie.insert(&i("aa"), true).unwrap();
|
trie.insert(&i("aa"), true).unwrap();
|
||||||
trie.insert(&i("abe"), true).unwrap();
|
|
||||||
trie.insert(&i("abd"), true).unwrap();
|
trie.insert(&i("abd"), true).unwrap();
|
||||||
|
trie.insert(&i("abe"), true).unwrap();
|
||||||
|
|
||||||
output.insert(&i("abd"), true).unwrap();
|
output.insert(&i("abd"), true).unwrap();
|
||||||
output.insert(&i("abe"), true).unwrap();
|
output.insert(&i("abe"), true).unwrap();
|
||||||
|
@ -226,10 +218,7 @@ mod test {
|
||||||
output.insert(&i("ace"), true).unwrap();
|
output.insert(&i("ace"), true).unwrap();
|
||||||
|
|
||||||
let a_children = &output.children.get(&k("a")).unwrap();
|
let a_children = &output.children.get(&k("a")).unwrap();
|
||||||
let output_nodes = vec![
|
let output_nodes = vec![&a_children.children[&k("a")], &a_children.children[&k("b")]];
|
||||||
a_children.children[&k("a")].as_ref(),
|
|
||||||
a_children.children[&k("b")].as_ref(),
|
|
||||||
];
|
|
||||||
|
|
||||||
let (nodes, _should_call) = trie.get(&i("a")).unwrap();
|
let (nodes, _should_call) = trie.get(&i("a")).unwrap();
|
||||||
assert_eq!(nodes, output_nodes);
|
assert_eq!(nodes, output_nodes);
|
|
@ -1,6 +1,7 @@
|
||||||
pub mod command_interface;
|
pub mod command_interface;
|
||||||
pub mod config;
|
pub mod config;
|
||||||
pub mod events;
|
pub mod events;
|
||||||
|
pub mod keymappings;
|
||||||
pub mod status;
|
pub mod status;
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
|
@ -11,15 +12,16 @@ use std::{
|
||||||
use anyhow::{Context, Error, Result};
|
use anyhow::{Context, Error, Result};
|
||||||
use cli_log::{info, warn};
|
use cli_log::{info, warn};
|
||||||
use directories::ProjectDirs;
|
use directories::ProjectDirs;
|
||||||
use keymaps::trie::Node;
|
|
||||||
use matrix_sdk::Client;
|
use matrix_sdk::Client;
|
||||||
use tokio::sync::mpsc;
|
use tokio::sync::mpsc;
|
||||||
use tokio_util::sync::CancellationToken;
|
use tokio_util::sync::CancellationToken;
|
||||||
|
|
||||||
use self::command_interface::{
|
use self::{
|
||||||
|
command_interface::{
|
||||||
command_transfer_value::support_types::Function, lua_command_manager::LuaCommandManager,
|
command_transfer_value::support_types::Function, lua_command_manager::LuaCommandManager,
|
||||||
|
},
|
||||||
|
keymappings::trie::Node,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
accounts::{Account, AccountsManager},
|
accounts::{Account, AccountsManager},
|
||||||
app::{
|
app::{
|
||||||
|
|
|
@ -3,7 +3,6 @@ use core::fmt;
|
||||||
use anyhow::{bail, Error, Result};
|
use anyhow::{bail, Error, Result};
|
||||||
use cli_log::warn;
|
use cli_log::warn;
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
use keymaps::key_repr::Keys;
|
|
||||||
use matrix_sdk::{
|
use matrix_sdk::{
|
||||||
room::MessagesOptions,
|
room::MessagesOptions,
|
||||||
ruma::{
|
ruma::{
|
||||||
|
@ -13,6 +12,8 @@ use matrix_sdk::{
|
||||||
Client,
|
Client,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use super::keymappings::key::Keys;
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Debug)]
|
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Debug)]
|
||||||
pub enum State {
|
pub enum State {
|
||||||
Normal,
|
Normal,
|
||||||
|
|
14
update.sh
14
update.sh
|
@ -1,19 +1,13 @@
|
||||||
#!/usr/bin/env sh
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
update() {
|
|
||||||
cd "$1" || (echo "No '$1' directory" && exit 1)
|
|
||||||
|
|
||||||
cargo update && cargo upgrade
|
cargo update && cargo upgrade
|
||||||
|
|
||||||
[ "$1" = "." ] || cd ..
|
cd ./language_macros || (echo "No language_macros directory" && exit 1)
|
||||||
}
|
|
||||||
|
|
||||||
update .
|
|
||||||
update ./language_macros
|
|
||||||
update ./keymaps
|
|
||||||
|
|
||||||
|
|
||||||
|
cargo update && cargo upgrade
|
||||||
|
|
||||||
|
cd ..
|
||||||
git add Cargo.lock Cargo.toml flake.lock ./language_macros/Cargo.toml
|
git add Cargo.lock Cargo.toml flake.lock ./language_macros/Cargo.toml
|
||||||
|
|
||||||
# vim: ft=sh
|
# vim: ft=sh
|
||||||
|
|
Reference in New Issue