add: realm boilerplate, copy of demo

This commit is contained in:
Charles
2024-11-26 22:24:13 -08:00
parent e1c1ed0995
commit 6076d13a70
9 changed files with 1589 additions and 2 deletions
Generated
+764
View File
@@ -2,6 +2,770 @@
# It is not intended for manual editing.
version = 3
[[package]]
name = "aho-corasick"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
dependencies = [
"memchr",
]
[[package]]
name = "allocator-api2"
version = "0.2.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "45862d1c77f2228b9e10bc609d5bc203d86ebc9b87ad8d5d5167a6c9abf739d9"
[[package]]
name = "autocfg"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
[[package]]
name = "bitflags"
version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
[[package]]
name = "cassowary"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53"
[[package]]
name = "castaway"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0abae9be0aaf9ea96a3b1b8b1b55c602ca751eba1b1500220cea4ecbafe7c0d5"
dependencies = [
"rustversion",
]
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "compact_str"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6050c3a16ddab2e412160b31f2c871015704239bca62f72f6e5f0be631d3f644"
dependencies = [
"castaway",
"cfg-if",
"itoa",
"rustversion",
"ryu",
"static_assertions",
]
[[package]]
name = "crossterm"
version = "0.28.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "829d955a0bb380ef178a640b91779e3987da38c9aea133b20614cfed8cdea9c6"
dependencies = [
"bitflags",
"crossterm_winapi",
"mio",
"parking_lot",
"rustix",
"signal-hook",
"signal-hook-mio",
"winapi",
]
[[package]]
name = "crossterm_winapi"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b"
dependencies = [
"winapi",
]
[[package]]
name = "darling"
version = "0.20.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989"
dependencies = [
"darling_core",
"darling_macro",
]
[[package]]
name = "darling_core"
version = "0.20.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5"
dependencies = [
"fnv",
"ident_case",
"proc-macro2",
"quote",
"strsim",
"syn",
]
[[package]]
name = "darling_macro"
version = "0.20.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806"
dependencies = [
"darling_core",
"quote",
"syn",
]
[[package]]
name = "diff"
version = "0.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8"
[[package]]
name = "either"
version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
[[package]]
name = "equivalent"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
[[package]]
name = "errno"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba"
dependencies = [
"libc",
"windows-sys",
]
[[package]]
name = "fnv"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
name = "foldhash"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f81ec6369c545a7d40e4589b5597581fa1c441fe1cce96dd1de43159910a36a2"
[[package]]
name = "hashbrown"
version = "0.15.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289"
dependencies = [
"allocator-api2",
"equivalent",
"foldhash",
]
[[package]]
name = "heck"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
[[package]]
name = "hermit-abi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
[[package]]
name = "ident_case"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
[[package]]
name = "indoc"
version = "2.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b248f5224d1d606005e02c97f5aa4e88eeb230488bcc03bc9ca4d7991399f2b5"
[[package]]
name = "instability"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b829f37dead9dc39df40c2d3376c179fdfd2ac771f53f55d3c30dc096a3c0c6e"
dependencies = [
"darling",
"indoc",
"pretty_assertions",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "itertools"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186"
dependencies = [
"either",
]
[[package]]
name = "itoa"
version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674"
[[package]]
name = "lazy-regex"
version = "3.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d8e41c97e6bc7ecb552016274b99fbb5d035e8de288c582d9b933af6677bfda"
dependencies = [
"lazy-regex-proc_macros",
"once_cell",
"regex",
]
[[package]]
name = "lazy-regex-proc_macros"
version = "3.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "76e1d8b05d672c53cb9c7b920bbba8783845ae4f0b076e02a3db1d02c81b4163"
dependencies = [
"proc-macro2",
"quote",
"regex",
"syn",
]
[[package]]
name = "libc"
version = "0.2.166"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2ccc108bbc0b1331bd061864e7cd823c0cab660bbe6970e66e2c0614decde36"
[[package]]
name = "linux-raw-sys"
version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89"
[[package]]
name = "lock_api"
version = "0.4.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17"
dependencies = [
"autocfg",
"scopeguard",
]
[[package]]
name = "log"
version = "0.4.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
[[package]]
name = "lru"
version = "0.12.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38"
dependencies = [
"hashbrown",
]
[[package]]
name = "memchr"
version = "2.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
[[package]]
name = "mio"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec"
dependencies = [
"hermit-abi",
"libc",
"log",
"wasi",
"windows-sys",
]
[[package]]
name = "once_cell"
version = "1.20.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
[[package]]
name = "orangepunk-tui"
version = "0.1.0"
dependencies = [
"tui-realm-stdlib",
"tuirealm",
]
[[package]]
name = "parking_lot"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27"
dependencies = [
"lock_api",
"parking_lot_core",
]
[[package]]
name = "parking_lot_core"
version = "0.9.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8"
dependencies = [
"cfg-if",
"libc",
"redox_syscall",
"smallvec",
"windows-targets",
]
[[package]]
name = "paste"
version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
[[package]]
name = "pretty_assertions"
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ae130e2f271fbc2ac3a40fb1d07180839cdbbe443c7a27e1e3c13c5cac0116d"
dependencies = [
"diff",
"yansi",
]
[[package]]
name = "proc-macro2"
version = "1.0.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
dependencies = [
"proc-macro2",
]
[[package]]
name = "ratatui"
version = "0.28.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fdef7f9be5c0122f890d58bdf4d964349ba6a6161f705907526d891efabba57d"
dependencies = [
"bitflags",
"cassowary",
"compact_str",
"crossterm",
"instability",
"itertools",
"lru",
"paste",
"strum",
"strum_macros",
"unicode-segmentation",
"unicode-truncate",
"unicode-width 0.1.14",
]
[[package]]
name = "redox_syscall"
version = "0.5.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f"
dependencies = [
"bitflags",
]
[[package]]
name = "regex"
version = "1.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
dependencies = [
"aho-corasick",
"memchr",
"regex-automata",
"regex-syntax",
]
[[package]]
name = "regex-automata"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
[[package]]
name = "rustix"
version = "0.38.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d7f649912bc1495e167a6edee79151c84b1bad49748cb4f1f1167f459f6224f6"
dependencies = [
"bitflags",
"errno",
"libc",
"linux-raw-sys",
"windows-sys",
]
[[package]]
name = "rustversion"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248"
[[package]]
name = "ryu"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
[[package]]
name = "scopeguard"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "signal-hook"
version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801"
dependencies = [
"libc",
"signal-hook-registry",
]
[[package]]
name = "signal-hook-mio"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34db1a06d485c9142248b7a054f034b349b212551f3dfd19c94d45a754a217cd"
dependencies = [
"libc",
"mio",
"signal-hook",
]
[[package]]
name = "signal-hook-registry"
version = "1.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1"
dependencies = [
"libc",
]
[[package]]
name = "smallvec"
version = "1.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
[[package]]
name = "smawk"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7c388c1b5e93756d0c740965c41e8822f866621d41acbdf6336a6a168f8840c"
[[package]]
name = "static_assertions"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
[[package]]
name = "strsim"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
[[package]]
name = "strum"
version = "0.26.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06"
dependencies = [
"strum_macros",
]
[[package]]
name = "strum_macros"
version = "0.26.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be"
dependencies = [
"heck",
"proc-macro2",
"quote",
"rustversion",
"syn",
]
[[package]]
name = "syn"
version = "2.0.89"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44d46482f1c1c87acd84dea20c1bf5ebff4c757009ed6bf19cfd36fb10e92c4e"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[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 0.1.14",
]
[[package]]
name = "thiserror"
version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "tui-realm-stdlib"
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78a24d06b8403c57b32a3d3fdac795adf4ef8610e5f9650a3629efc8a9d6c0bb"
dependencies = [
"textwrap",
"tuirealm",
"unicode-width 0.2.0",
]
[[package]]
name = "tuirealm"
version = "2.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d3865c9f0e84c07c991c24c853f095bb764859fa3806fe6e00b559f40f1253f"
dependencies = [
"bitflags",
"crossterm",
"lazy-regex",
"ratatui",
"thiserror",
"tuirealm_derive",
]
[[package]]
name = "tuirealm_derive"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "caa8b0560f4245acc0bbe0e1d76e1f6a308145dd6e107befce4cf29e7fe32662"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "unicode-ident"
version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83"
[[package]]
name = "unicode-linebreak"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f"
[[package]]
name = "unicode-segmentation"
version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493"
[[package]]
name = "unicode-truncate"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b3644627a5af5fa321c95b9b235a72fd24cd29c648c2c379431e6628655627bf"
dependencies = [
"itertools",
"unicode-segmentation",
"unicode-width 0.1.14",
]
[[package]]
name = "unicode-width"
version = "0.1.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af"
[[package]]
name = "unicode-width"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd"
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-sys"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-targets"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_gnullvm",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
[[package]]
name = "windows_i686_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
[[package]]
name = "windows_i686_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
[[package]]
name = "windows_i686_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
[[package]]
name = "yansi"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049"
+2
View File
@@ -4,3 +4,5 @@ version = "0.1.0"
edition = "2021"
[dependencies]
tui-realm-stdlib = "2.0.1"
tuirealm = "2.0.3"
+7
View File
@@ -0,0 +1,7 @@
//! ## Terminal
//!
//! terminal helper
pub use super::*;
pub mod model;
+190
View File
@@ -0,0 +1,190 @@
//! ## Model
//!
//! app model
use std::time::{Duration, SystemTime};
use tuirealm::event::NoUserEvent;
use tuirealm::props::{Alignment, Color, TextModifiers};
use tuirealm::ratatui::layout::{Constraint, Direction, Layout};
use tuirealm::terminal::{CrosstermTerminalAdapter, TerminalAdapter, TerminalBridge};
use tuirealm::{
Application, AttrValue, Attribute, EventListenerCfg, Sub, SubClause, SubEventClause, Update,
};
use super::components::{Clock, DigitCounter, Label, LetterCounter};
use super::{Id, Msg};
pub struct Model<T>
where
T: TerminalAdapter,
{
/// Application
pub app: Application<Id, Msg, NoUserEvent>,
/// Indicates that the application must quit
pub quit: bool,
/// Tells whether to redraw interface
pub redraw: bool,
/// Used to draw to terminal
pub terminal: TerminalBridge<T>,
}
impl Default for Model<CrosstermTerminalAdapter> {
fn default() -> Self {
Self {
app: Self::init_app(),
quit: false,
redraw: true,
terminal: TerminalBridge::init_crossterm().expect("Cannot initialize terminal"),
}
}
}
impl<T> Model<T>
where
T: TerminalAdapter,
{
pub fn view(&mut self) {
assert!(self
.terminal
.draw(|f| {
let chunks = Layout::default()
.direction(Direction::Vertical)
.margin(1)
.constraints(
[
Constraint::Length(3), // Clock
Constraint::Length(3), // Letter Counter
Constraint::Length(3), // Digit Counter
Constraint::Length(1), // Label
]
.as_ref(),
)
.split(f.area());
self.app.view(&Id::Clock, f, chunks[0]);
self.app.view(&Id::LetterCounter, f, chunks[1]);
self.app.view(&Id::DigitCounter, f, chunks[2]);
self.app.view(&Id::Label, f, chunks[3]);
})
.is_ok());
}
fn init_app() -> Application<Id, Msg, NoUserEvent> {
// Setup application
// NOTE: NoUserEvent is a shorthand to tell tui-realm we're not going to use any custom user event
// NOTE: the event listener is configured to use the default crossterm input listener and to raise a Tick event each second
// which we will use to update the clock
let mut app: Application<Id, Msg, NoUserEvent> = Application::init(
EventListenerCfg::default()
.crossterm_input_listener(Duration::from_millis(20), 3)
.poll_timeout(Duration::from_millis(10))
.tick_interval(Duration::from_secs(1)),
);
// Mount components
assert!(app
.mount(
Id::Label,
Box::new(
Label::default()
.text("Waiting for a Msg...")
.alignment(Alignment::Left)
.background(Color::Reset)
.foreground(Color::LightYellow)
.modifiers(TextModifiers::BOLD),
),
Vec::default(),
)
.is_ok());
// Mount clock, subscribe to tick
assert!(app
.mount(
Id::Clock,
Box::new(
Clock::new(SystemTime::now())
.alignment(Alignment::Center)
.background(Color::Reset)
.foreground(Color::Cyan)
.modifiers(TextModifiers::BOLD)
),
vec![Sub::new(SubEventClause::Tick, SubClause::Always)]
)
.is_ok());
// Mount counters
assert!(app
.mount(
Id::LetterCounter,
Box::new(LetterCounter::new(0)),
Vec::new()
)
.is_ok());
assert!(app
.mount(
Id::DigitCounter,
Box::new(DigitCounter::new(5)),
Vec::default()
)
.is_ok());
// Active letter counter
assert!(app.active(&Id::LetterCounter).is_ok());
app
}
}
// Let's implement Update for model
impl<T> Update<Msg> for Model<T>
where
T: TerminalAdapter,
{
fn update(&mut self, msg: Option<Msg>) -> Option<Msg> {
if let Some(msg) = msg {
// Set redraw
self.redraw = true;
// Match message
match msg {
Msg::AppClose => {
self.quit = true; // Terminate
None
}
Msg::Clock => None,
Msg::DigitCounterBlur => {
// Give focus to letter counter
assert!(self.app.active(&Id::LetterCounter).is_ok());
None
}
Msg::DigitCounterChanged(v) => {
// Update label
assert!(self
.app
.attr(
&Id::Label,
Attribute::Text,
AttrValue::String(format!("DigitCounter has now value: {}", v))
)
.is_ok());
None
}
Msg::LetterCounterBlur => {
// Give focus to digit counter
assert!(self.app.active(&Id::DigitCounter).is_ok());
None
}
Msg::LetterCounterChanged(v) => {
// Update label
assert!(self
.app
.attr(
&Id::Label,
Attribute::Text,
AttrValue::String(format!("LetterCounter has now value: {}", v))
)
.is_ok());
None
}
}
} else {
None
}
}
}
+120
View File
@@ -0,0 +1,120 @@
//! ## Label
//!
//! label component
use std::ops::Add;
use std::time::{Duration, SystemTime, UNIX_EPOCH};
use tuirealm::command::{Cmd, CmdResult};
use tuirealm::props::{Alignment, Color, TextModifiers};
use tuirealm::ratatui::layout::Rect;
use tuirealm::{
AttrValue, Attribute, Component, Event, Frame, MockComponent, NoUserEvent, State, StateValue,
};
use super::{Label, Msg};
/// Simple clock component which displays current time
pub struct Clock {
component: Label,
states: OwnStates,
}
impl Clock {
pub fn new(initial_time: SystemTime) -> Self {
Self {
component: Label::default(),
states: OwnStates::new(initial_time),
}
}
pub fn alignment(mut self, a: Alignment) -> Self {
self.component
.attr(Attribute::TextAlign, AttrValue::Alignment(a));
self
}
pub fn foreground(mut self, c: Color) -> Self {
self.component
.attr(Attribute::Foreground, AttrValue::Color(c));
self
}
pub fn background(mut self, c: Color) -> Self {
self.component
.attr(Attribute::Background, AttrValue::Color(c));
self
}
pub fn modifiers(mut self, m: TextModifiers) -> Self {
self.attr(Attribute::TextProps, AttrValue::TextModifiers(m));
self
}
fn time_to_str(&self) -> String {
let since_the_epoch = self.get_epoch_time();
let hours = (since_the_epoch / 3600) % 24;
let minutes = (since_the_epoch / 60) % 60;
let seconds = since_the_epoch % 60;
format!("{:02}:{:02}:{:02}", hours, minutes, seconds)
}
fn get_epoch_time(&self) -> u64 {
self.states
.time
.duration_since(UNIX_EPOCH)
.expect("Time went backwards")
.as_secs()
}
}
impl MockComponent for Clock {
fn view(&mut self, frame: &mut Frame, area: Rect) {
// Render
self.component.view(frame, area);
}
fn query(&self, attr: Attribute) -> Option<AttrValue> {
self.component.query(attr)
}
fn attr(&mut self, attr: Attribute, value: AttrValue) {
self.component.attr(attr, value);
}
fn state(&self) -> State {
// Return current time
State::One(StateValue::U64(self.get_epoch_time()))
}
fn perform(&mut self, cmd: Cmd) -> CmdResult {
self.component.perform(cmd)
}
}
impl Component<Msg, NoUserEvent> for Clock {
fn on(&mut self, ev: Event<NoUserEvent>) -> Option<Msg> {
if let Event::Tick = ev {
self.states.tick();
// Set text
self.attr(Attribute::Text, AttrValue::String(self.time_to_str()));
Some(Msg::Clock)
} else {
None
}
}
}
struct OwnStates {
time: SystemTime,
}
impl OwnStates {
pub fn new(time: SystemTime) -> Self {
Self { time }
}
pub fn tick(&mut self) {
self.time = self.time.add(Duration::from_secs(1));
}
}
+273
View File
@@ -0,0 +1,273 @@
//! ## Label
//!
//! label component
use tuirealm::command::{Cmd, CmdResult};
use tuirealm::event::{Key, KeyEvent, KeyModifiers};
use tuirealm::props::{Alignment, Borders, Color, Style, TextModifiers};
use tuirealm::ratatui::layout::Rect;
use tuirealm::ratatui::widgets::{BorderType, Paragraph};
use tuirealm::{
AttrValue, Attribute, Component, Event, Frame, MockComponent, NoUserEvent, Props, State,
StateValue,
};
use super::{get_block, Msg};
/// Counter which increments its value on Submit
struct Counter {
props: Props,
states: OwnStates,
}
impl Default for Counter {
fn default() -> Self {
Self {
props: Props::default(),
states: OwnStates::default(),
}
}
}
impl Counter {
pub fn label<S>(mut self, label: S) -> Self
where
S: AsRef<str>,
{
self.attr(
Attribute::Title,
AttrValue::Title((label.as_ref().to_string(), Alignment::Center)),
);
self
}
pub fn value(mut self, n: isize) -> Self {
self.attr(Attribute::Value, AttrValue::Number(n));
self
}
pub fn alignment(mut self, a: Alignment) -> Self {
self.attr(Attribute::TextAlign, AttrValue::Alignment(a));
self
}
pub fn foreground(mut self, c: Color) -> Self {
self.attr(Attribute::Foreground, AttrValue::Color(c));
self
}
pub fn background(mut self, c: Color) -> Self {
self.attr(Attribute::Background, AttrValue::Color(c));
self
}
pub fn modifiers(mut self, m: TextModifiers) -> Self {
self.attr(Attribute::TextProps, AttrValue::TextModifiers(m));
self
}
pub fn borders(mut self, b: Borders) -> Self {
self.attr(Attribute::Borders, AttrValue::Borders(b));
self
}
}
impl MockComponent for Counter {
fn view(&mut self, frame: &mut Frame, area: Rect) {
// Check if visible
if self.props.get_or(Attribute::Display, AttrValue::Flag(true)) == AttrValue::Flag(true) {
// Get properties
let text = self.states.counter.to_string();
let alignment = self
.props
.get_or(Attribute::TextAlign, AttrValue::Alignment(Alignment::Left))
.unwrap_alignment();
let foreground = self
.props
.get_or(Attribute::Foreground, AttrValue::Color(Color::Reset))
.unwrap_color();
let background = self
.props
.get_or(Attribute::Background, AttrValue::Color(Color::Reset))
.unwrap_color();
let modifiers = self
.props
.get_or(
Attribute::TextProps,
AttrValue::TextModifiers(TextModifiers::empty()),
)
.unwrap_text_modifiers();
let title = self
.props
.get_or(
Attribute::Title,
AttrValue::Title((String::default(), Alignment::Center)),
)
.unwrap_title();
let borders = self
.props
.get_or(Attribute::Borders, AttrValue::Borders(Borders::default()))
.unwrap_borders();
let focus = self
.props
.get_or(Attribute::Focus, AttrValue::Flag(false))
.unwrap_flag();
frame.render_widget(
Paragraph::new(text)
.block(get_block(borders, title, focus))
.style(
Style::default()
.fg(foreground)
.bg(background)
.add_modifier(modifiers),
)
.alignment(alignment),
area,
);
}
}
fn query(&self, attr: Attribute) -> Option<AttrValue> {
self.props.get(attr)
}
fn attr(&mut self, attr: Attribute, value: AttrValue) {
self.props.set(attr, value);
}
fn state(&self) -> State {
State::One(StateValue::Isize(self.states.counter))
}
fn perform(&mut self, cmd: Cmd) -> CmdResult {
match cmd {
Cmd::Submit => {
self.states.incr();
CmdResult::Changed(self.state())
}
_ => CmdResult::None,
}
}
}
struct OwnStates {
counter: isize,
}
impl Default for OwnStates {
fn default() -> Self {
Self { counter: 0 }
}
}
impl OwnStates {
fn incr(&mut self) {
self.counter += 1;
}
}
// -- Counter components
#[derive(MockComponent)]
pub struct LetterCounter {
component: Counter,
}
impl LetterCounter {
pub fn new(initial_value: isize) -> Self {
Self {
component: Counter::default()
.alignment(Alignment::Center)
.background(Color::Reset)
.borders(
Borders::default()
.color(Color::LightGreen)
.modifiers(BorderType::Rounded),
)
.foreground(Color::LightGreen)
.modifiers(TextModifiers::BOLD)
.value(initial_value)
.label("Letter counter"),
}
}
}
impl Component<Msg, NoUserEvent> for LetterCounter {
fn on(&mut self, ev: Event<NoUserEvent>) -> Option<Msg> {
// Get command
let cmd = match ev {
Event::Keyboard(KeyEvent {
code: Key::Char(ch),
modifiers: KeyModifiers::NONE,
}) if ch.is_alphabetic() => Cmd::Submit,
Event::Keyboard(KeyEvent {
code: Key::Tab,
modifiers: KeyModifiers::NONE,
}) => return Some(Msg::LetterCounterBlur), // Return focus lost
Event::Keyboard(KeyEvent {
code: Key::Esc,
modifiers: KeyModifiers::NONE,
}) => return Some(Msg::AppClose),
_ => Cmd::None,
};
// perform
match self.perform(cmd) {
CmdResult::Changed(State::One(StateValue::Isize(c))) => {
Some(Msg::LetterCounterChanged(c))
}
_ => None,
}
}
}
#[derive(MockComponent)]
pub struct DigitCounter {
component: Counter,
}
impl DigitCounter {
pub fn new(initial_value: isize) -> Self {
Self {
component: Counter::default()
.alignment(Alignment::Center)
.background(Color::Reset)
.borders(
Borders::default()
.color(Color::Yellow)
.modifiers(BorderType::Rounded),
)
.foreground(Color::Yellow)
.modifiers(TextModifiers::BOLD)
.value(initial_value)
.label("Digit counter"),
}
}
}
impl Component<Msg, NoUserEvent> for DigitCounter {
fn on(&mut self, ev: Event<NoUserEvent>) -> Option<Msg> {
// Get command
let cmd = match ev {
Event::Keyboard(KeyEvent {
code: Key::Char(ch),
modifiers: KeyModifiers::NONE,
}) if ch.is_digit(10) => Cmd::Submit,
Event::Keyboard(KeyEvent {
code: Key::Tab,
modifiers: KeyModifiers::NONE,
}) => return Some(Msg::DigitCounterBlur), // Return focus lost
Event::Keyboard(KeyEvent {
code: Key::Esc,
modifiers: KeyModifiers::NONE,
}) => return Some(Msg::AppClose),
_ => Cmd::None,
};
// perform
match self.perform(cmd) {
CmdResult::Changed(State::One(StateValue::Isize(c))) => {
Some(Msg::DigitCounterChanged(c))
}
_ => None,
}
}
}
+124
View File
@@ -0,0 +1,124 @@
//! ## Label
//!
//! label component
use tuirealm::command::{Cmd, CmdResult};
use tuirealm::props::{Alignment, Color, Style, TextModifiers};
use tuirealm::ratatui::layout::Rect;
use tuirealm::ratatui::widgets::Paragraph;
use tuirealm::{
AttrValue, Attribute, Component, Event, Frame, MockComponent, NoUserEvent, Props, State,
};
use super::Msg;
/// Simple label component; just renders a text
/// NOTE: since I need just one label, I'm not going to use different object; I will directly implement Component for Label.
/// This is not ideal actually and in a real app you should differentiate Mock Components from Application Components.
pub struct Label {
props: Props,
}
impl Default for Label {
fn default() -> Self {
Self {
props: Props::default(),
}
}
}
impl Label {
pub fn text<S>(mut self, s: S) -> Self
where
S: AsRef<str>,
{
self.attr(Attribute::Text, AttrValue::String(s.as_ref().to_string()));
self
}
pub fn alignment(mut self, a: Alignment) -> Self {
self.attr(Attribute::TextAlign, AttrValue::Alignment(a));
self
}
pub fn foreground(mut self, c: Color) -> Self {
self.attr(Attribute::Foreground, AttrValue::Color(c));
self
}
pub fn background(mut self, c: Color) -> Self {
self.attr(Attribute::Background, AttrValue::Color(c));
self
}
pub fn modifiers(mut self, m: TextModifiers) -> Self {
self.attr(Attribute::TextProps, AttrValue::TextModifiers(m));
self
}
}
impl MockComponent for Label {
fn view(&mut self, frame: &mut Frame, area: Rect) {
// Check if visible
if self.props.get_or(Attribute::Display, AttrValue::Flag(true)) == AttrValue::Flag(true) {
// Get properties
let text = self
.props
.get_or(Attribute::Text, AttrValue::String(String::default()))
.unwrap_string();
let alignment = self
.props
.get_or(Attribute::TextAlign, AttrValue::Alignment(Alignment::Left))
.unwrap_alignment();
let foreground = self
.props
.get_or(Attribute::Foreground, AttrValue::Color(Color::Reset))
.unwrap_color();
let background = self
.props
.get_or(Attribute::Background, AttrValue::Color(Color::Reset))
.unwrap_color();
let modifiers = self
.props
.get_or(
Attribute::TextProps,
AttrValue::TextModifiers(TextModifiers::empty()),
)
.unwrap_text_modifiers();
frame.render_widget(
Paragraph::new(text)
.style(
Style::default()
.fg(foreground)
.bg(background)
.add_modifier(modifiers),
)
.alignment(alignment),
area,
);
}
}
fn query(&self, attr: Attribute) -> Option<AttrValue> {
self.props.get(attr)
}
fn attr(&mut self, attr: Attribute, value: AttrValue) {
self.props.set(attr, value);
}
fn state(&self) -> State {
State::None
}
fn perform(&mut self, _: Cmd) -> CmdResult {
CmdResult::None
}
}
impl Component<Msg, NoUserEvent> for Label {
fn on(&mut self, _: Event<NoUserEvent>) -> Option<Msg> {
// Does nothing
None
}
}
+33
View File
@@ -0,0 +1,33 @@
//! ## Components
//!
//! demo example components
use tuirealm::props::{Alignment, Borders, Color, Style};
use tuirealm::ratatui::widgets::Block;
use super::Msg;
// -- modules
mod clock;
mod counter;
mod label;
// -- export
pub use clock::Clock;
pub use counter::{DigitCounter, LetterCounter};
pub use label::Label;
/// ### get_block
///
/// Get block
pub(crate) fn get_block<'a>(props: Borders, title: (String, Alignment), focus: bool) -> Block<'a> {
Block::default()
.borders(props.sides)
.border_style(match focus {
true => props.style(),
false => Style::default().fg(Color::Reset).bg(Color::Reset),
})
.border_type(props.modifiers)
.title(title.0)
.title_alignment(title.1)
}
+76 -2
View File
@@ -1,3 +1,77 @@
fn main() {
println!("Hello, world!");
//! ## Demo
//!
//! `Demo` shows how to use tui-realm in a real case
extern crate tuirealm;
use tuirealm::application::PollStrategy;
use tuirealm::{AttrValue, Attribute, Update};
// -- internal
mod app;
mod components;
use app::model::Model;
// Let's define the messages handled by our app. NOTE: it must derive `PartialEq`
#[derive(Debug, PartialEq)]
pub enum Msg {
AppClose,
Clock,
DigitCounterChanged(isize),
DigitCounterBlur,
LetterCounterChanged(isize),
LetterCounterBlur,
}
// Let's define the component ids for our application
#[derive(Debug, Eq, PartialEq, Clone, Hash)]
pub enum Id {
Clock,
DigitCounter,
LetterCounter,
Label,
}
fn main() {
// Setup model
let mut model = Model::default();
// Enter alternate screen
let _ = model.terminal.enter_alternate_screen();
let _ = model.terminal.enable_raw_mode();
// Main loop
// NOTE: loop until quit; quit is set in update if AppClose is received from counter
while !model.quit {
// Tick
match model.app.tick(PollStrategy::Once) {
Err(err) => {
assert!(model
.app
.attr(
&Id::Label,
Attribute::Text,
AttrValue::String(format!("Application error: {}", err)),
)
.is_ok());
}
Ok(messages) if messages.len() > 0 => {
// NOTE: redraw if at least one msg has been processed
model.redraw = true;
for msg in messages.into_iter() {
let mut msg = Some(msg);
while msg.is_some() {
msg = model.update(msg);
}
}
}
_ => {}
}
// Redraw
if model.redraw {
model.view();
model.redraw = false;
}
}
// Terminate terminal
let _ = model.terminal.leave_alternate_screen();
let _ = model.terminal.disable_raw_mode();
let _ = model.terminal.clear_screen();
}