Compare commits
1 Commits
dani/widge
...
feature/ni
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
08e35f209d |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,2 +1,3 @@
|
||||
target/*
|
||||
**/node_modules/*
|
||||
.DS_Store
|
||||
432
Cargo.lock
generated
432
Cargo.lock
generated
@@ -19,6 +19,18 @@ dependencies = [
|
||||
"cpufeatures",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ahash"
|
||||
version = "0.8.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"once_cell",
|
||||
"version_check",
|
||||
"zerocopy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aho-corasick"
|
||||
version = "1.1.3"
|
||||
@@ -28,6 +40,12 @@ dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "allocator-api2"
|
||||
version = "0.2.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f"
|
||||
|
||||
[[package]]
|
||||
name = "android-tzdata"
|
||||
version = "0.1.1"
|
||||
@@ -76,6 +94,12 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1"
|
||||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
version = "0.10.4"
|
||||
@@ -124,6 +148,21 @@ dependencies = [
|
||||
"pkg-config",
|
||||
]
|
||||
|
||||
[[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.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a17ed5635fc8536268e5d4de1e22e81ac34419e5f052d4d51f4e01dcc263fcc"
|
||||
dependencies = [
|
||||
"rustversion",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.90"
|
||||
@@ -151,7 +190,7 @@ dependencies = [
|
||||
"js-sys",
|
||||
"num-traits",
|
||||
"wasm-bindgen",
|
||||
"windows-targets",
|
||||
"windows-targets 0.52.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -186,6 +225,19 @@ dependencies = [
|
||||
"inout",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "compact_str"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f86b9c4c00838774a6d902ef931eff7470720c51d90c2e32cfe15dc304737b3f"
|
||||
dependencies = [
|
||||
"castaway",
|
||||
"cfg-if",
|
||||
"itoa",
|
||||
"ryu",
|
||||
"static_assertions",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "console_error_panic_hook"
|
||||
version = "0.1.7"
|
||||
@@ -232,6 +284,31 @@ version = "0.8.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345"
|
||||
|
||||
[[package]]
|
||||
name = "crossterm"
|
||||
version = "0.27.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f476fe445d41c9e991fd07515a6f463074b782242ccf4a5b7b1d1012e70824df"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"crossterm_winapi",
|
||||
"libc",
|
||||
"mio",
|
||||
"parking_lot",
|
||||
"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 = "crypto-common"
|
||||
version = "0.1.6"
|
||||
@@ -299,6 +376,22 @@ dependencies = [
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.14.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
"allocator-api2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
|
||||
|
||||
[[package]]
|
||||
name = "hmac"
|
||||
version = "0.12.1"
|
||||
@@ -331,6 +424,12 @@ dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indoc"
|
||||
version = "2.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b248f5224d1d606005e02c97f5aa4e88eeb230488bcc03bc9ca4d7991399f2b5"
|
||||
|
||||
[[package]]
|
||||
name = "inout"
|
||||
version = "0.1.3"
|
||||
@@ -411,12 +510,31 @@ version = "0.2.153"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
|
||||
|
||||
[[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.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
|
||||
|
||||
[[package]]
|
||||
name = "lru"
|
||||
version = "0.12.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d3262e75e648fce39813cb56ac41f3c3e3f65217ebf3844d818d1f9398cfb0dc"
|
||||
dependencies = [
|
||||
"hashbrown",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.7.2"
|
||||
@@ -432,6 +550,18 @@ dependencies = [
|
||||
"adler",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mio"
|
||||
version = "0.8.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"log",
|
||||
"wasi",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-conv"
|
||||
version = "0.1.0"
|
||||
@@ -453,6 +583,29 @@ version = "1.19.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
version = "0.12.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7e4af0ca4f6caed20e900d564c242b8e5d4903fdacf31d3daf527b66fe6f42fb"
|
||||
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 0.52.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parse-zoneinfo"
|
||||
version = "0.3.0"
|
||||
@@ -473,6 +626,12 @@ dependencies = [
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "paste"
|
||||
version = "1.0.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c"
|
||||
|
||||
[[package]]
|
||||
name = "pbkdf2"
|
||||
version = "0.11.0"
|
||||
@@ -589,6 +748,35 @@ dependencies = [
|
||||
"getrandom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ratatui"
|
||||
version = "0.26.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a564a852040e82671dc50a37d88f3aa83bbc690dfc6844cfe7a2591620206a80"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cassowary",
|
||||
"compact_str",
|
||||
"crossterm",
|
||||
"indoc",
|
||||
"itertools",
|
||||
"lru",
|
||||
"paste",
|
||||
"stability",
|
||||
"strum",
|
||||
"unicode-segmentation",
|
||||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.10.4"
|
||||
@@ -624,6 +812,12 @@ version = "0.19.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3cd14fd5e3b777a7422cca79358c57a8f6e3a703d9ac187448d0daf220c2407f"
|
||||
|
||||
[[package]]
|
||||
name = "rustversion"
|
||||
version = "1.0.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "80af6f9131f277a45a3fba6ce8e2258037bb0477a67e610d3c1fe046ab31de47"
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.17"
|
||||
@@ -636,6 +830,12 @@ version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294"
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.197"
|
||||
@@ -700,12 +900,86 @@ dependencies = [
|
||||
"digest",
|
||||
]
|
||||
|
||||
[[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.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "29ad2e15f37ec9a6cc544097b78a1ec90001e9f71b81338ca39f430adaca99af"
|
||||
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 = "siphasher"
|
||||
version = "0.3.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d"
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "1.13.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
|
||||
|
||||
[[package]]
|
||||
name = "stability"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2ff9eaf853dec4c8802325d8b6d3dffa86cc707fd7a1a4cdbf416e13b061787a"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "static_assertions"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
||||
|
||||
[[package]]
|
||||
name = "strum"
|
||||
version = "0.26.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5d8cec3501a5194c432b2b7976db6b7d10ec95c253208b45f83f7136aa985e29"
|
||||
dependencies = [
|
||||
"strum_macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "strum_macros"
|
||||
version = "0.26.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c6cf59daf282c0a494ba14fd21610a0325f9f90ec9d1231dea26bcb1d696c946"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"rustversion",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "subtle"
|
||||
version = "2.5.0"
|
||||
@@ -762,6 +1036,26 @@ version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
|
||||
|
||||
[[package]]
|
||||
name = "tiron"
|
||||
version = "0.1.3"
|
||||
dependencies = [
|
||||
"crossterm",
|
||||
"ironcalc",
|
||||
"ratatui",
|
||||
"tui-input",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tui-input"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b3e785f863a3af4c800a2a669d0b64c879b538738e352607e2624d03f868dc01"
|
||||
dependencies = [
|
||||
"crossterm",
|
||||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.17.0"
|
||||
@@ -774,6 +1068,18 @@ version = "1.0.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-segmentation"
|
||||
version = "1.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
version = "0.1.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "68f5e5f3158ecfd4b8ff6fe086db7c8467a2dfdac97fe420f2b7c4aa97af66d6"
|
||||
|
||||
[[package]]
|
||||
name = "uuid"
|
||||
version = "1.8.0"
|
||||
@@ -908,13 +1214,59 @@ dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[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-core"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
"windows-targets 0.52.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
|
||||
dependencies = [
|
||||
"windows-targets 0.48.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm 0.48.5",
|
||||
"windows_aarch64_msvc 0.48.5",
|
||||
"windows_i686_gnu 0.48.5",
|
||||
"windows_i686_msvc 0.48.5",
|
||||
"windows_x86_64_gnu 0.48.5",
|
||||
"windows_x86_64_gnullvm 0.48.5",
|
||||
"windows_x86_64_msvc 0.48.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -923,57 +1275,119 @@ version = "0.52.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
"windows_aarch64_gnullvm 0.52.4",
|
||||
"windows_aarch64_msvc 0.52.4",
|
||||
"windows_i686_gnu 0.52.4",
|
||||
"windows_i686_msvc 0.52.4",
|
||||
"windows_x86_64_gnu 0.52.4",
|
||||
"windows_x86_64_gnullvm 0.52.4",
|
||||
"windows_x86_64_msvc 0.52.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.52.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.52.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.52.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.52.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.52.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.52.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.52.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8"
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy"
|
||||
version = "0.7.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be"
|
||||
dependencies = [
|
||||
"zerocopy-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy-derive"
|
||||
version = "0.7.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zip"
|
||||
version = "0.6.6"
|
||||
|
||||
@@ -4,6 +4,7 @@ resolver = "2"
|
||||
members = [
|
||||
"base",
|
||||
"xlsx",
|
||||
"tironcalc",
|
||||
"bindings/wasm",
|
||||
]
|
||||
|
||||
|
||||
@@ -292,7 +292,10 @@ fn vertical(value: &str) -> Result<VerticalAlignment, String> {
|
||||
/// # }
|
||||
/// ```
|
||||
pub struct UserModel {
|
||||
model: Model,
|
||||
/// The underlying model
|
||||
/// See also:
|
||||
/// * [Model]
|
||||
pub model: Model,
|
||||
history: History,
|
||||
send_queue: Vec<QueueDiffs>,
|
||||
pause_evaluation: bool,
|
||||
@@ -645,7 +648,9 @@ impl UserModel {
|
||||
pub fn insert_row(&mut self, sheet: u32, row: i32) -> Result<(), String> {
|
||||
let diff_list = vec![Diff::InsertRow { sheet, row }];
|
||||
self.push_diff_list(diff_list);
|
||||
self.model.insert_rows(sheet, row, 1)
|
||||
self.model.insert_rows(sheet, row, 1)?;
|
||||
self.model.evaluate();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Deletes a row
|
||||
@@ -672,7 +677,9 @@ impl UserModel {
|
||||
old_data,
|
||||
}];
|
||||
self.push_diff_list(diff_list);
|
||||
self.model.delete_rows(sheet, row, 1)
|
||||
self.model.delete_rows(sheet, row, 1)?;
|
||||
self.model.evaluate();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Inserts a column
|
||||
@@ -682,7 +689,9 @@ impl UserModel {
|
||||
pub fn insert_column(&mut self, sheet: u32, column: i32) -> Result<(), String> {
|
||||
let diff_list = vec![Diff::InsertColumn { sheet, column }];
|
||||
self.push_diff_list(diff_list);
|
||||
self.model.insert_columns(sheet, column, 1)
|
||||
self.model.insert_columns(sheet, column, 1)?;
|
||||
self.model.evaluate();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Deletes a column
|
||||
@@ -727,7 +736,9 @@ impl UserModel {
|
||||
}),
|
||||
}];
|
||||
self.push_diff_list(diff_list);
|
||||
self.model.delete_columns(sheet, column, 1)
|
||||
self.model.delete_columns(sheet, column, 1)?;
|
||||
self.model.evaluate();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Sets the width of a column
|
||||
|
||||
12
tironcalc/Cargo.toml
Normal file
12
tironcalc/Cargo.toml
Normal file
@@ -0,0 +1,12 @@
|
||||
[package]
|
||||
name = "tiron"
|
||||
version = "0.1.3"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
crossterm = "0.27.0"
|
||||
ironcalc = { path = "../xlsx"}
|
||||
ratatui = "0.26.2"
|
||||
tui-input = "0.8.0"
|
||||
52
tironcalc/README.md
Normal file
52
tironcalc/README.md
Normal file
@@ -0,0 +1,52 @@
|
||||
# TironCalc
|
||||
|
||||
[![Discord chat][discord-badge]][discord-url]
|
||||
|
||||
[discord-badge]: https://img.shields.io/discord/1206947691058171904.svg?logo=discord&style=flat-square
|
||||
[discord-url]: https://discord.gg/zZYWfh3RHJ
|
||||
|
||||
TironCalc, or Tiron for friends, is a TUI (Terminal User Interface) for IronCalc. Based on [ratatui](https://github.com/ratatui-org/ratatui)
|
||||
|
||||

|
||||
|
||||
## Build
|
||||
|
||||
```
|
||||
cargo build --release
|
||||
```
|
||||
|
||||
You will find the binary at `./target/release/tiron`.
|
||||
|
||||
## Documentation
|
||||
|
||||
Start empty project:
|
||||
|
||||
```
|
||||
$ tiron
|
||||
```
|
||||
|
||||
Load an existing Excel file:
|
||||
|
||||
```
|
||||
$ tiron example.xlsx
|
||||
```
|
||||
|
||||
- `e` to edit a cell and enter the value or formula.
|
||||
- `q` to quit and save
|
||||
- `+` to add a sheet
|
||||
- `s` to go to the next sheet
|
||||
- `PgUp/PgDown` to navigate rows faster
|
||||
- `u` undo changes
|
||||
- `U` redo changes
|
||||
- `r` insert row
|
||||
- `c` insert column
|
||||
- `C` delete column
|
||||
- `R` delete row
|
||||
- `
|
||||
|
||||
|
||||
## Inspiration
|
||||
|
||||
James Gosling of Java fame created [sc](https://en.wikipedia.org/wiki/Sc_(spreadsheet_calculator)) the spreadsheet calculator.
|
||||
|
||||
Andrés Martinelli has been maintaining [sc-im](https://github.com/andmarti1424/sc-im), the spreadsheet calculator improvised.
|
||||
BIN
tironcalc/screenshot.png
Normal file
BIN
tironcalc/screenshot.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 10 KiB |
556
tironcalc/src/main.rs
Normal file
556
tironcalc/src/main.rs
Normal file
@@ -0,0 +1,556 @@
|
||||
use crossterm::{
|
||||
event::{self, DisableMouseCapture, EnableMouseCapture, Event as CEvent, KeyCode},
|
||||
execute,
|
||||
terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
|
||||
};
|
||||
use ironcalc::{
|
||||
base::{expressions::utils::number_to_column, Model, UserModel},
|
||||
export::save_to_xlsx,
|
||||
import::{load_from_icalc, load_from_xlsx},
|
||||
};
|
||||
use ratatui::{
|
||||
backend::CrosstermBackend,
|
||||
layout::{Constraint, Direction, Layout, Rect},
|
||||
style::{Color, Style, Stylize},
|
||||
text::{Line, Span},
|
||||
widgets::{Block, BorderType, Borders, Cell, Clear, Paragraph, Row, Table},
|
||||
Terminal,
|
||||
};
|
||||
use std::thread;
|
||||
use std::time::{Duration, Instant};
|
||||
use std::{io, sync::mpsc};
|
||||
use tui_input::{backend::crossterm::EventHandler, Input};
|
||||
|
||||
use std::env;
|
||||
|
||||
enum Event<I> {
|
||||
Input(I),
|
||||
Tick,
|
||||
}
|
||||
|
||||
#[derive(PartialEq)]
|
||||
enum CursorMode {
|
||||
Navigate,
|
||||
Input,
|
||||
Popup,
|
||||
}
|
||||
|
||||
struct SelectedRange {
|
||||
sheet: u32,
|
||||
row: i32,
|
||||
column: i32,
|
||||
min_row: i32,
|
||||
min_column: i32,
|
||||
max_row: i32,
|
||||
max_column: i32,
|
||||
}
|
||||
|
||||
struct SheetState {
|
||||
row: i32,
|
||||
column: i32,
|
||||
min_row: i32,
|
||||
min_column: i32,
|
||||
max_row: i32,
|
||||
max_column: i32,
|
||||
}
|
||||
|
||||
struct ModelState {
|
||||
selected_sheet: u32,
|
||||
sheet_states: Vec<SheetState>,
|
||||
}
|
||||
|
||||
impl ModelState {
|
||||
pub fn new(sheet_count: usize) -> ModelState {
|
||||
let mut sheet_states = vec![];
|
||||
for _ in 0..sheet_count {
|
||||
sheet_states.push(SheetState {
|
||||
row: 1,
|
||||
column: 1,
|
||||
min_row: 1,
|
||||
min_column: 1,
|
||||
max_row: 1,
|
||||
max_column: 1,
|
||||
});
|
||||
}
|
||||
ModelState {
|
||||
selected_sheet: 0,
|
||||
sheet_states,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_selected_range(&self) -> SelectedRange {
|
||||
let sheet = self.selected_sheet;
|
||||
let sheet_state = self.sheet_states.get(sheet as usize).unwrap();
|
||||
|
||||
SelectedRange {
|
||||
sheet,
|
||||
row: sheet_state.row,
|
||||
column: sheet_state.column,
|
||||
min_column: sheet_state.min_column,
|
||||
min_row: sheet_state.min_row,
|
||||
max_column: sheet_state.max_column,
|
||||
max_row: sheet_state.max_row,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_selected_sheet(&mut self, selected_sheet: u32) {
|
||||
self.selected_sheet = selected_sheet;
|
||||
}
|
||||
|
||||
pub fn get_selected_sheet(&self) -> u32 {
|
||||
self.selected_sheet
|
||||
}
|
||||
|
||||
pub fn move_up(&mut self) {
|
||||
let sheet = self.selected_sheet;
|
||||
let mut sheet_state = &mut self.sheet_states.get(sheet as usize).unwrap();
|
||||
sheet_state.column -= 1;
|
||||
|
||||
}
|
||||
|
||||
pub fn move_down(&mut self) {
|
||||
|
||||
}
|
||||
|
||||
pub fn move_left(&mut self) {
|
||||
|
||||
}
|
||||
|
||||
pub fn move_right(&mut self) {
|
||||
|
||||
}
|
||||
|
||||
pub fn move_shift_up(&mut self) {
|
||||
|
||||
}
|
||||
|
||||
pub fn move_shift_down(&mut self) {
|
||||
|
||||
}
|
||||
|
||||
pub fn move_shift_left(&mut self) {
|
||||
|
||||
}
|
||||
|
||||
pub fn move_shift_right(&mut self) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
enable_raw_mode()?;
|
||||
|
||||
let args: Vec<String> = env::args().collect();
|
||||
let mut file_name = "model.xlsx";
|
||||
let model = if args.len() > 1 {
|
||||
file_name = &args[1];
|
||||
if file_name.ends_with(".ic") {
|
||||
load_from_icalc(file_name).unwrap()
|
||||
} else {
|
||||
load_from_xlsx(file_name, "en", "UTC").unwrap()
|
||||
}
|
||||
} else {
|
||||
Model::new_empty(file_name, "en", "UTC").unwrap()
|
||||
};
|
||||
let mut user_model = UserModel::from_model(model);
|
||||
let mut state = ModelState::new(user_model.get_worksheets_properties().len());
|
||||
// let mut selected_sheet = 0;
|
||||
// let mut selected_row_index = 1;
|
||||
// let mut selected_column_index = 1;
|
||||
let mut minimum_row_index = 1;
|
||||
let mut minimum_column_index = 1;
|
||||
let sheet_list_width = 20;
|
||||
let column_width: u16 = 11;
|
||||
let mut cursor_mode = CursorMode::Navigate;
|
||||
let mut input_formula = Input::default();
|
||||
|
||||
let mut input_file_name: Input = file_name.into();
|
||||
|
||||
let mut popup_open = false;
|
||||
|
||||
let (tx, rx) = mpsc::channel();
|
||||
let tick_rate = Duration::from_millis(200);
|
||||
thread::spawn(move || {
|
||||
let mut last_tick = Instant::now();
|
||||
loop {
|
||||
let timeout = tick_rate
|
||||
.checked_sub(last_tick.elapsed())
|
||||
.unwrap_or_else(|| Duration::from_secs(0));
|
||||
|
||||
if event::poll(timeout).expect("poll works") {
|
||||
if let CEvent::Key(key) = event::read().expect("can read events") {
|
||||
tx.send(Event::Input(key)).expect("can send events");
|
||||
}
|
||||
}
|
||||
|
||||
if last_tick.elapsed() >= tick_rate && tx.send(Event::Tick).is_ok() {
|
||||
last_tick = Instant::now();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let mut stdout = io::stdout();
|
||||
execute!(stdout, EnterAlternateScreen, EnableMouseCapture)?;
|
||||
|
||||
let backend = CrosstermBackend::new(stdout);
|
||||
let mut terminal = Terminal::new(backend)?;
|
||||
terminal.clear()?;
|
||||
|
||||
let header_style = Style::default().fg(Color::Yellow).bg(Color::White);
|
||||
let selected_header_style = Style::default().bg(Color::Yellow).fg(Color::White);
|
||||
|
||||
let selected_cell_style = Style::default().fg(Color::Yellow).bg(Color::LightCyan);
|
||||
|
||||
let background_style = Style::default().bg(Color::Black);
|
||||
let selected_sheet_style = Style::default().bg(Color::White).fg(Color::LightMagenta);
|
||||
let non_selected_sheet_style = Style::default().fg(Color::White);
|
||||
let mut sheet_properties = user_model.get_worksheets_properties();
|
||||
loop {
|
||||
terminal.draw(|rect| {
|
||||
let size = rect.size();
|
||||
|
||||
let global_chunks = Layout::default()
|
||||
.direction(Direction::Horizontal)
|
||||
.constraints([Constraint::Length(sheet_list_width), Constraint::Min(3)].as_ref())
|
||||
.split(size);
|
||||
|
||||
// Sheet list to the left
|
||||
let sheets = Block::default()
|
||||
.borders(Borders::ALL)
|
||||
.style(Style::default().fg(Color::White))
|
||||
.title("Sheets")
|
||||
.border_type(BorderType::Plain)
|
||||
.style(background_style);
|
||||
let mut rows = vec![];
|
||||
(0..sheet_properties.len()).for_each(|sheet_index| {
|
||||
let sheet_name = &sheet_properties[sheet_index].name;
|
||||
let style = if sheet_index == state.get_selected_sheet() {
|
||||
selected_sheet_style
|
||||
} else {
|
||||
non_selected_sheet_style
|
||||
};
|
||||
rows.push(Row::new(vec![Cell::from(sheet_name.clone()).style(style)]));
|
||||
});
|
||||
let widths = &[Constraint::Length(100)];
|
||||
let sheet_list = Table::new(rows, widths).block(sheets).column_spacing(0);
|
||||
|
||||
rect.render_widget(sheet_list, global_chunks[0]);
|
||||
|
||||
// The spreadsheet is the formula bar at the top and the sheet data
|
||||
let spreadsheet_chunks = Layout::default()
|
||||
.direction(Direction::Vertical)
|
||||
.margin(0)
|
||||
.constraints([Constraint::Length(1), Constraint::Min(2)].as_ref())
|
||||
.split(global_chunks[1]);
|
||||
|
||||
let spreadsheet_width = size.width - sheet_list_width;
|
||||
let spreadsheet_heigh = size.height - 1;
|
||||
let row_count = spreadsheet_heigh - 1;
|
||||
|
||||
let first_row_width: u16 = 3;
|
||||
let column_count =
|
||||
f64::ceil(((spreadsheet_width - first_row_width) as f64) / (column_width as f64))
|
||||
as i32;
|
||||
let mut rows = vec![];
|
||||
// The first row in the column headers
|
||||
let mut row = Vec::new();
|
||||
// The first cell in that row is the top left square of the spreadsheet
|
||||
row.push(Cell::from(""));
|
||||
let mut maximum_column_index = minimum_column_index + column_count - 1;
|
||||
let mut maximum_row_index = minimum_row_index + row_count - 1;
|
||||
|
||||
// We want to make sure the selected cell is visible.
|
||||
if selected_column_index > maximum_column_index {
|
||||
maximum_column_index = selected_column_index;
|
||||
minimum_column_index = maximum_column_index - column_count + 1;
|
||||
} else if selected_column_index < minimum_column_index {
|
||||
minimum_column_index = selected_column_index;
|
||||
maximum_column_index = minimum_column_index + column_count - 1;
|
||||
}
|
||||
if selected_row_index >= maximum_row_index {
|
||||
maximum_row_index = selected_row_index;
|
||||
minimum_row_index = maximum_row_index - row_count + 1;
|
||||
} else if selected_row_index < minimum_row_index {
|
||||
minimum_row_index = selected_row_index;
|
||||
maximum_row_index = minimum_row_index + row_count - 1;
|
||||
}
|
||||
for column_index in minimum_column_index..=maximum_column_index {
|
||||
let column_str = number_to_column(column_index);
|
||||
let style = if column_index == selected_column_index {
|
||||
selected_header_style
|
||||
} else {
|
||||
header_style
|
||||
};
|
||||
row.push(Cell::from(format!(" {}", column_str.unwrap())).style(style));
|
||||
}
|
||||
rows.push(Row::new(row));
|
||||
for row_index in minimum_row_index..=maximum_row_index {
|
||||
let mut row = Vec::new();
|
||||
let style = if row_index == selected_row_index {
|
||||
selected_header_style
|
||||
} else {
|
||||
header_style
|
||||
};
|
||||
row.push(Cell::from(format!("{}", row_index)).style(style));
|
||||
for column_index in minimum_column_index..=maximum_column_index {
|
||||
let value = user_model
|
||||
.get_formatted_cell_value(
|
||||
selected_sheet as u32,
|
||||
row_index as i32,
|
||||
column_index,
|
||||
)
|
||||
.unwrap();
|
||||
// let cell_style = user_model
|
||||
// .get_cell_style(selected_sheet as u32, row_index as i32, column_index)
|
||||
// .unwrap();
|
||||
let style = if selected_row_index == row_index
|
||||
&& selected_column_index == column_index
|
||||
{
|
||||
selected_cell_style
|
||||
} else {
|
||||
// let bg_color = match cell_style.fill.fg_color {
|
||||
// Some(s) => Color::from_str(&s).unwrap(),
|
||||
// None => Color::White,
|
||||
// };
|
||||
// let fg_color = match cell_style.font.color {
|
||||
// Some(s) => Color::from_str(&s).unwrap(),
|
||||
// None => Color::Black,
|
||||
// };
|
||||
let bg_color = Color::White;
|
||||
let fg_color = Color::Black;
|
||||
Style::default().fg(fg_color).bg(bg_color)
|
||||
};
|
||||
row.push(Cell::from(value.to_string()).style(style));
|
||||
}
|
||||
rows.push(Row::new(row));
|
||||
}
|
||||
let mut widths = Vec::new();
|
||||
widths.push(Constraint::Length(first_row_width));
|
||||
for _ in 0..column_count {
|
||||
widths.push(Constraint::Length(column_width));
|
||||
}
|
||||
let spreadsheet = Table::new(rows, widths)
|
||||
.block(Block::default().style(Style::default().bg(Color::Black)))
|
||||
.column_spacing(0);
|
||||
|
||||
let text = if cursor_mode != CursorMode::Input {
|
||||
user_model
|
||||
.get_cell_content(
|
||||
selected_sheet as u32,
|
||||
selected_row_index as i32,
|
||||
selected_column_index,
|
||||
)
|
||||
.unwrap()
|
||||
} else {
|
||||
input_formula.value().to_string()
|
||||
};
|
||||
let cell_address_text = format!(
|
||||
"{}{}: ",
|
||||
number_to_column(selected_column_index).unwrap(),
|
||||
selected_row_index,
|
||||
);
|
||||
let formula_bar_text = format!("{}{}", cell_address_text, text,);
|
||||
let formula_bar = Paragraph::new(vec![Line::from(vec![Span::raw(formula_bar_text)])]);
|
||||
rect.render_widget(formula_bar.block(Block::default()), spreadsheet_chunks[0]);
|
||||
rect.render_widget(spreadsheet, spreadsheet_chunks[1]);
|
||||
if cursor_mode == CursorMode::Input {
|
||||
let area = spreadsheet_chunks[0];
|
||||
rect.set_cursor(
|
||||
area.x
|
||||
+ (input_formula.visual_cursor() as u16)
|
||||
+ cell_address_text.len() as u16,
|
||||
area.y,
|
||||
)
|
||||
}
|
||||
|
||||
if popup_open {
|
||||
let area = centered_rect(60, 20, size);
|
||||
rect.render_widget(Clear, area);
|
||||
let input_text = input_file_name.value();
|
||||
let text = vec![
|
||||
Line::from(vec![input_text.fg(Color::Yellow)]),
|
||||
"".into(),
|
||||
Line::from(vec![
|
||||
"ESC".green(),
|
||||
" to abort. ".into(),
|
||||
"END".green(),
|
||||
" to quit without saving. ".into(),
|
||||
"Enter".green(),
|
||||
" to save and quit".into(),
|
||||
]),
|
||||
];
|
||||
rect.render_widget(
|
||||
Paragraph::new(text).block(Block::bordered().title("Save as")),
|
||||
area,
|
||||
);
|
||||
rect.set_cursor(
|
||||
// Put cursor past the end of the input text
|
||||
area.x + (input_file_name.visual_cursor() as u16) + 1,
|
||||
// Move one line own, from the border to the input line
|
||||
area.y + 1,
|
||||
)
|
||||
}
|
||||
})?;
|
||||
|
||||
match cursor_mode {
|
||||
CursorMode::Popup => {
|
||||
match rx.recv()? {
|
||||
Event::Input(event) => match event.code {
|
||||
KeyCode::End => {
|
||||
terminal.clear()?;
|
||||
// restore terminal
|
||||
disable_raw_mode()?;
|
||||
execute!(
|
||||
terminal.backend_mut(),
|
||||
LeaveAlternateScreen,
|
||||
DisableMouseCapture
|
||||
)?;
|
||||
terminal.show_cursor()?;
|
||||
break;
|
||||
}
|
||||
KeyCode::Enter => {
|
||||
terminal.clear()?;
|
||||
// restore terminal
|
||||
disable_raw_mode()?;
|
||||
execute!(
|
||||
terminal.backend_mut(),
|
||||
LeaveAlternateScreen,
|
||||
DisableMouseCapture
|
||||
)?;
|
||||
terminal.show_cursor()?;
|
||||
let _ = save_to_xlsx(&user_model.model, input_file_name.value());
|
||||
break;
|
||||
}
|
||||
KeyCode::Esc => {
|
||||
popup_open = false;
|
||||
cursor_mode = CursorMode::Navigate;
|
||||
}
|
||||
_ => {
|
||||
input_file_name.handle_event(&CEvent::Key(event));
|
||||
}
|
||||
},
|
||||
Event::Tick => {}
|
||||
}
|
||||
}
|
||||
CursorMode::Navigate => {
|
||||
match rx.recv()? {
|
||||
Event::Input(event) => match event.code {
|
||||
KeyCode::Char('q') => {
|
||||
popup_open = true;
|
||||
cursor_mode = CursorMode::Popup;
|
||||
}
|
||||
KeyCode::Down => {
|
||||
selected_row_index += 1;
|
||||
}
|
||||
KeyCode::Up => {
|
||||
if selected_row_index > 1 {
|
||||
selected_row_index -= 1;
|
||||
}
|
||||
}
|
||||
KeyCode::Right => {
|
||||
selected_column_index += 1;
|
||||
}
|
||||
KeyCode::Left => {
|
||||
if selected_column_index > 1 {
|
||||
selected_column_index -= 1;
|
||||
}
|
||||
}
|
||||
KeyCode::PageDown => {
|
||||
selected_row_index += 10;
|
||||
}
|
||||
KeyCode::PageUp => {
|
||||
if selected_row_index > 10 {
|
||||
selected_row_index -= 10;
|
||||
} else {
|
||||
selected_row_index = 1;
|
||||
}
|
||||
}
|
||||
KeyCode::Char('s') => {
|
||||
selected_sheet += 1;
|
||||
if selected_sheet >= sheet_properties.len() {
|
||||
selected_sheet = 0;
|
||||
}
|
||||
}
|
||||
KeyCode::Char('a') => {
|
||||
selected_sheet = selected_sheet.saturating_sub(1);
|
||||
}
|
||||
KeyCode::Char('u') => user_model.undo().unwrap(),
|
||||
KeyCode::Char('U') => user_model.redo().unwrap(),
|
||||
KeyCode::Char('c') => user_model
|
||||
.insert_column(selected_sheet as u32, selected_column_index as i32)
|
||||
.unwrap(),
|
||||
KeyCode::Char('C') => user_model
|
||||
.delete_column(selected_sheet as u32, selected_column_index as i32)
|
||||
.unwrap(),
|
||||
KeyCode::Char('r') => user_model
|
||||
.insert_row(selected_sheet as u32, selected_row_index as i32)
|
||||
.unwrap(),
|
||||
KeyCode::Char('R') => user_model
|
||||
.delete_row(selected_sheet as u32, selected_row_index as i32)
|
||||
.unwrap(),
|
||||
KeyCode::Char('e') => {
|
||||
cursor_mode = CursorMode::Input;
|
||||
let input_str = user_model
|
||||
.get_cell_content(
|
||||
selected_sheet as u32,
|
||||
selected_row_index as i32,
|
||||
selected_column_index,
|
||||
)
|
||||
.unwrap();
|
||||
// .unwrap_or_default();
|
||||
input_formula = input_formula.with_value(input_str);
|
||||
}
|
||||
KeyCode::Char('+') => {
|
||||
user_model.new_sheet();
|
||||
sheet_properties = user_model.get_worksheets_properties();
|
||||
}
|
||||
_ => {
|
||||
// println!("{:?}", event);
|
||||
}
|
||||
},
|
||||
Event::Tick => {}
|
||||
}
|
||||
}
|
||||
CursorMode::Input => match rx.recv()? {
|
||||
Event::Input(event) => match event.code {
|
||||
KeyCode::Enter => {
|
||||
cursor_mode = CursorMode::Navigate;
|
||||
let value = input_formula.value().to_string();
|
||||
let sheet = selected_sheet as i32;
|
||||
let row = selected_row_index as i32;
|
||||
let column = selected_column_index;
|
||||
user_model
|
||||
.set_user_input(sheet as u32, row, column, &value)
|
||||
.unwrap();
|
||||
user_model.evaluate();
|
||||
}
|
||||
_ => {
|
||||
input_formula.handle_event(&CEvent::Key(event));
|
||||
}
|
||||
},
|
||||
Event::Tick => {}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// helper function to create a centered rect using up certain percentage of the available rect `r`
|
||||
fn centered_rect(percent_x: u16, percent_y: u16, r: Rect) -> Rect {
|
||||
let popup_layout = Layout::vertical([
|
||||
Constraint::Percentage((100 - percent_y) / 2),
|
||||
Constraint::Percentage(percent_y),
|
||||
Constraint::Percentage((100 - percent_y) / 2),
|
||||
])
|
||||
.split(r);
|
||||
|
||||
Layout::horizontal([
|
||||
Constraint::Percentage((100 - percent_x) / 2),
|
||||
Constraint::Percentage(percent_x),
|
||||
Constraint::Percentage((100 - percent_x) / 2),
|
||||
])
|
||||
.split(popup_layout[1])[1]
|
||||
}
|
||||
Reference in New Issue
Block a user