mirror of
https://github.com/pinnacle-comp/pinnacle.git
synced 2025-01-30 20:34:49 +01:00
Start on a better CLI
This commit is contained in:
parent
8d2c5d4dcb
commit
63c0ef1e85
6 changed files with 570 additions and 50 deletions
213
Cargo.lock
generated
213
Cargo.lock
generated
|
@ -66,6 +66,21 @@ version = "0.2.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fc7eb209b1518d6bb87b283c20095f5228ecda460da70b44f0802523dea6da04"
|
checksum = "fc7eb209b1518d6bb87b283c20095f5228ecda460da70b44f0802523dea6da04"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "android-tzdata"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "android_system_properties"
|
||||||
|
version = "0.1.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anstream"
|
name = "anstream"
|
||||||
version = "0.6.11"
|
version = "0.6.11"
|
||||||
|
@ -397,6 +412,20 @@ dependencies = [
|
||||||
"num-traits",
|
"num-traits",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "chrono"
|
||||||
|
version = "0.4.34"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5bc015644b92d5890fab7489e49d21f879d5c990186827d42ec511919404f38b"
|
||||||
|
dependencies = [
|
||||||
|
"android-tzdata",
|
||||||
|
"iana-time-zone",
|
||||||
|
"js-sys",
|
||||||
|
"num-traits",
|
||||||
|
"wasm-bindgen",
|
||||||
|
"windows-targets 0.52.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap"
|
name = "clap"
|
||||||
version = "4.5.1"
|
version = "4.5.1"
|
||||||
|
@ -437,6 +466,19 @@ version = "0.7.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce"
|
checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cliclack"
|
||||||
|
version = "0.1.13"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "be29210ca32b96e4f67fe9a520d2eeacc078d94ff4027100dc6b7262fdfec5c4"
|
||||||
|
dependencies = [
|
||||||
|
"console",
|
||||||
|
"indicatif",
|
||||||
|
"once_cell",
|
||||||
|
"textwrap",
|
||||||
|
"zeroize",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "color_quant"
|
name = "color_quant"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
|
@ -468,6 +510,19 @@ dependencies = [
|
||||||
"crossbeam-utils",
|
"crossbeam-utils",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "console"
|
||||||
|
version = "0.15.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb"
|
||||||
|
dependencies = [
|
||||||
|
"encode_unicode",
|
||||||
|
"lazy_static",
|
||||||
|
"libc",
|
||||||
|
"unicode-width",
|
||||||
|
"windows-sys 0.52.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "const_format"
|
name = "const_format"
|
||||||
version = "0.2.32"
|
version = "0.2.32"
|
||||||
|
@ -528,6 +583,19 @@ dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam"
|
||||||
|
version = "0.8.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1137cd7e7fc0fb5d3c5a8678be38ec56e819125d8d7907411fe24ccb943faca8"
|
||||||
|
dependencies = [
|
||||||
|
"crossbeam-channel",
|
||||||
|
"crossbeam-deque",
|
||||||
|
"crossbeam-epoch",
|
||||||
|
"crossbeam-queue",
|
||||||
|
"crossbeam-utils",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam-channel"
|
name = "crossbeam-channel"
|
||||||
version = "0.5.11"
|
version = "0.5.11"
|
||||||
|
@ -556,6 +624,15 @@ dependencies = [
|
||||||
"crossbeam-utils",
|
"crossbeam-utils",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-queue"
|
||||||
|
version = "0.3.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35"
|
||||||
|
dependencies = [
|
||||||
|
"crossbeam-utils",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam-utils"
|
name = "crossbeam-utils"
|
||||||
version = "0.8.19"
|
version = "0.8.19"
|
||||||
|
@ -577,6 +654,17 @@ dependencies = [
|
||||||
"powerfmt",
|
"powerfmt",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dircpy"
|
||||||
|
version = "0.3.16"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "29259db751c34980bfc44100875890c507f585323453b91936960ab1104272ca"
|
||||||
|
dependencies = [
|
||||||
|
"jwalk",
|
||||||
|
"log",
|
||||||
|
"walkdir",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dirs"
|
name = "dirs"
|
||||||
version = "5.0.1"
|
version = "5.0.1"
|
||||||
|
@ -670,6 +758,12 @@ version = "1.9.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
|
checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "encode_unicode"
|
||||||
|
version = "0.3.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "encoding_rs"
|
name = "encoding_rs"
|
||||||
version = "0.8.33"
|
version = "0.8.33"
|
||||||
|
@ -1013,6 +1107,29 @@ dependencies = [
|
||||||
"tokio-io-timeout",
|
"tokio-io-timeout",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "iana-time-zone"
|
||||||
|
version = "0.1.60"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141"
|
||||||
|
dependencies = [
|
||||||
|
"android_system_properties",
|
||||||
|
"core-foundation-sys",
|
||||||
|
"iana-time-zone-haiku",
|
||||||
|
"js-sys",
|
||||||
|
"wasm-bindgen",
|
||||||
|
"windows-core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "iana-time-zone-haiku"
|
||||||
|
version = "0.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
|
||||||
|
dependencies = [
|
||||||
|
"cc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "icrate"
|
name = "icrate"
|
||||||
version = "0.0.4"
|
version = "0.0.4"
|
||||||
|
@ -1056,6 +1173,19 @@ dependencies = [
|
||||||
"hashbrown 0.14.3",
|
"hashbrown 0.14.3",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "indicatif"
|
||||||
|
version = "0.17.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "763a5a8f45087d6bcea4222e7b72c291a054edf80e4ef6efd2a4979878c7bea3"
|
||||||
|
dependencies = [
|
||||||
|
"console",
|
||||||
|
"instant",
|
||||||
|
"number_prefix",
|
||||||
|
"portable-atomic",
|
||||||
|
"unicode-width",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "input"
|
name = "input"
|
||||||
version = "0.9.0"
|
version = "0.9.0"
|
||||||
|
@ -1075,6 +1205,15 @@ version = "1.18.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bd4f5b4d1c00331c5245163aacfe5f20be75b564c7112d45893d4ae038119eb0"
|
checksum = "bd4f5b4d1c00331c5245163aacfe5f20be75b564c7112d45893d4ae038119eb0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "instant"
|
||||||
|
version = "0.1.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "io-lifetimes"
|
name = "io-lifetimes"
|
||||||
version = "1.0.11"
|
version = "1.0.11"
|
||||||
|
@ -1147,6 +1286,16 @@ dependencies = [
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jwalk"
|
||||||
|
version = "0.8.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2735847566356cd2179a2a38264839308f7079fa96e6bd5a42d740460e003c56"
|
||||||
|
dependencies = [
|
||||||
|
"crossbeam",
|
||||||
|
"rayon",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "khronos_api"
|
name = "khronos_api"
|
||||||
version = "3.1.0"
|
version = "3.1.0"
|
||||||
|
@ -1451,6 +1600,12 @@ dependencies = [
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "number_prefix"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "objc-sys"
|
name = "objc-sys"
|
||||||
version = "0.3.2"
|
version = "0.3.2"
|
||||||
|
@ -1586,7 +1741,10 @@ version = "0.0.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"bitflags 2.4.2",
|
"bitflags 2.4.2",
|
||||||
|
"chrono",
|
||||||
"clap",
|
"clap",
|
||||||
|
"cliclack",
|
||||||
|
"dircpy",
|
||||||
"image",
|
"image",
|
||||||
"nix",
|
"nix",
|
||||||
"pinnacle-api-defs",
|
"pinnacle-api-defs",
|
||||||
|
@ -1667,6 +1825,12 @@ dependencies = [
|
||||||
"windows-sys 0.52.0",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "portable-atomic"
|
||||||
|
version = "1.6.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "powerfmt"
|
name = "powerfmt"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
|
@ -2050,6 +2214,12 @@ version = "1.13.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7"
|
checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "smawk"
|
||||||
|
version = "0.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b7c388c1b5e93756d0c740965c41e8822f866621d41acbdf6336a6a168f8840c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "smithay"
|
name = "smithay"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
|
@ -2212,6 +2382,17 @@ dependencies = [
|
||||||
"windows-sys 0.52.0",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "textwrap"
|
||||||
|
version = "0.16.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "23d434d3f8967a09480fb04132ebe0a3e088c173e6d0ee7897abbdf4eab0f8b9"
|
||||||
|
dependencies = [
|
||||||
|
"smawk",
|
||||||
|
"unicode-linebreak",
|
||||||
|
"unicode-width",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror"
|
name = "thiserror"
|
||||||
version = "1.0.57"
|
version = "1.0.57"
|
||||||
|
@ -2565,12 +2746,24 @@ version = "1.0.12"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-linebreak"
|
||||||
|
version = "0.1.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-segmentation"
|
name = "unicode-segmentation"
|
||||||
version = "1.11.0"
|
version = "1.11.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202"
|
checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-width"
|
||||||
|
version = "0.1.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-xid"
|
name = "unicode-xid"
|
||||||
version = "0.2.4"
|
version = "0.2.4"
|
||||||
|
@ -3271,3 +3464,23 @@ dependencies = [
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zeroize"
|
||||||
|
version = "1.7.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d"
|
||||||
|
dependencies = [
|
||||||
|
"zeroize_derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zeroize_derive"
|
||||||
|
version = "1.4.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
41
Cargo.toml
41
Cargo.toml
|
@ -7,20 +7,21 @@ edition = "2021"
|
||||||
repository = "https://github.com/pinnacle-comp/pinnacle/"
|
repository = "https://github.com/pinnacle-comp/pinnacle/"
|
||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
|
# Tokio
|
||||||
tokio = { version = "1.36.0", features = ["macros", "rt-multi-thread"]}
|
tokio = { version = "1.36.0", features = ["macros", "rt-multi-thread"]}
|
||||||
tokio-stream = { version = "0.1.14", features = ["net"] }
|
tokio-stream = { version = "0.1.14", features = ["net"] }
|
||||||
|
# gRPC
|
||||||
prost = "0.12.3"
|
prost = "0.12.3"
|
||||||
tonic = "0.11.0"
|
tonic = "0.11.0"
|
||||||
tonic-reflection = "0.11.0"
|
tonic-reflection = "0.11.0"
|
||||||
tonic-build = "0.11.0"
|
tonic-build = "0.11.0"
|
||||||
|
# API definitions
|
||||||
pinnacle-api-defs = { path = "./pinnacle-api-defs" }
|
pinnacle-api-defs = { path = "./pinnacle-api-defs" }
|
||||||
|
# Misc.
|
||||||
xkbcommon = "0.7.0"
|
xkbcommon = "0.7.0"
|
||||||
xdg = "2.5.2"
|
xdg = "2.5.2"
|
||||||
|
|
||||||
#################################################################################
|
########################################################################yo😎###########
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "pinnacle"
|
name = "pinnacle"
|
||||||
|
@ -34,38 +35,42 @@ repository.workspace = true
|
||||||
keywords = ["wayland", "compositor", "smithay", "lua"]
|
keywords = ["wayland", "compositor", "smithay", "lua"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
# Smithay
|
||||||
smithay = { git = "https://github.com/Smithay/smithay", rev = "418190e", default-features = false, features = ["desktop", "wayland_frontend"] }
|
smithay = { git = "https://github.com/Smithay/smithay", rev = "418190e", default-features = false, features = ["desktop", "wayland_frontend"] }
|
||||||
smithay-drm-extras = { git = "https://github.com/Smithay/smithay", rev = "418190e" }
|
smithay-drm-extras = { git = "https://github.com/Smithay/smithay", rev = "418190e" }
|
||||||
|
# Tracing
|
||||||
tracing = "0.1.40"
|
tracing = "0.1.40"
|
||||||
tracing-subscriber = { version = "0.3.18", features = ["env-filter", "registry"] }
|
tracing-subscriber = { version = "0.3.18", features = ["env-filter", "registry"] }
|
||||||
tracing-appender = "0.2.3"
|
tracing-appender = "0.2.3"
|
||||||
|
# Errors
|
||||||
anyhow = { version = "1.0.79", features = ["backtrace"] }
|
anyhow = { version = "1.0.79", features = ["backtrace"] }
|
||||||
thiserror = "1.0.57"
|
thiserror = "1.0.57"
|
||||||
|
# xcursor stuff
|
||||||
xcursor = { version = "0.3.5" }
|
xcursor = { version = "0.3.5" }
|
||||||
image = { version = "0.24.8", default-features = false }
|
image = { version = "0.24.8", default-features = false }
|
||||||
|
# gRPC
|
||||||
|
prost = { workspace = true }
|
||||||
|
tonic = { workspace = true }
|
||||||
|
tonic-reflection = { workspace = true }
|
||||||
|
# Tokio
|
||||||
|
tokio = { workspace = true, features = ["process", "io-util", "signal"] }
|
||||||
|
tokio-stream = { workspace = true }
|
||||||
|
# CLI
|
||||||
|
clap = { version = "4.5.1", features = ["derive"] }
|
||||||
|
cliclack = "0.1.13"
|
||||||
|
# Misc.
|
||||||
|
bitflags = "2.4.2"
|
||||||
serde = { version = "1.0.196", features = ["derive"] }
|
serde = { version = "1.0.196", features = ["derive"] }
|
||||||
toml = "0.8.10"
|
toml = "0.8.10"
|
||||||
shellexpand = "3.1.0"
|
shellexpand = "3.1.0"
|
||||||
clap = { version = "4.5.1", features = ["derive"] }
|
|
||||||
x11rb = { version = "0.13.0", default-features = false, features = ["composite"] }
|
x11rb = { version = "0.13.0", default-features = false, features = ["composite"] }
|
||||||
xkbcommon = { workspace = true }
|
xkbcommon = { workspace = true }
|
||||||
xdg = { workspace = true }
|
xdg = { workspace = true }
|
||||||
sysinfo = "0.30.5"
|
sysinfo = "0.30.5"
|
||||||
nix = { version = "0.27.1", features = ["user", "resource"] }
|
nix = { version = "0.27.1", features = ["user", "resource"] }
|
||||||
|
|
||||||
prost = { workspace = true }
|
|
||||||
tonic = { workspace = true }
|
|
||||||
tonic-reflection = { workspace = true }
|
|
||||||
|
|
||||||
tokio = { workspace = true, features = ["process", "io-util", "signal"] }
|
|
||||||
tokio-stream = { workspace = true }
|
|
||||||
|
|
||||||
bitflags = "2.4.2"
|
|
||||||
pinnacle-api-defs = { workspace = true }
|
pinnacle-api-defs = { workspace = true }
|
||||||
|
dircpy = "0.3.16"
|
||||||
|
chrono = "0.4.34"
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
xdg = { workspace = true }
|
xdg = { workspace = true }
|
||||||
|
|
2
build.rs
2
build.rs
|
@ -5,7 +5,7 @@ fn main() {
|
||||||
let xdg = xdg::BaseDirectories::with_prefix("pinnacle").unwrap();
|
let xdg = xdg::BaseDirectories::with_prefix("pinnacle").unwrap();
|
||||||
|
|
||||||
let proto_dir = xdg.place_data_file("protobuf").unwrap();
|
let proto_dir = xdg.place_data_file("protobuf").unwrap();
|
||||||
let default_config_dir = xdg.place_data_file("default_config").unwrap();
|
let default_config_dir = xdg.place_data_file("default_config").unwrap().join("lua");
|
||||||
|
|
||||||
let remove_protos = format!("rm -r {proto_dir:?}");
|
let remove_protos = format!("rm -r {proto_dir:?}");
|
||||||
let copy_protos = format!("cp -r ./api/protocol {proto_dir:?}");
|
let copy_protos = format!("cp -r ./api/protocol {proto_dir:?}");
|
||||||
|
|
317
src/cli.rs
Normal file
317
src/cli.rs
Normal file
|
@ -0,0 +1,317 @@
|
||||||
|
use std::{
|
||||||
|
cell::RefCell,
|
||||||
|
ffi::OsString,
|
||||||
|
marker::PhantomData,
|
||||||
|
path::{Path, PathBuf},
|
||||||
|
rc::Rc,
|
||||||
|
};
|
||||||
|
|
||||||
|
use clap::{error::ErrorKind, CommandFactory, Parser, ValueHint};
|
||||||
|
use cliclack::Validate;
|
||||||
|
|
||||||
|
/// Valid backends that Pinnacle can run.
|
||||||
|
#[derive(clap::ValueEnum, Debug, Clone, Copy)]
|
||||||
|
pub enum Backend {
|
||||||
|
/// Run Pinnacle in a window in your graphical environment
|
||||||
|
Winit,
|
||||||
|
/// Run Pinnacle from a tty
|
||||||
|
Udev,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The main CLI struct.
|
||||||
|
#[derive(clap::Parser, Debug)]
|
||||||
|
#[command(author, version, about, long_about = None)]
|
||||||
|
pub struct Cli {
|
||||||
|
/// Start Pinnacle with the config at this directory
|
||||||
|
#[arg(short, long, value_name("DIR"), value_hint(ValueHint::DirPath))]
|
||||||
|
pub config_dir: Option<PathBuf>,
|
||||||
|
|
||||||
|
/// Run Pinnacle with the specified backend
|
||||||
|
///
|
||||||
|
/// This is usually not necessary, but if your environment variables are mucked up
|
||||||
|
/// then this can be used to choose a backend.
|
||||||
|
#[arg(short, long)]
|
||||||
|
pub backend: Option<Backend>,
|
||||||
|
|
||||||
|
/// Force Pinnacle to run with the provided backend
|
||||||
|
#[arg(long, requires = "backend")]
|
||||||
|
pub force: bool,
|
||||||
|
|
||||||
|
/// Allow running Pinnacle as root (this is NOT recommended)
|
||||||
|
#[arg(long)]
|
||||||
|
pub allow_root: bool,
|
||||||
|
|
||||||
|
/// Start Pinnacle without a config
|
||||||
|
///
|
||||||
|
/// This is meant to be used for debugging.
|
||||||
|
/// Additionally, Pinnacle will not load the
|
||||||
|
/// default config if a manually spawned one
|
||||||
|
/// crashes or exits.
|
||||||
|
#[arg(long)]
|
||||||
|
pub no_config: bool,
|
||||||
|
|
||||||
|
/// Cli subcommands
|
||||||
|
#[command(subcommand)]
|
||||||
|
pub subcommand: Option<CliSubcommand>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Cli {
|
||||||
|
pub fn parse_and_prompt() -> Self {
|
||||||
|
let args = Cli::parse();
|
||||||
|
|
||||||
|
match &args.subcommand {
|
||||||
|
Some(CliSubcommand::Config(ConfigSubcommand::Gen(config_gen))) => {
|
||||||
|
generate_config(config_gen.clone()).unwrap();
|
||||||
|
}
|
||||||
|
None => (),
|
||||||
|
}
|
||||||
|
|
||||||
|
args
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Cli subcommands.
|
||||||
|
#[derive(clap::Subcommand, Debug)]
|
||||||
|
pub enum CliSubcommand {
|
||||||
|
/// Commands dealing with configuration
|
||||||
|
#[command(subcommand)]
|
||||||
|
Config(ConfigSubcommand),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Config subcommands
|
||||||
|
#[derive(clap::Subcommand, Debug)]
|
||||||
|
pub enum ConfigSubcommand {
|
||||||
|
/// Generate a config
|
||||||
|
///
|
||||||
|
/// If not all flags are provided, this will launch an
|
||||||
|
/// interactive prompt.
|
||||||
|
Gen(ConfigGen),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Config arguments.
|
||||||
|
#[derive(clap::Args, Debug, Clone)]
|
||||||
|
pub struct ConfigGen {
|
||||||
|
/// Generate a config in a specific language
|
||||||
|
#[arg(short, long)]
|
||||||
|
pub lang: Option<Lang>,
|
||||||
|
/// Generate a config at this directory
|
||||||
|
#[arg(short, long, value_hint(ValueHint::DirPath))]
|
||||||
|
pub dir: Option<PathBuf>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Possible languages for configuration.
|
||||||
|
#[derive(clap::ValueEnum, Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
pub enum Lang {
|
||||||
|
/// Generate a Lua config
|
||||||
|
Lua,
|
||||||
|
/// Generate a Rust config
|
||||||
|
Rust,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for Lang {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, "{self:?}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/// Show the interactive prompt for config generation.
|
||||||
|
pub fn generate_config(args: ConfigGen) -> anyhow::Result<()> {
|
||||||
|
cliclack::intro("Config generation")?;
|
||||||
|
|
||||||
|
let mut skip_confirmation = true;
|
||||||
|
|
||||||
|
let lang = match args.lang {
|
||||||
|
Some(lang) => {
|
||||||
|
cliclack::log::success(format!("Select a language:\n{lang} (from -l/--lang)"))?;
|
||||||
|
lang
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
skip_confirmation = false;
|
||||||
|
cliclack::select("Select a language:")
|
||||||
|
.items(&[(Lang::Lua, "Lua", ""), (Lang::Rust, "Rust", "")])
|
||||||
|
.interact()?
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let dir = match args.dir {
|
||||||
|
Some(dir) => {
|
||||||
|
cliclack::log::success(format!(
|
||||||
|
"Choose a directory to place the config in:\n{} (from -d/--dir)",
|
||||||
|
dir.display()
|
||||||
|
))?;
|
||||||
|
dir
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
skip_confirmation = false;
|
||||||
|
let mut wants_to_create_dir: Option<PathBuf> = None;
|
||||||
|
let mut wants_to_create = false;
|
||||||
|
|
||||||
|
let dir: String = cliclack::input("Choose a directory to place the config in:")
|
||||||
|
// Now this is a grade A bastardization of what this function is supposed to do
|
||||||
|
.validate_interactively(DirValidator::new(move |s: &String| {
|
||||||
|
let dir = shellexpand::full(s)
|
||||||
|
.map_err(|err| format!("Directory expansion failed: {err}"))?;
|
||||||
|
let mut dir = PathBuf::from(dir.to_string());
|
||||||
|
|
||||||
|
if dir.is_relative() {
|
||||||
|
let mut new_dir = std::env::current_dir().map_err(|err| {
|
||||||
|
format!("Failed to get the current dir to resolve relative path: {err}")
|
||||||
|
})?;
|
||||||
|
new_dir.push(dir);
|
||||||
|
dir = new_dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
match dir.try_exists() {
|
||||||
|
Ok(exists) => {
|
||||||
|
if exists {
|
||||||
|
if !dir.is_dir() {
|
||||||
|
Err(format!(
|
||||||
|
"`{}` exists but is not a directory",
|
||||||
|
dir.display()
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
wants_to_create_dir = None;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
} else if wants_to_create_dir.as_ref() == Some(&dir) {
|
||||||
|
if wants_to_create {
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
wants_to_create = true;
|
||||||
|
Err(format!(
|
||||||
|
"`{}` doesn't exist. Press ENTER again to create it.",
|
||||||
|
dir.display()
|
||||||
|
))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
wants_to_create = false;
|
||||||
|
wants_to_create_dir = Some(dir.clone());
|
||||||
|
Err(format!(
|
||||||
|
"`{}` doesn't exist. Press ENTER twice to create it.",
|
||||||
|
dir.display()
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(err) => Err(format!(
|
||||||
|
"Failed to check if `{}` exists: {err}",
|
||||||
|
dir.display()
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
.interact()?;
|
||||||
|
|
||||||
|
let dir = shellexpand::full(&dir)?;
|
||||||
|
let mut dir = PathBuf::from(dir.to_string());
|
||||||
|
|
||||||
|
if dir.is_relative() {
|
||||||
|
let mut new_dir = std::env::current_dir()?;
|
||||||
|
new_dir.push(dir);
|
||||||
|
dir = new_dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
dir
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if skip_confirmation {
|
||||||
|
cliclack::log::info("Final confirmation: skipping because all flags were present")?;
|
||||||
|
} else {
|
||||||
|
let confirm_creation = cliclack::confirm(format!(
|
||||||
|
"Final confirmation: create a {} config inside `{}`?",
|
||||||
|
lang,
|
||||||
|
dir.display()
|
||||||
|
))
|
||||||
|
.initial_value(false)
|
||||||
|
.interact()?;
|
||||||
|
|
||||||
|
if !confirm_creation {
|
||||||
|
cliclack::outro_cancel("Config generation cancelled.")?;
|
||||||
|
anyhow::bail!("cancelled");
|
||||||
|
} else {
|
||||||
|
cliclack::log::info("HERE")?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate the config
|
||||||
|
|
||||||
|
let xdg_base_dirs = xdg::BaseDirectories::with_prefix("pinnacle")?;
|
||||||
|
let mut default_config_dir = xdg_base_dirs.get_data_file("default_config");
|
||||||
|
match lang {
|
||||||
|
Lang::Lua => {
|
||||||
|
cliclack::log::info("HERE 2")?;
|
||||||
|
default_config_dir.push("lua");
|
||||||
|
// %F = %Y-%m-%d or year-month-day in ISO 8601
|
||||||
|
let now = format!("{}", chrono::Local::now().format("%F.%T"));
|
||||||
|
let mut backed_up_files: Vec<(String, String)> = Vec::new();
|
||||||
|
for file in std::fs::read_dir(&default_config_dir)? {
|
||||||
|
let file = file?;
|
||||||
|
let name = file.file_name();
|
||||||
|
let target_file = dir.join(&name);
|
||||||
|
if let Ok(true) = target_file.try_exists() {
|
||||||
|
let backup_name = format!("{}.{now}.bak", name.to_string_lossy());
|
||||||
|
backed_up_files.push((name.to_string_lossy().to_string(), backup_name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cliclack::log::info("HERE 3")?;
|
||||||
|
|
||||||
|
if !backed_up_files.is_empty() {
|
||||||
|
cliclack::log::info("HERE 4")?;
|
||||||
|
let prompt = backed_up_files
|
||||||
|
.iter()
|
||||||
|
.map(|(src, dst)| format!("{src} -> {dst}"))
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join("\n");
|
||||||
|
cliclack::note("The following files will be renamed:", prompt)?;
|
||||||
|
let r#continue = cliclack::confirm("Continue?").interact()?;
|
||||||
|
|
||||||
|
if !r#continue {
|
||||||
|
cliclack::outro_cancel("Config generation cancelled.")?;
|
||||||
|
anyhow::bail!("cancelled");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (src, dst) in backed_up_files.iter() {
|
||||||
|
std::fs::rename(dir.join(src), dir.join(dst))?;
|
||||||
|
}
|
||||||
|
|
||||||
|
cliclack::log::info("Renamed old files")?;
|
||||||
|
|
||||||
|
dircpy::copy_dir(default_config_dir, dir)?;
|
||||||
|
|
||||||
|
cliclack::log::info("Copied new config over")?;
|
||||||
|
}
|
||||||
|
cliclack::log::info("HERE END")?;
|
||||||
|
}
|
||||||
|
Lang::Rust => {
|
||||||
|
default_config_dir.push("rust");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cliclack::outro("Done!")?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
struct DirValidator<T, F: FnMut(&T) -> Result<(), E>, E>(Rc<RefCell<F>>, PhantomData<(T, E)>);
|
||||||
|
|
||||||
|
impl<T, F, E> DirValidator<T, F, E>
|
||||||
|
where
|
||||||
|
F: FnMut(&T) -> Result<(), E>,
|
||||||
|
{
|
||||||
|
fn new(validator: F) -> Self {
|
||||||
|
Self(Rc::new(RefCell::new(validator)), PhantomData)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T, F, E> Validate<T> for DirValidator<T, F, E>
|
||||||
|
where
|
||||||
|
F: FnMut(&T) -> Result<(), E>,
|
||||||
|
{
|
||||||
|
type Err = E;
|
||||||
|
|
||||||
|
fn validate(&self, input: &T) -> Result<(), Self::Err> {
|
||||||
|
let mut validator = self.0.borrow_mut();
|
||||||
|
validator(input)
|
||||||
|
}
|
||||||
|
}
|
|
@ -225,7 +225,10 @@ impl State {
|
||||||
|
|
||||||
tracing::info!("Starting config at {}", config_dir.display());
|
tracing::info!("Starting config at {}", config_dir.display());
|
||||||
|
|
||||||
let default_lua_config_dir = self.xdg_base_dirs.get_data_file("default_config");
|
let default_lua_config_dir = self
|
||||||
|
.xdg_base_dirs
|
||||||
|
.get_data_file("default_config")
|
||||||
|
.join("lua");
|
||||||
|
|
||||||
let load_default_config = |state: &mut State, reason: &str| {
|
let load_default_config = |state: &mut State, reason: &str| {
|
||||||
tracing::error!(
|
tracing::error!(
|
||||||
|
|
42
src/main.rs
42
src/main.rs
|
@ -13,6 +13,7 @@
|
||||||
|
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
|
use cli::Cli;
|
||||||
use nix::unistd::Uid;
|
use nix::unistd::Uid;
|
||||||
use tracing::{info, level_filters::LevelFilter, warn};
|
use tracing::{info, level_filters::LevelFilter, warn};
|
||||||
use tracing_appender::rolling::Rotation;
|
use tracing_appender::rolling::Rotation;
|
||||||
|
@ -21,6 +22,7 @@ use xdg::BaseDirectories;
|
||||||
|
|
||||||
mod api;
|
mod api;
|
||||||
mod backend;
|
mod backend;
|
||||||
|
mod cli;
|
||||||
mod config;
|
mod config;
|
||||||
mod cursor;
|
mod cursor;
|
||||||
mod focus;
|
mod focus;
|
||||||
|
@ -34,30 +36,6 @@ mod state;
|
||||||
mod tag;
|
mod tag;
|
||||||
mod window;
|
mod window;
|
||||||
|
|
||||||
#[derive(clap::Args, Debug)]
|
|
||||||
#[group(id = "backend", required = false, multiple = false)]
|
|
||||||
struct Backends {
|
|
||||||
#[arg(long, group = "backend")]
|
|
||||||
/// Run Pinnacle in a window in your graphical environment
|
|
||||||
winit: bool,
|
|
||||||
#[arg(long, group = "backend")]
|
|
||||||
/// Run Pinnacle from a tty
|
|
||||||
udev: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(clap::Parser, Debug)]
|
|
||||||
#[command(author, version, about, long_about = None)]
|
|
||||||
struct Args {
|
|
||||||
#[command(flatten)]
|
|
||||||
backend: Backends,
|
|
||||||
#[arg(long)]
|
|
||||||
/// Allow running Pinnacle as root (this is NOT recommended)
|
|
||||||
allow_root: bool,
|
|
||||||
#[arg(long, requires = "backend")]
|
|
||||||
/// Force Pinnacle to run with the provided backend
|
|
||||||
force: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> anyhow::Result<()> {
|
async fn main() -> anyhow::Result<()> {
|
||||||
let xdg_state_dir = BaseDirectories::with_prefix("pinnacle")?.get_state_home();
|
let xdg_state_dir = BaseDirectories::with_prefix("pinnacle")?.get_state_home();
|
||||||
|
@ -96,7 +74,12 @@ async fn main() -> anyhow::Result<()> {
|
||||||
.with(stdout_layer)
|
.with(stdout_layer)
|
||||||
.init();
|
.init();
|
||||||
|
|
||||||
let args = Args::parse();
|
let args = Cli::parse_and_prompt();
|
||||||
|
|
||||||
|
tracing::info!("{args:#?}");
|
||||||
|
|
||||||
|
tracing::info!("Currently in cli debugging, remove this later");
|
||||||
|
return Ok(());
|
||||||
|
|
||||||
if Uid::effective().is_root() {
|
if Uid::effective().is_root() {
|
||||||
if !args.allow_root {
|
if !args.allow_root {
|
||||||
|
@ -118,8 +101,8 @@ async fn main() -> anyhow::Result<()> {
|
||||||
warn!("You may see LOTS of file descriptors open under Pinnacle.");
|
warn!("You may see LOTS of file descriptors open under Pinnacle.");
|
||||||
}
|
}
|
||||||
|
|
||||||
match (args.backend.winit, args.backend.udev, args.force) {
|
match (args.backend, args.force) {
|
||||||
(false, false, _) => {
|
(None, _) => {
|
||||||
if in_graphical_env {
|
if in_graphical_env {
|
||||||
info!("Starting winit backend");
|
info!("Starting winit backend");
|
||||||
crate::backend::winit::run_winit()?;
|
crate::backend::winit::run_winit()?;
|
||||||
|
@ -128,7 +111,7 @@ async fn main() -> anyhow::Result<()> {
|
||||||
crate::backend::udev::run_udev()?;
|
crate::backend::udev::run_udev()?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(true, false, force) => {
|
(Some(cli::Backend::Winit), force) => {
|
||||||
if !in_graphical_env {
|
if !in_graphical_env {
|
||||||
if force {
|
if force {
|
||||||
warn!("Starting winit backend with no detected graphical environment");
|
warn!("Starting winit backend with no detected graphical environment");
|
||||||
|
@ -143,7 +126,7 @@ async fn main() -> anyhow::Result<()> {
|
||||||
crate::backend::winit::run_winit()?;
|
crate::backend::winit::run_winit()?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(false, true, force) => {
|
(Some(cli::Backend::Udev), force) => {
|
||||||
if in_graphical_env {
|
if in_graphical_env {
|
||||||
if force {
|
if force {
|
||||||
warn!("Starting udev backend with a detected graphical environment");
|
warn!("Starting udev backend with a detected graphical environment");
|
||||||
|
@ -159,7 +142,6 @@ async fn main() -> anyhow::Result<()> {
|
||||||
crate::backend::udev::run_udev()?;
|
crate::backend::udev::run_udev()?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
Loading…
Add table
Reference in a new issue