Temp
This commit is contained in:
407
Cargo.lock
generated
407
Cargo.lock
generated
@@ -1,6 +1,6 @@
|
|||||||
# This file is automatically @generated by Cargo.
|
# This file is automatically @generated by Cargo.
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 3
|
version = 4
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "addr2line"
|
name = "addr2line"
|
||||||
@@ -35,6 +35,51 @@ version = "0.2.18"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f"
|
checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "async-channel"
|
||||||
|
version = "2.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "89b47800b0be77592da0afd425cc03468052844aff33b84e33cc696f64e77b6a"
|
||||||
|
dependencies = [
|
||||||
|
"concurrent-queue",
|
||||||
|
"event-listener-strategy",
|
||||||
|
"futures-core",
|
||||||
|
"pin-project-lite",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "async-fs"
|
||||||
|
version = "1.6.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "279cf904654eeebfa37ac9bb1598880884924aab82e290aa65c9e77a0e142e06"
|
||||||
|
dependencies = [
|
||||||
|
"async-lock",
|
||||||
|
"autocfg",
|
||||||
|
"blocking",
|
||||||
|
"futures-lite 1.13.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "async-lock"
|
||||||
|
version = "2.8.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b"
|
||||||
|
dependencies = [
|
||||||
|
"event-listener 2.5.3",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "async-task"
|
||||||
|
version = "4.7.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "atomic-waker"
|
||||||
|
version = "1.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "autocfg"
|
name = "autocfg"
|
||||||
version = "1.3.0"
|
version = "1.3.0"
|
||||||
@@ -62,6 +107,19 @@ version = "2.6.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
|
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "blocking"
|
||||||
|
version = "1.6.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "703f41c54fc768e63e091340b424302bb1c29ef4aa0c7f10fe849dfb114d29ea"
|
||||||
|
dependencies = [
|
||||||
|
"async-channel",
|
||||||
|
"async-task",
|
||||||
|
"futures-io",
|
||||||
|
"futures-lite 2.3.0",
|
||||||
|
"piper",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bytes"
|
name = "bytes"
|
||||||
version = "1.7.1"
|
version = "1.7.1"
|
||||||
@@ -103,6 +161,21 @@ dependencies = [
|
|||||||
"static_assertions",
|
"static_assertions",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "concurrent-queue"
|
||||||
|
version = "2.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973"
|
||||||
|
dependencies = [
|
||||||
|
"crossbeam-utils",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-utils"
|
||||||
|
version = "0.8.20"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossterm"
|
name = "crossterm"
|
||||||
version = "0.28.1"
|
version = "0.28.1"
|
||||||
@@ -138,12 +211,47 @@ dependencies = [
|
|||||||
"powerfmt",
|
"powerfmt",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dirs"
|
||||||
|
version = "3.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "30baa043103c9d0c2a57cf537cc2f35623889dc0d405e6c3cccfadbc81c71309"
|
||||||
|
dependencies = [
|
||||||
|
"dirs-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dirs"
|
||||||
|
version = "4.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059"
|
||||||
|
dependencies = [
|
||||||
|
"dirs-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dirs-sys"
|
||||||
|
version = "0.3.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"redox_users",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "either"
|
name = "either"
|
||||||
version = "1.13.0"
|
version = "1.13.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
|
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "equivalent"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "errno"
|
name = "errno"
|
||||||
version = "0.3.9"
|
version = "0.3.9"
|
||||||
@@ -154,6 +262,48 @@ dependencies = [
|
|||||||
"windows-sys",
|
"windows-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "event-listener"
|
||||||
|
version = "2.5.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "event-listener"
|
||||||
|
version = "5.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6032be9bd27023a771701cc49f9f053c751055f71efb2e0ae5c15809093675ba"
|
||||||
|
dependencies = [
|
||||||
|
"concurrent-queue",
|
||||||
|
"parking",
|
||||||
|
"pin-project-lite",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "event-listener-strategy"
|
||||||
|
version = "0.5.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0f214dc438f977e6d4e3500aaa277f5ad94ca83fbbd9b1a15713ce2344ccc5a1"
|
||||||
|
dependencies = [
|
||||||
|
"event-listener 5.3.1",
|
||||||
|
"pin-project-lite",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fastrand"
|
||||||
|
version = "1.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be"
|
||||||
|
dependencies = [
|
||||||
|
"instant",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fastrand"
|
||||||
|
version = "2.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures"
|
name = "futures"
|
||||||
version = "0.3.30"
|
version = "0.3.30"
|
||||||
@@ -202,6 +352,31 @@ version = "0.3.30"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1"
|
checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-lite"
|
||||||
|
version = "1.13.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce"
|
||||||
|
dependencies = [
|
||||||
|
"fastrand 1.9.0",
|
||||||
|
"futures-core",
|
||||||
|
"futures-io",
|
||||||
|
"memchr",
|
||||||
|
"parking",
|
||||||
|
"pin-project-lite",
|
||||||
|
"waker-fn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-lite"
|
||||||
|
version = "2.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "52527eb5074e35e9339c6b4e8d12600c7128b68fb25dcb9fa9dec18f7c25f3a5"
|
||||||
|
dependencies = [
|
||||||
|
"futures-core",
|
||||||
|
"pin-project-lite",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-macro"
|
name = "futures-macro"
|
||||||
version = "0.3.30"
|
version = "0.3.30"
|
||||||
@@ -243,12 +418,29 @@ dependencies = [
|
|||||||
"slab",
|
"slab",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "getrandom"
|
||||||
|
version = "0.2.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"wasi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gimli"
|
name = "gimli"
|
||||||
version = "0.31.0"
|
version = "0.31.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "32085ea23f3234fc7846555e85283ba4de91e21016dc0455a16286d87a292d64"
|
checksum = "32085ea23f3234fc7846555e85283ba4de91e21016dc0455a16286d87a292d64"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hashbrown"
|
||||||
|
version = "0.12.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hashbrown"
|
name = "hashbrown"
|
||||||
version = "0.14.5"
|
version = "0.14.5"
|
||||||
@@ -259,6 +451,12 @@ dependencies = [
|
|||||||
"allocator-api2",
|
"allocator-api2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hashbrown"
|
||||||
|
version = "0.15.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "heck"
|
name = "heck"
|
||||||
version = "0.5.0"
|
version = "0.5.0"
|
||||||
@@ -271,6 +469,26 @@ version = "0.3.9"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
|
checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "indexmap"
|
||||||
|
version = "1.9.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"hashbrown 0.12.3",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "indexmap"
|
||||||
|
version = "2.6.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da"
|
||||||
|
dependencies = [
|
||||||
|
"equivalent",
|
||||||
|
"hashbrown 0.15.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "instability"
|
name = "instability"
|
||||||
version = "0.3.2"
|
version = "0.3.2"
|
||||||
@@ -281,6 +499,15 @@ dependencies = [
|
|||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "instant"
|
||||||
|
version = "0.1.13"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itertools"
|
name = "itertools"
|
||||||
version = "0.13.0"
|
version = "0.13.0"
|
||||||
@@ -296,12 +523,28 @@ version = "1.0.11"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
|
checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lazy_static"
|
||||||
|
version = "1.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.158"
|
version = "0.2.158"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439"
|
checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libredox"
|
||||||
|
version = "0.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "linux-raw-sys"
|
name = "linux-raw-sys"
|
||||||
version = "0.4.14"
|
version = "0.4.14"
|
||||||
@@ -330,7 +573,7 @@ version = "0.12.4"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "37ee39891760e7d94734f6f63fedc29a2e4a152f836120753a72503f09fcf904"
|
checksum = "37ee39891760e7d94734f6f63fedc29a2e4a152f836120753a72503f09fcf904"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"hashbrown",
|
"hashbrown 0.14.5",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -391,6 +634,12 @@ version = "1.20.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "33ea5043e58958ee56f3e15a90aee535795cd7dfd319846288d93c5b57d85cbe"
|
checksum = "33ea5043e58958ee56f3e15a90aee535795cd7dfd319846288d93c5b57d85cbe"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "parking"
|
||||||
|
version = "2.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "parking_lot"
|
name = "parking_lot"
|
||||||
version = "0.12.3"
|
version = "0.12.3"
|
||||||
@@ -432,6 +681,26 @@ version = "0.1.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "piper"
|
||||||
|
version = "0.2.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066"
|
||||||
|
dependencies = [
|
||||||
|
"atomic-waker",
|
||||||
|
"fastrand 2.1.1",
|
||||||
|
"futures-io",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "plain_path"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9f1b940aa8e0562ece01eb12a9731bb8f6f0325c2c97c8629f852504f01d4537"
|
||||||
|
dependencies = [
|
||||||
|
"dirs 3.0.2",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "powerfmt"
|
name = "powerfmt"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
@@ -487,6 +756,17 @@ dependencies = [
|
|||||||
"bitflags",
|
"bitflags",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "redox_users"
|
||||||
|
version = "0.4.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom",
|
||||||
|
"libredox",
|
||||||
|
"thiserror",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc-demangle"
|
name = "rustc-demangle"
|
||||||
version = "0.1.24"
|
version = "0.1.24"
|
||||||
@@ -526,24 +806,51 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.198"
|
version = "1.0.210"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9846a40c979031340571da2545a4e5b7c4163bdae79b301d5f86d03979451fcc"
|
checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.198"
|
version = "1.0.210"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e88edab869b01783ba905e7d0153f9fc1a6505a96e4ad3018011eedb838566d9"
|
checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_json"
|
||||||
|
version = "1.0.128"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8"
|
||||||
|
dependencies = [
|
||||||
|
"itoa",
|
||||||
|
"memchr",
|
||||||
|
"ryu",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_spanned"
|
||||||
|
version = "0.6.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "shlex"
|
||||||
|
version = "1.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "signal-hook"
|
name = "signal-hook"
|
||||||
version = "0.3.17"
|
version = "0.3.17"
|
||||||
@@ -599,6 +906,18 @@ dependencies = [
|
|||||||
"windows-sys",
|
"windows-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ssh_cfg"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "33130e7e8a61e5822f5f6f7f7127e4adad805fcc1a55dc83d2b5c15c1279014c"
|
||||||
|
dependencies = [
|
||||||
|
"async-fs",
|
||||||
|
"dirs 4.0.0",
|
||||||
|
"indexmap 1.9.3",
|
||||||
|
"plain_path",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "static_assertions"
|
name = "static_assertions"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
@@ -644,8 +963,35 @@ version = "0.1.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"crossterm",
|
"crossterm",
|
||||||
"futures",
|
"futures",
|
||||||
|
"indexmap 2.6.0",
|
||||||
|
"lazy_static",
|
||||||
"ratatui",
|
"ratatui",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"shlex",
|
||||||
|
"ssh_cfg",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
"toml",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror"
|
||||||
|
version = "1.0.64"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84"
|
||||||
|
dependencies = [
|
||||||
|
"thiserror-impl",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror-impl"
|
||||||
|
version = "1.0.64"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -698,6 +1044,40 @@ dependencies = [
|
|||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml"
|
||||||
|
version = "0.8.19"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
"serde_spanned",
|
||||||
|
"toml_datetime",
|
||||||
|
"toml_edit",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml_datetime"
|
||||||
|
version = "0.6.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml_edit"
|
||||||
|
version = "0.22.22"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5"
|
||||||
|
dependencies = [
|
||||||
|
"indexmap 2.6.0",
|
||||||
|
"serde",
|
||||||
|
"serde_spanned",
|
||||||
|
"toml_datetime",
|
||||||
|
"winnow",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-ident"
|
name = "unicode-ident"
|
||||||
version = "1.0.13"
|
version = "1.0.13"
|
||||||
@@ -733,6 +1113,12 @@ version = "0.9.5"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
|
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "waker-fn"
|
||||||
|
version = "1.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "317211a0dc0ceedd78fb2ca9a44aed3d7b9b26f81870d485c07122b4350673b7"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasi"
|
name = "wasi"
|
||||||
version = "0.11.0+wasi-snapshot-preview1"
|
version = "0.11.0+wasi-snapshot-preview1"
|
||||||
@@ -834,6 +1220,15 @@ version = "0.52.6"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winnow"
|
||||||
|
version = "0.6.20"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zerocopy"
|
name = "zerocopy"
|
||||||
version = "0.7.35"
|
version = "0.7.35"
|
||||||
|
|||||||
@@ -8,5 +8,12 @@ edition = "2021"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
crossterm = { version = "0.28.1", features = ["event-stream"] }
|
crossterm = { version = "0.28.1", features = ["event-stream"] }
|
||||||
futures = "0.3.30"
|
futures = "0.3.30"
|
||||||
|
indexmap = "2.6.0"
|
||||||
|
lazy_static = "1.5.0"
|
||||||
ratatui = { version = "0.28.1", features = ["all-widgets"] }
|
ratatui = { version = "0.28.1", features = ["all-widgets"] }
|
||||||
|
serde = { version = "1.0.210", features = ["derive"] }
|
||||||
|
serde_json = "1.0.128"
|
||||||
|
shlex = "1.3.0"
|
||||||
|
ssh_cfg = "0.3.0"
|
||||||
tokio = { version = "1.40.0", features = ["full"] }
|
tokio = { version = "1.40.0", features = ["full"] }
|
||||||
|
toml = "0.8.19"
|
||||||
|
|||||||
1
rustfmt.toml
Normal file
1
rustfmt.toml
Normal file
@@ -0,0 +1 @@
|
|||||||
|
imports_granularity = "Crate"
|
||||||
38
src/app.rs
38
src/app.rs
@@ -1,22 +1,28 @@
|
|||||||
use std::error;
|
use std::error;
|
||||||
|
|
||||||
|
use crate::component::Component;
|
||||||
|
|
||||||
/// Application result type.
|
/// Application result type.
|
||||||
pub type AppResult<T> = std::result::Result<T, Box<dyn error::Error>>;
|
pub type AppResult<T> = std::result::Result<T, Box<dyn error::Error>>;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum Mode {
|
||||||
|
Normal,
|
||||||
|
Insert,
|
||||||
|
}
|
||||||
|
|
||||||
/// Application.
|
/// Application.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct App {
|
pub struct App {
|
||||||
/// Is the application running?
|
|
||||||
pub running: bool,
|
pub running: bool,
|
||||||
/// counter
|
pub mode: Mode,
|
||||||
pub counter: u8,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for App {
|
impl Default for App {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
running: true,
|
running: true,
|
||||||
counter: 0,
|
mode: Mode::Normal,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -34,16 +40,26 @@ impl App {
|
|||||||
pub fn quit(&mut self) {
|
pub fn quit(&mut self) {
|
||||||
self.running = false;
|
self.running = false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn increment_counter(&mut self) {
|
pub struct AppComponents {
|
||||||
if let Some(res) = self.counter.checked_add(1) {
|
pub components: Vec<Box<dyn Component>>,
|
||||||
self.counter = res;
|
}
|
||||||
|
|
||||||
|
impl Default for AppComponents {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
components: Vec::new(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn decrement_counter(&mut self) {
|
impl AppComponents {
|
||||||
if let Some(res) = self.counter.checked_sub(1) {
|
pub fn new() -> Self {
|
||||||
self.counter = res;
|
Self::default()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn add_component(&mut self, component: Box<dyn Component>) {
|
||||||
|
self.components.push(component);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
13
src/component.rs
Normal file
13
src/component.rs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
use crossterm::event::{Event, KeyEvent};
|
||||||
|
use ratatui::{layout::Rect, Frame};
|
||||||
|
|
||||||
|
use crate::app::{App, AppComponents};
|
||||||
|
|
||||||
|
pub mod home;
|
||||||
|
pub mod input;
|
||||||
|
|
||||||
|
pub trait Component {
|
||||||
|
fn draw(&mut self, frame: &mut Frame, app: &mut App, area: Rect);
|
||||||
|
fn handle_event(&mut self, app: &mut App, event: &Event);
|
||||||
|
fn get_help(&self) -> Option<Vec<(&'static str, &'static str)>>;
|
||||||
|
}
|
||||||
76
src/component/home.rs
Normal file
76
src/component/home.rs
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
use crate::{
|
||||||
|
app::App,
|
||||||
|
component::{input::Input, Component},
|
||||||
|
};
|
||||||
|
use crossterm::event::Event;
|
||||||
|
use ratatui::{
|
||||||
|
layout::{Constraint, Direction, Layout, Rect},
|
||||||
|
style::{Color, Style},
|
||||||
|
widgets::{Block, BorderType, Borders, List, ListItem, Paragraph},
|
||||||
|
Frame,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct Home {
|
||||||
|
input: Input,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Home {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
input: Input::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Component for Home {
|
||||||
|
fn draw(&mut self, frame: &mut Frame, app: &mut App, area: Rect) {
|
||||||
|
let layout = Layout::default()
|
||||||
|
.direction(Direction::Vertical)
|
||||||
|
.constraints([
|
||||||
|
Constraint::Length(3),
|
||||||
|
Constraint::Min(3),
|
||||||
|
Constraint::Length(3),
|
||||||
|
])
|
||||||
|
.split(frame.area());
|
||||||
|
|
||||||
|
let input_block = Block::default()
|
||||||
|
.title("Home")
|
||||||
|
.borders(Borders::ALL)
|
||||||
|
.border_type(BorderType::Rounded);
|
||||||
|
frame.render_widget(input_block, layout[0]);
|
||||||
|
let input_area = Rect::new(layout[0].x + 1, layout[0].y + 1, layout[0].width - 2, 1);
|
||||||
|
self.input.draw(frame, app, input_area);
|
||||||
|
let list_block = Block::default()
|
||||||
|
.borders(Borders::ALL)
|
||||||
|
.border_type(BorderType::Rounded);
|
||||||
|
frame.render_widget(list_block, layout[1]);
|
||||||
|
let list_area = Rect::new(
|
||||||
|
layout[1].x + 1,
|
||||||
|
layout[1].y + 1,
|
||||||
|
layout[1].width - 2,
|
||||||
|
layout[1].height - 2,
|
||||||
|
);
|
||||||
|
let items = vec![
|
||||||
|
ListItem::new("Item 1"),
|
||||||
|
ListItem::new("Item 2"),
|
||||||
|
ListItem::new("Item 3"),
|
||||||
|
];
|
||||||
|
let list = List::default().items(items);
|
||||||
|
frame.render_widget(list, list_area);
|
||||||
|
let help_block = Block::default()
|
||||||
|
.borders(Borders::ALL)
|
||||||
|
.border_type(BorderType::Rounded);
|
||||||
|
frame.render_widget(help_block, layout[2]);
|
||||||
|
let help_area = Rect::new(layout[2].x + 1, layout[2].y + 1, layout[2].width - 2, 1);
|
||||||
|
let help = Paragraph::new("Press 'q' to quit");
|
||||||
|
frame.render_widget(help, help_area);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_event(&mut self, app: &mut App, event: &Event) {
|
||||||
|
self.input.handle_event(app, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_help(&self) -> Option<Vec<(&'static str, &'static str)>> {
|
||||||
|
self.input.get_help()
|
||||||
|
}
|
||||||
|
}
|
||||||
55
src/component/input.rs
Normal file
55
src/component/input.rs
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
use crossterm::event::{Event, KeyCode, KeyEvent, KeyEventKind, KeyModifiers};
|
||||||
|
use ratatui::{
|
||||||
|
layout::Rect,
|
||||||
|
widgets::{Block, Borders, Paragraph},
|
||||||
|
Frame,
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::app::App;
|
||||||
|
|
||||||
|
use super::Component;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Input {
|
||||||
|
value: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Input {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
value: String::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Component for Input {
|
||||||
|
fn draw(&mut self, frame: &mut Frame, _app: &mut App, area: Rect) {
|
||||||
|
let input = Paragraph::new(self.value.clone());
|
||||||
|
frame.render_widget(input, area);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_event(&mut self, _app: &mut App, event: &Event) {
|
||||||
|
if let Event::Key(KeyEvent {
|
||||||
|
code,
|
||||||
|
kind: KeyEventKind::Press,
|
||||||
|
modifiers,
|
||||||
|
..
|
||||||
|
}) = event
|
||||||
|
{
|
||||||
|
use KeyCode::*;
|
||||||
|
match (code, modifiers) {
|
||||||
|
(Char(c), &KeyModifiers::NONE | &KeyModifiers::SHIFT) => {
|
||||||
|
self.value.push(c.to_owned());
|
||||||
|
}
|
||||||
|
(Backspace, &KeyModifiers::NONE) => {
|
||||||
|
self.value.pop();
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_help(&self) -> Option<Vec<(&'static str, &'static str)>> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
8
src/connection.rs
Normal file
8
src/connection.rs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
use std::error::Error;
|
||||||
|
|
||||||
|
pub mod authentication;
|
||||||
|
pub mod connection_config;
|
||||||
|
|
||||||
|
pub trait Connection {
|
||||||
|
fn connect(&self) -> Result<(), Box<dyn Error>>;
|
||||||
|
}
|
||||||
33
src/connection/authentication.rs
Normal file
33
src/connection/authentication.rs
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
|
||||||
|
pub enum AuthenticationMethod {
|
||||||
|
Password(String),
|
||||||
|
PrivateKey(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Authentication {
|
||||||
|
pub auth_name: String,
|
||||||
|
pub method: AuthenticationMethod,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct AuthenticationManager {
|
||||||
|
pub authentications: Vec<Authentication>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AuthenticationManager {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
authentications: Vec::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_authentication(&mut self, auth_name: String, method: AuthenticationMethod) {
|
||||||
|
self.authentications.push(Authentication {
|
||||||
|
auth_name,
|
||||||
|
method,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_authentication(&self, auth_name: &str) -> Option<&Authentication> {
|
||||||
|
self.authentications.iter().find(|auth| auth.auth_name == auth_name)
|
||||||
|
}
|
||||||
|
}
|
||||||
77
src/connection/connection_config.rs
Normal file
77
src/connection/connection_config.rs
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
use std::{
|
||||||
|
fs::{File, OpenOptions},
|
||||||
|
io::Write,
|
||||||
|
os::unix::fs::OpenOptionsExt,
|
||||||
|
path::Path,
|
||||||
|
process::Command,
|
||||||
|
};
|
||||||
|
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use crate::{connection::authentication::{self, AuthenticationMethod}, global::AUTH_MAN};
|
||||||
|
|
||||||
|
use super::{authentication::Authentication, Connection};
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
pub enum ConnectionType {
|
||||||
|
SSH(SshConnectionConfig),
|
||||||
|
SH(ShConnectionConfig),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
pub struct SshConnectionConfig {
|
||||||
|
pub host: String,
|
||||||
|
pub port: u16,
|
||||||
|
pub user: String,
|
||||||
|
pub auth_name: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
pub struct ShConnectionConfig {
|
||||||
|
pub command: String,
|
||||||
|
pub path: String,
|
||||||
|
pub args: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
pub struct ConnectionManager {
|
||||||
|
pub connection_type: ConnectionType,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Connection for ConnectionManager {
|
||||||
|
fn connect(&self) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
let mut command = match &self.connection_type {
|
||||||
|
ConnectionType::SH(sh) => Command::new(&sh.command),
|
||||||
|
ConnectionType::SSH(ssh) => {
|
||||||
|
let authentication = AUTH_MAN.get_authentication(&ssh.auth_name);
|
||||||
|
match authentication {
|
||||||
|
Some(auth) => {
|
||||||
|
match &auth.method {
|
||||||
|
AuthenticationMethod::Password(password) => {
|
||||||
|
Command::new(format!("sshpass -p {} ssh", password))
|
||||||
|
}
|
||||||
|
AuthenticationMethod::PrivateKey(key) => {
|
||||||
|
let secret_path = Path::new("/tmp/tethers_tmp.tmp");
|
||||||
|
let mut secret_file = OpenOptions::new()
|
||||||
|
.write(true)
|
||||||
|
.create(true)
|
||||||
|
.mode(0o600)
|
||||||
|
.open(secret_path)?;
|
||||||
|
secret_file.set_len(0)?;
|
||||||
|
secret_file.write_all(key.as_bytes())?;
|
||||||
|
let mut command = Command::new("ssh");
|
||||||
|
command.args(["-i", secret_path.to_str().unwrap(), "-P", &ssh.port.to_string(), "-l", &ssh.user, &ssh.host]);
|
||||||
|
command
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => return Err(Box::new(std::io::Error::new(std::io::ErrorKind::Other, "Authentication not found"))),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
println!("{:?}", command);
|
||||||
|
command.spawn()?.wait()?;
|
||||||
|
println!("exit!");
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
40
src/global.rs
Normal file
40
src/global.rs
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
use futures::lock::Mutex;
|
||||||
|
use lazy_static::lazy_static;
|
||||||
|
|
||||||
|
use crate::connection::authentication::{AuthenticationManager, AuthenticationMethod};
|
||||||
|
|
||||||
|
lazy_static! {
|
||||||
|
pub static ref AUTH_MAN: AuthenticationManager = {
|
||||||
|
let mut auth_man = AuthenticationManager::new();
|
||||||
|
auth_man.add_authentication("tencent".to_string(), AuthenticationMethod::PrivateKey(
|
||||||
|
r#"-----BEGIN RSA PRIVATE KEY-----
|
||||||
|
MIIEowIBAAKCAQEAwLsc4WtfQ9myeqYrsXhyJxg6pqsjE7NNgva9OO6bMRLUJOip
|
||||||
|
9fEMGk/cLXDFEqTiB5WmXCfHc+pOOomyA2OlMFW4hMfV7TB+c2BIEL7BHb+B+m50
|
||||||
|
ps8b1tFze9hqArPL/wZ6xDDks83v3MUSMBoq+rf5cOix/wJtm9dUtVODBYjlYaT9
|
||||||
|
wFDkuIjpxmLR6+Jiq+nJWVeBBIHABDjhj+qI2Qp4tRoQl1hzfcbFLzDMqI/HANEW
|
||||||
|
cYOJ+Z+TizA6TH3s8FBxU9NKQhA8Dur4jH+HG9XrsVGh9gckcI8iYWWEr1O6MvrB
|
||||||
|
MVtSEiSarsWpc732YxHDWyJ9BYaZq5BKMNNa5QIDAQABAoIBAA0Roxe2DDOxo2Sl
|
||||||
|
t/jEzhjQj8mVeT9wvSTQTmx54ZQmTrRiAoRm4Ac4uxlpuDNXcuxIvYsqN2Ao1z0o
|
||||||
|
8SVBsIXiiiyW0G7RBwIT2U8pYDcAMXQl4UseaCjc8xPGzQl5369fZRvApQF8SXOS
|
||||||
|
+XTBkYCG0SdS4B8GryAOLfRNwWiyjXkfkJiLdMjLaomOZMKLrq3mAjNPFoKX4piL
|
||||||
|
xBFztBhQwvNKp0GVNiz8WyEQ+nWTpl3l1cU1PE98Mk4YkCRBvwSiJlTJHdqWmnPU
|
||||||
|
ne3OeazNqucKWU+iWiTWb8Y4x0L/rZUf/N6KmQp5dhc3BzrOrjTXyytjm5zNxcTT
|
||||||
|
zsgf5tECgYEA9BvihyQ8+FY8bRqBqXXA95vecleqxeLfzL4PG19WZCoG3uTC5YuK
|
||||||
|
uPOV4awcJESP3JTOKBM9KYiaYKigFSES6GQIYD28tLz6b3DAj2GcCiTZbwLkVj33
|
||||||
|
A58EYfrKcbzTHN3P4Gzh8mV3067uk2CPan6SPWfP36BdHukIKnKrytcCgYEAyh6H
|
||||||
|
JUOXphcrWDVjca6PB23JbuUHLrT3I2hcM5IPj5lOEdx15efUp7+708Lm1LcPlnVy
|
||||||
|
eZlSCnPBlOnFeXULbxjFtPp4IaJSki470lTNZbvOMF7b4Os8f1axbWkby4dqsN9U
|
||||||
|
szp7Pb2VAt7TQjXdnAy0+w1uUrbh5nK27CHF7KMCgYEAq+xbvcxi+JBb3IeXnI8n
|
||||||
|
ifyITcW6q8Ze0udk4mViBgencSJytZJy8FH2VMuPwmdbXwKas5ThNbhU6hC5Nkhl
|
||||||
|
9bBGSeoRVsXmJ8ikhhc7+9T6InpJ8QeRSkaboposLLDNiv4Z4zksZTjbjQYeV0Ph
|
||||||
|
niJowsCzog9iplt/ec3rel8CgYA4nFxV/5yWFJ87UZjM2ouNFR76RIPCfUVLUYuh
|
||||||
|
liNtoQ7QyeLrxgc2BOni4hAtPCjNh4/MpzjnXIy33NJGtpXBRDr7+bt0EDb4YqK2
|
||||||
|
wrHU8MlLmwYS9VA4ilufvXTfiMpFSAg9OwARxuvZpfed7+BmONjoCFcCK98R4MeD
|
||||||
|
U+JP6QKBgBTBhg1ptSvWNhePXsdxiZOjOuo3/W/qLJmcCSIvk9c3rd877jtvxOC2
|
||||||
|
919rt4YO0gr2EYQWQ4cmCQvzaCEKX4st5ArA0XvcOTdlXMYQSaXoj96DwfpGspYu
|
||||||
|
1AG7ygBL7Aoyv5hB0g+7pgtbfzr6GRkb2t8x/uveZ8fu4C0txLAE
|
||||||
|
-----END RSA PRIVATE KEY-----"#.to_string()
|
||||||
|
));
|
||||||
|
auth_man
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
use crate::app::{App, AppResult};
|
|
||||||
use crossterm::event::{KeyCode, KeyEvent, KeyModifiers};
|
|
||||||
|
|
||||||
/// Handles the key events and updates the state of [`App`].
|
|
||||||
pub fn handle_key_events(key_event: KeyEvent, app: &mut App) -> AppResult<()> {
|
|
||||||
match key_event.code {
|
|
||||||
// Exit application on `ESC` or `q`
|
|
||||||
KeyCode::Esc | KeyCode::Char('q') => {
|
|
||||||
app.quit();
|
|
||||||
}
|
|
||||||
// Exit application on `Ctrl-C`
|
|
||||||
KeyCode::Char('c') | KeyCode::Char('C') => {
|
|
||||||
if key_event.modifiers == KeyModifiers::CONTROL {
|
|
||||||
app.quit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Counter handlers
|
|
||||||
KeyCode::Right => {
|
|
||||||
app.increment_counter();
|
|
||||||
}
|
|
||||||
KeyCode::Left => {
|
|
||||||
app.decrement_counter();
|
|
||||||
}
|
|
||||||
// Other handlers you could add here.
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
83
src/main.rs
83
src/main.rs
@@ -1,46 +1,71 @@
|
|||||||
use std::io;
|
use std::io;
|
||||||
|
|
||||||
|
use app::AppComponents;
|
||||||
|
use component::{home::Home, input::Input};
|
||||||
|
use connection::{
|
||||||
|
authentication::AuthenticationMethod, connection_config::{
|
||||||
|
ConnectionManager, ConnectionType, ShConnectionConfig, SshConnectionConfig,
|
||||||
|
}, Connection
|
||||||
|
};
|
||||||
|
use global::AUTH_MAN;
|
||||||
use ratatui::{backend::CrosstermBackend, Terminal};
|
use ratatui::{backend::CrosstermBackend, Terminal};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
app::{App, AppResult},
|
app::{App, AppResult},
|
||||||
event::{Event, EventHandler},
|
event::EventHandler,
|
||||||
handler::handle_key_events,
|
|
||||||
tui::Tui,
|
tui::Tui,
|
||||||
|
util::{sh_config, ssh_config},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub mod app;
|
pub mod app;
|
||||||
|
pub mod component;
|
||||||
|
pub mod connection;
|
||||||
pub mod event;
|
pub mod event;
|
||||||
pub mod handler;
|
|
||||||
pub mod tui;
|
pub mod tui;
|
||||||
pub mod ui;
|
pub mod ui;
|
||||||
|
pub mod util;
|
||||||
|
pub mod global;
|
||||||
|
|
||||||
#[tokio::main]
|
// #[tokio::main]
|
||||||
async fn main() -> AppResult<()> {
|
// async fn main() -> AppResult<()> {
|
||||||
// Create an application.
|
// // Create an application.
|
||||||
let mut app = App::new();
|
// let mut app = App::new();
|
||||||
|
// let mut components = AppComponents::new();
|
||||||
|
// components.add_component(Box::new(Home::new()));
|
||||||
|
|
||||||
// Initialize the terminal user interface.
|
// // Initialize the terminal user interface.
|
||||||
let backend = CrosstermBackend::new(io::stdout());
|
// let backend = CrosstermBackend::new(io::stdout());
|
||||||
let terminal = Terminal::new(backend)?;
|
// let terminal = Terminal::new(backend)?; let events = EventHandler::new(250);
|
||||||
let events = EventHandler::new(250);
|
// let mut tui = Tui::new(terminal, events);
|
||||||
let mut tui = Tui::new(terminal, events);
|
// tui.init()?;
|
||||||
tui.init()?;
|
|
||||||
|
|
||||||
// Start the main loop.
|
// // Start the main loop.
|
||||||
while app.running {
|
// while app.running {
|
||||||
// Render the user interface.
|
// // Render the user interface.
|
||||||
tui.draw(&mut app)?;
|
// tui.draw(&mut app, &mut components)?;
|
||||||
// Handle events.
|
// // Handle events.
|
||||||
match tui.events.next().await? {
|
// tui.handle_events(&mut app, &mut components).await?;
|
||||||
Event::Tick => app.tick(),
|
// }
|
||||||
Event::Key(key_event) => handle_key_events(key_event, &mut app)?,
|
|
||||||
Event::Mouse(_) => {}
|
// // Exit the user interface.
|
||||||
Event::Resize(_, _) => {}
|
// tui.exit()?;
|
||||||
}
|
// Ok(())
|
||||||
}
|
// }
|
||||||
|
|
||||||
// Exit the user interface.
|
fn main() {
|
||||||
tui.exit()?;
|
|
||||||
Ok(())
|
let config = ConnectionManager {
|
||||||
|
connection_type: ConnectionType::SSH(SshConnectionConfig {
|
||||||
|
host: "myhost.fallen-angle.com".to_string(),
|
||||||
|
port: 22,
|
||||||
|
user: "rainbus".to_string(),
|
||||||
|
auth_name: "tencent".to_string(),
|
||||||
|
}),
|
||||||
|
// connection_type: ConnectionType::SH(ShConnectionConfig {
|
||||||
|
// command: "bash".to_string(),
|
||||||
|
// path: "".to_string(),
|
||||||
|
// args: vec![],
|
||||||
|
// })
|
||||||
|
};
|
||||||
|
config.connect().unwrap();
|
||||||
}
|
}
|
||||||
|
|||||||
47
src/tui.rs
47
src/tui.rs
@@ -1,12 +1,15 @@
|
|||||||
use crate::app::{App, AppResult};
|
use crate::{
|
||||||
use crate::event::EventHandler;
|
app::{self, App, AppComponents, AppResult},
|
||||||
use crate::ui;
|
component,
|
||||||
use crossterm::event::{DisableMouseCapture, EnableMouseCapture};
|
event::{Event, EventHandler},
|
||||||
use crossterm::terminal::{self, EnterAlternateScreen, LeaveAlternateScreen};
|
ui,
|
||||||
use ratatui::backend::Backend;
|
};
|
||||||
use ratatui::Terminal;
|
use crossterm::{
|
||||||
use std::io;
|
event::{DisableMouseCapture, EnableMouseCapture, KeyCode},
|
||||||
use std::panic;
|
terminal::{self, EnterAlternateScreen, LeaveAlternateScreen},
|
||||||
|
};
|
||||||
|
use ratatui::{backend::Backend, Terminal};
|
||||||
|
use std::{io, panic};
|
||||||
|
|
||||||
/// Representation of a terminal user interface.
|
/// Representation of a terminal user interface.
|
||||||
///
|
///
|
||||||
@@ -50,11 +53,33 @@ impl<B: Backend> Tui<B> {
|
|||||||
///
|
///
|
||||||
/// [`Draw`]: ratatui::Terminal::draw
|
/// [`Draw`]: ratatui::Terminal::draw
|
||||||
/// [`rendering`]: crate::ui::render
|
/// [`rendering`]: crate::ui::render
|
||||||
pub fn draw(&mut self, app: &mut App) -> AppResult<()> {
|
pub fn draw(&mut self, app: &mut App, components: &mut AppComponents) -> AppResult<()> {
|
||||||
self.terminal.draw(|frame| ui::render(app, frame))?;
|
self.terminal
|
||||||
|
.draw(|frame| ui::render(app, components, frame))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn handle_events(
|
||||||
|
&mut self,
|
||||||
|
app: &mut App,
|
||||||
|
components: &mut AppComponents,
|
||||||
|
) -> AppResult<()> {
|
||||||
|
match self.events.next().await? {
|
||||||
|
Event::Key(key_event) => {
|
||||||
|
for component in components.components.iter_mut() {
|
||||||
|
component.handle_event(app, &crossterm::event::Event::Key(key_event));
|
||||||
|
}
|
||||||
|
if key_event.code == KeyCode::Esc {
|
||||||
|
app.quit();
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
Event::Tick => Ok(()),
|
||||||
|
Event::Mouse(_) => Ok(()),
|
||||||
|
Event::Resize(_, _) => Ok(()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Resets the terminal interface.
|
/// Resets the terminal interface.
|
||||||
///
|
///
|
||||||
/// This function is also used for the panic hook to revert
|
/// This function is also used for the panic hook to revert
|
||||||
|
|||||||
41
src/ui.rs
41
src/ui.rs
@@ -1,34 +1,31 @@
|
|||||||
use ratatui::{
|
use ratatui::{
|
||||||
layout::Alignment,
|
layout::{Alignment, Constraint, Direction, Layout},
|
||||||
style::{Color, Style},
|
style::{Color, Style},
|
||||||
widgets::{Block, BorderType, Paragraph},
|
widgets::{Block, BorderType, Borders, Paragraph},
|
||||||
Frame,
|
Frame,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::app::App;
|
use crate::{
|
||||||
|
app::{App, AppComponents},
|
||||||
|
component::input,
|
||||||
|
};
|
||||||
|
|
||||||
/// Renders the user interface widgets.
|
/// Renders the user interface widgets.
|
||||||
pub fn render(app: &mut App, frame: &mut Frame) {
|
pub fn render(app: &mut App, components: &mut AppComponents, frame: &mut Frame) {
|
||||||
// This is where you add new widgets.
|
// This is where you add new widgets.
|
||||||
// See the following resources:
|
// See the following resources:
|
||||||
// - https://docs.rs/ratatui/latest/ratatui/widgets/index.html
|
// - https://docs.rs/ratatui/latest/ratatui/widgets/index.html
|
||||||
// - https://github.com/ratatui/ratatui/tree/master/examples
|
// - https://github.com/ratatui/ratatui/tree/master/examples
|
||||||
frame.render_widget(
|
// let layout = Layout::default()
|
||||||
Paragraph::new(format!(
|
// .direction(Direction::Vertical)
|
||||||
"This is a tui template.\n\
|
// .constraints([
|
||||||
Press `Esc`, `Ctrl-C` or `q` to stop running.\n\
|
// Constraint::Length(3),
|
||||||
Press left and right to increment and decrement the counter respectively.\n\
|
// Constraint::Min(1),
|
||||||
Counter: {}",
|
// Constraint::Length(1),
|
||||||
app.counter
|
// ])
|
||||||
))
|
// .split(frame.area());
|
||||||
.block(
|
// for (index, component) in components.components.iter_mut().enumerate() {
|
||||||
Block::bordered()
|
// component.draw(frame, app, layout[index]);
|
||||||
.title("Template")
|
// }
|
||||||
.title_alignment(Alignment::Center)
|
components.components[0].draw(frame, app, frame.area());
|
||||||
.border_type(BorderType::Rounded),
|
|
||||||
)
|
|
||||||
.style(Style::default().fg(Color::Cyan).bg(Color::Black))
|
|
||||||
.centered(),
|
|
||||||
frame.area(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|||||||
2
src/util.rs
Normal file
2
src/util.rs
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
pub mod sh_config;
|
||||||
|
pub mod ssh_config;
|
||||||
22
src/util/sh_config.rs
Normal file
22
src/util/sh_config.rs
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
use std::{error::Error, path::Path};
|
||||||
|
|
||||||
|
#[cfg(any(target_os = "linux", target_os = "macos"))]
|
||||||
|
pub fn get_shells() -> Result<Vec<String>, Box<dyn Error>> {
|
||||||
|
let path = Path::new("/etc/shells");
|
||||||
|
let file_content = std::fs::read_to_string(path)?;
|
||||||
|
let shells = file_content
|
||||||
|
.lines()
|
||||||
|
.filter(|line| !(line.starts_with("#") || line.is_empty()))
|
||||||
|
.map(|line| line.to_string())
|
||||||
|
.collect::<Vec<String>>();
|
||||||
|
Ok(shells)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
pub fn get_shells() -> Result<Vec<String>, Box<dyn Error>> {
|
||||||
|
let shells = vec![
|
||||||
|
"C:\\Windows\\System32\\cmd.exe",
|
||||||
|
"C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe",
|
||||||
|
];
|
||||||
|
Ok(shells)
|
||||||
|
}
|
||||||
9
src/util/ssh_config.rs
Normal file
9
src/util/ssh_config.rs
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
use std::error::Error;
|
||||||
|
|
||||||
|
use ssh_cfg::{SshConfig, SshConfigParser};
|
||||||
|
|
||||||
|
pub async fn ssh_config() -> Result<SshConfig, Box<dyn Error>> {
|
||||||
|
let sshs = SshConfigParser::parse_home().await?;
|
||||||
|
|
||||||
|
Ok(sshs)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user