chore: merge release-v0.12.0 into main
This commit is contained in:
+14
-4
@@ -1,8 +1,18 @@
|
||||
### 2025-08-21
|
||||
### 2025-09-28
|
||||
|
||||
### Reverts
|
||||
+ GitHub workflow reverted, [d1b69858c622636afbc46db7d37cf91e58d61212]
|
||||
### Chores
|
||||
+ create_release.sh updated, [d4af754ad245540db60177f7b202b3c64519c961]
|
||||
+ dependencies updated, [03599b46657d38d0c9f25c2ccfd9510f2b98dd84], [aef0c9503e7045a256856aa887d8c8d7722b9936], [f0771eab5d07d141fe7a8997db650f0f65ffe0a7], [1596de8681ad6c0a7832eb922dd2dc36ab30eb41]
|
||||
+ GitHub workflow updated, [66dae5e61ea294ac8ce134a6c32b27c04166b6eb]
|
||||
|
||||
see [v0.11.0 release notes](https://github.com/mrjackwills/oxker/releases/tag/v0.11.0) for more information about v0.11 release
|
||||
### Docs
|
||||
+ fix numerous typos, [618a43b501914fdf2659e171172ad180364cf87a]
|
||||
|
||||
### Features
|
||||
+ *BREAKING CHANGE* - `scroll_down_many` & `scroll_up_many` removed, `scroll_down_one` `scroll_up_one` renamed `scroll_down`, `scroll_up`, see [example_config](https://github.com/mrjackwills/oxker/tree/main/example_config), [52a04ec1d0b9e4877e304f60a857ebc00f88b4fd]
|
||||
+ log search feature, closes #72. Use `#` button, remappable via `log_search_mode`, to enter log search mode. Case-sensitive by default, editable in `config.toml` with `log_search_case_sensitive` entry. Customise colours via `[colors.log_search]` entries, again see see [example_config](https://github.com/mrjackwills/oxker/tree/main/example_config), [96d9469623a7c90b79aa8d82abf587290343ad37], [a2316a9cac270790920a1ebd1be6532d51aba77c]
|
||||
+ `term` renamed `filter term`, tests updated, [487c3faf96f4c197c8b82644c02466ea40626a5e]
|
||||
|
||||
My 32-bit armhf armv6 hardware no longer seems to be able to run Docker. Future `oxker` releases won't be tested on real hardware but will continue to be built and published for armv6.
|
||||
|
||||
see <a href='https://github.com/mrjackwills/oxker/blob/main/CHANGELOG.md'>CHANGELOG.md</a> for more details
|
||||
|
||||
@@ -1,10 +1,16 @@
|
||||
name: Release CI
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
packages: write
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "v[0-9]+.[0-9]+.[0-9]+"
|
||||
|
||||
jobs:
|
||||
|
||||
#################################################
|
||||
## Cross platform binary build for release page #
|
||||
#################################################
|
||||
@@ -98,6 +104,7 @@ jobs:
|
||||
artifacts: |
|
||||
**/oxker_*.zip
|
||||
**/oxker_*.tar.gz
|
||||
|
||||
#########################################
|
||||
## Build images for Dockerhub & ghcr.io #
|
||||
#########################################
|
||||
@@ -169,4 +176,3 @@ jobs:
|
||||
- uses: actions/checkout@v5
|
||||
- name: Publish
|
||||
run: cargo publish
|
||||
|
||||
|
||||
+19
-1
@@ -1,3 +1,21 @@
|
||||
# <a href='https://github.com/mrjackwills/oxker/releases/tag/v0.12.0'>v0.12.0</a>
|
||||
### 2025-09-28
|
||||
|
||||
### Chores
|
||||
+ create_release.sh updated, [d4af754a](https://github.com/mrjackwills/oxker/commit/d4af754ad245540db60177f7b202b3c64519c961)
|
||||
+ dependencies updated, [03599b46](https://github.com/mrjackwills/oxker/commit/03599b46657d38d0c9f25c2ccfd9510f2b98dd84), [aef0c950](https://github.com/mrjackwills/oxker/commit/aef0c9503e7045a256856aa887d8c8d7722b9936), [f0771eab](https://github.com/mrjackwills/oxker/commit/f0771eab5d07d141fe7a8997db650f0f65ffe0a7), [1596de86](https://github.com/mrjackwills/oxker/commit/1596de8681ad6c0a7832eb922dd2dc36ab30eb41)
|
||||
+ GitHub workflow updated, [66dae5e6](https://github.com/mrjackwills/oxker/commit/66dae5e61ea294ac8ce134a6c32b27c04166b6eb)
|
||||
|
||||
### Docs
|
||||
+ fix numerous typos, [618a43b5](https://github.com/mrjackwills/oxker/commit/618a43b501914fdf2659e171172ad180364cf87a)
|
||||
|
||||
### Features
|
||||
+ *BREAKING CHANGE* - `scroll_down_many` & `scroll_up_many` removed, `scroll_down_one` `scroll_up_one` renamed `scroll_down`, `scroll_up`, see [example_config](https://github.com/mrjackwills/oxker/tree/main/example_config), [52a04ec1](https://github.com/mrjackwills/oxker/commit/52a04ec1d0b9e4877e304f60a857ebc00f88b4fd)
|
||||
+ log search feature, closes [#72](https://github.com/mrjackwills/oxker/issues/72). Use `#` button, remappable via `log_search_mode`, to enter log search mode. Case-sensitive by default, editable in `config.toml` with `log_search_case_sensitive` entry. Customise colours via `[colors.log_search]` entries, again see see [example_config](https://github.com/mrjackwills/oxker/tree/main/example_config), [96d94696](https://github.com/mrjackwills/oxker/commit/96d9469623a7c90b79aa8d82abf587290343ad37), [a2316a9c](https://github.com/mrjackwills/oxker/commit/a2316a9cac270790920a1ebd1be6532d51aba77c)
|
||||
+ `term` renamed `filter term`, tests updated, [487c3faf](https://github.com/mrjackwills/oxker/commit/487c3faf96f4c197c8b82644c02466ea40626a5e)
|
||||
|
||||
My 32-bit armhf armv6 hardware no longer seems to be able to run Docker. Future `oxker` releases won't be tested on real hardware but will continue to be built and published for armv6.
|
||||
|
||||
# <a href='https://github.com/mrjackwills/oxker/releases/tag/v0.11.1'>v0.11.1</a>
|
||||
### 2025-08-21
|
||||
|
||||
@@ -17,7 +35,7 @@ see [v0.11.0 release notes](https://github.com/mrjackwills/oxker/releases/tag/v0
|
||||
### Features
|
||||
+ Horizontally scroll across logs. By default use `←` & `→` keys to traverse horizontally across the lines when logs panel selected. Updated `config.toml` with `log_scroll_forward` and `log_scroll_back` [c190f020](https://github.com/mrjackwills/oxker/commit/c190f0206cc55b8e45b8373f9be954e828c18b3b), [8939ac03](https://github.com/mrjackwills/oxker/commit/8939ac0345326633e794cc10a981a1f3c5c07549)
|
||||
+ Force clear screen & redraw of UI. By default uses `f` key, `config.toml` updated with `force_redraw` [50edbc0c](https://github.com/mrjackwills/oxker/commit/50edbc0cc09db864835fe81a03cba8eadafe548b)
|
||||
+ Increase scroll speed using the `ctrl` key in conjuction with a scroll key, `config.toml` updated with `scroll_modifier`. The next release will remove `scroll_down_many` & `scroll_down_up` keys, [c5bbffdb](https://github.com/mrjackwills/oxker/commit/c5bbffdb5f9e800951e4060aa6aee8e00db589aa)
|
||||
+ Increase scroll speed using the `ctrl` key in conjunction with a scroll key, `config.toml` updated with `scroll_modifier`. The next release will remove `scroll_down_many` & `scroll_down_up` keys, [c5bbffdb](https://github.com/mrjackwills/oxker/commit/c5bbffdb5f9e800951e4060aa6aee8e00db589aa)
|
||||
|
||||
### Refactors
|
||||
+ remove macos cfg none-const functions, Zigbuild now uses Rust 1.87.0, [eb686e2c](https://github.com/mrjackwills/oxker/commit/eb686e2c952e04da74b3e12c0bfa015ec4615e1d)
|
||||
|
||||
Generated
+190
-153
@@ -4,9 +4,9 @@ version = 4
|
||||
|
||||
[[package]]
|
||||
name = "addr2line"
|
||||
version = "0.24.2"
|
||||
version = "0.25.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1"
|
||||
checksum = "1b5d307320b3181d6d7954e663bd7c774a838b8220fe0593c86d9fb09f498b4b"
|
||||
dependencies = [
|
||||
"gimli",
|
||||
]
|
||||
@@ -23,12 +23,6 @@ version = "0.2.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"
|
||||
|
||||
[[package]]
|
||||
name = "android-tzdata"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
|
||||
|
||||
[[package]]
|
||||
name = "android_system_properties"
|
||||
version = "0.1.5"
|
||||
@@ -90,9 +84,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.99"
|
||||
version = "1.0.100"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b0674a1ddeecb70197781e945de4b3b8ffb61fa939a5597bcf48503737663100"
|
||||
checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61"
|
||||
|
||||
[[package]]
|
||||
name = "atomic-waker"
|
||||
@@ -108,9 +102,9 @@ checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
|
||||
|
||||
[[package]]
|
||||
name = "backtrace"
|
||||
version = "0.3.75"
|
||||
version = "0.3.76"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002"
|
||||
checksum = "bb531853791a215d7c62a30daf0dde835f381ab5de4589cfe7c649d2cbe92bd6"
|
||||
dependencies = [
|
||||
"addr2line",
|
||||
"cfg-if",
|
||||
@@ -118,7 +112,7 @@ dependencies = [
|
||||
"miniz_oxide",
|
||||
"object",
|
||||
"rustc-demangle",
|
||||
"windows-targets 0.52.6",
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -129,9 +123,9 @@ checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.9.2"
|
||||
version = "2.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a65b545ab31d687cff52899d4890855fec459eb6afe0da6417b8a18da87aa29"
|
||||
checksum = "2261d10cca569e4643e526d8dc2e62e433cc8aba21ab764233731f8d369bf394"
|
||||
|
||||
[[package]]
|
||||
name = "bollard"
|
||||
@@ -213,10 +207,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.2.33"
|
||||
version = "1.2.39"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3ee0f8803222ba5a7e2777dd72ca451868909b1ac410621b676adf07280e9b5f"
|
||||
checksum = "e1354349954c6fc9cb0deab020f27f783cf0b604e8bb754dc4658ecf0d29c35f"
|
||||
dependencies = [
|
||||
"find-msvc-tools",
|
||||
"shlex",
|
||||
]
|
||||
|
||||
@@ -228,11 +223,10 @@ checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9"
|
||||
|
||||
[[package]]
|
||||
name = "chrono"
|
||||
version = "0.4.41"
|
||||
version = "0.4.42"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d"
|
||||
checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2"
|
||||
dependencies = [
|
||||
"android-tzdata",
|
||||
"iana-time-zone",
|
||||
"num-traits",
|
||||
"serde",
|
||||
@@ -241,9 +235,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.5.45"
|
||||
version = "4.5.48"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1fc0e74a703892159f5ae7d3aac52c8e6c392f5ae5f359c70b5881d60aaac318"
|
||||
checksum = "e2134bb3ea021b78629caa971416385309e0131b351b25e01dc16fb54e1b5fae"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
"clap_derive",
|
||||
@@ -251,9 +245,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.5.44"
|
||||
version = "4.5.48"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b3e7f4214277f3c7aa526a59dd3fbe306a370daee1f8b7b8c987069cd8e888a8"
|
||||
checksum = "c2ba64afa3c0a6df7fa517765e31314e983f51dda798ffba27b988194fb65dc9"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
@@ -265,9 +259,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "4.5.45"
|
||||
version = "4.5.47"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "14cb31bb0a7d536caef2639baa7fad459e15c3144efefa6dbd1c84562c4739f6"
|
||||
checksum = "bbfd7eae0b0f1a6e63d4b13c9c478de77c2eb546fba158ad50b4203dc24b9f9c"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
@@ -356,7 +350,7 @@ dependencies = [
|
||||
"document-features",
|
||||
"mio",
|
||||
"parking_lot",
|
||||
"rustix 1.0.8",
|
||||
"rustix 1.1.2",
|
||||
"signal-hook",
|
||||
"signal-hook-mio",
|
||||
"winapi",
|
||||
@@ -408,12 +402,12 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "deranged"
|
||||
version = "0.4.0"
|
||||
version = "0.5.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c9e6a11ca8224451684bc0d7d5a7adbf8f2fd6887261a1cfc3c0432f9d4068e"
|
||||
checksum = "a41953f86f8a05768a6cda24def994fd2f424b04ec5c719cf89989779f199071"
|
||||
dependencies = [
|
||||
"powerfmt",
|
||||
"serde",
|
||||
"serde_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -455,7 +449,7 @@ dependencies = [
|
||||
"libc",
|
||||
"option-ext",
|
||||
"redox_users",
|
||||
"windows-sys 0.60.2",
|
||||
"windows-sys 0.61.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -504,14 +498,20 @@ checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
|
||||
|
||||
[[package]]
|
||||
name = "errno"
|
||||
version = "0.3.13"
|
||||
version = "0.3.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad"
|
||||
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.60.2",
|
||||
"windows-sys 0.61.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "find-msvc-tools"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1ced73b1dacfc750a6db6c0a0c3a3853c8b41997e2e2c563dc90804ae6867959"
|
||||
|
||||
[[package]]
|
||||
name = "fnv"
|
||||
version = "1.0.7"
|
||||
@@ -605,14 +605,14 @@ dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"r-efi",
|
||||
"wasi 0.14.2+wasi-0.2.4",
|
||||
"wasi 0.14.7+wasi-0.2.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gimli"
|
||||
version = "0.31.1"
|
||||
version = "0.32.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
|
||||
checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7"
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
@@ -631,6 +631,12 @@ dependencies = [
|
||||
"foldhash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d"
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.5.0"
|
||||
@@ -728,9 +734,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "hyper-util"
|
||||
version = "0.1.16"
|
||||
version = "0.1.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8d9b05277c7e8da2c93a568989bb6207bef0112e8d17df7a6eda4a3cf143bc5e"
|
||||
checksum = "3c6995591a8f1380fcb4ba966a252a4b29188d51d2b89e3a252f5305be65aea8"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"futures-channel",
|
||||
@@ -764,9 +770,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "iana-time-zone"
|
||||
version = "0.1.63"
|
||||
version = "0.1.64"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8"
|
||||
checksum = "33e57f83510bb73707521ebaffa789ec8caf86f9657cad665b092b581d40e9fb"
|
||||
dependencies = [
|
||||
"android_system_properties",
|
||||
"core-foundation-sys",
|
||||
@@ -912,13 +918,14 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "2.10.0"
|
||||
version = "2.11.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661"
|
||||
checksum = "4b0f83760fb341a774ed326568e19f5a863af4a952def8c39f9ab92fd95b88e5"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown 0.15.5",
|
||||
"hashbrown 0.16.0",
|
||||
"serde",
|
||||
"serde_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -929,9 +936,9 @@ checksum = "f4c7245a08504955605670dbf141fceab975f15ca21570696aebe9d2e71576bd"
|
||||
|
||||
[[package]]
|
||||
name = "insta"
|
||||
version = "1.43.1"
|
||||
version = "1.43.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "154934ea70c58054b556dd430b99a98c2a7ff5309ac9891597e339b5c28f4371"
|
||||
checksum = "46fdb647ebde000f43b5b53f773c30cf9b0cb4300453208713fa38b2c70935a0"
|
||||
dependencies = [
|
||||
"console",
|
||||
"once_cell",
|
||||
@@ -953,9 +960,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "io-uring"
|
||||
version = "0.7.9"
|
||||
version = "0.7.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d93587f37623a1a17d94ef2bc9ada592f5465fe7732084ab7beefabe5c77c0c4"
|
||||
checksum = "046fa2d4d00aea763528b4950358d0ead425372445dc8ff86312b3c69ff7727b"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cfg-if",
|
||||
@@ -1027,9 +1034,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.77"
|
||||
version = "0.3.81"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f"
|
||||
checksum = "ec48937a97411dcb524a265206ccd4c90bb711fca92b2792c407f268825b9305"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"wasm-bindgen",
|
||||
@@ -1043,15 +1050,15 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.175"
|
||||
version = "0.2.176"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543"
|
||||
checksum = "58f929b4d672ea937a23a1ab494143d968337a5f47e56d0815df1e0890ddf174"
|
||||
|
||||
[[package]]
|
||||
name = "libredox"
|
||||
version = "0.1.9"
|
||||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "391290121bad3d37fbddad76d8f5d1c1c314cfc646d143d7e07a3086ddff0ce3"
|
||||
checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"libc",
|
||||
@@ -1065,9 +1072,9 @@ checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab"
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.9.4"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12"
|
||||
checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039"
|
||||
|
||||
[[package]]
|
||||
name = "litemap"
|
||||
@@ -1093,9 +1100,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.27"
|
||||
version = "0.4.28"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94"
|
||||
checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432"
|
||||
|
||||
[[package]]
|
||||
name = "lru"
|
||||
@@ -1108,9 +1115,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.7.5"
|
||||
version = "2.7.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0"
|
||||
checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273"
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
@@ -1135,12 +1142,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nu-ansi-term"
|
||||
version = "0.46.0"
|
||||
version = "0.50.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84"
|
||||
checksum = "d4a28e057d01f97e61255210fcff094d74ed0466038633e95017f5beb68e4399"
|
||||
dependencies = [
|
||||
"overload",
|
||||
"winapi",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1160,9 +1166,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.36.7"
|
||||
version = "0.37.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87"
|
||||
checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
@@ -1185,15 +1191,9 @@ version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
|
||||
|
||||
[[package]]
|
||||
name = "overload"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
|
||||
|
||||
[[package]]
|
||||
name = "oxker"
|
||||
version = "0.11.1"
|
||||
version = "0.12.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bollard",
|
||||
@@ -1281,9 +1281,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "potential_utf"
|
||||
version = "0.1.2"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585"
|
||||
checksum = "84df19adbe5b5a0782edcab45899906947ab039ccf4573713735ee7de1e6b08a"
|
||||
dependencies = [
|
||||
"zerovec",
|
||||
]
|
||||
@@ -1438,15 +1438,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "1.0.8"
|
||||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8"
|
||||
checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys 0.9.4",
|
||||
"windows-sys 0.60.2",
|
||||
"linux-raw-sys 0.11.0",
|
||||
"windows-sys 0.61.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1493,18 +1493,28 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.219"
|
||||
version = "1.0.228"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6"
|
||||
checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
|
||||
dependencies = [
|
||||
"serde_core",
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_core"
|
||||
version = "1.0.228"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.219"
|
||||
version = "1.0.228"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00"
|
||||
checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -1513,14 +1523,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.143"
|
||||
version = "1.0.145"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d401abef1d108fbd9cbaebc3e46611f4b1021f714a0597a71f41ee463f5f4a5a"
|
||||
checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"memchr",
|
||||
"ryu",
|
||||
"serde",
|
||||
"serde_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1547,11 +1558,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_spanned"
|
||||
version = "1.0.0"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "40734c41988f7306bb04f0ecf60ec0f3f1caa34290e4e8ea471dcd3346483b83"
|
||||
checksum = "5417783452c2be558477e104686f7de5dae53dba813c28435e0e70f82d9b04ee"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1568,15 +1579,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_with"
|
||||
version = "3.14.0"
|
||||
version = "3.14.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f2c45cd61fefa9db6f254525d46e392b852e0e61d9a1fd36e5bd183450a556d5"
|
||||
checksum = "c522100790450cf78eeac1507263d0a350d4d5b30df0c8e1fe051a10c22b376e"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"chrono",
|
||||
"hex",
|
||||
"indexmap 1.9.3",
|
||||
"indexmap 2.10.0",
|
||||
"indexmap 2.11.4",
|
||||
"schemars 0.9.0",
|
||||
"schemars 1.0.4",
|
||||
"serde",
|
||||
@@ -1751,9 +1762,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.3.41"
|
||||
version = "0.3.44"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40"
|
||||
checksum = "91e7d9e3bb61134e77bde20dd4825b97c010155709965fedf0f49bb138e52a9d"
|
||||
dependencies = [
|
||||
"deranged",
|
||||
"itoa",
|
||||
@@ -1766,15 +1777,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "time-core"
|
||||
version = "0.1.4"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c"
|
||||
checksum = "40868e7c1d2f0b8d73e4a8c7f0ff63af4f6d19be117e90bd73eb1d62cf831c6b"
|
||||
|
||||
[[package]]
|
||||
name = "time-macros"
|
||||
version = "0.2.22"
|
||||
version = "0.2.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3526739392ec93fd8b359c8e98514cb3e8e021beb4e5f597b00a0221f8ed8a49"
|
||||
checksum = "30cfb0125f12d9c277f35663a0a33f8c30190f4e4574868a330595412d34ebf3"
|
||||
dependencies = [
|
||||
"num-conv",
|
||||
"time-core",
|
||||
@@ -1836,11 +1847,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.9.5"
|
||||
version = "0.9.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "75129e1dc5000bfbaa9fee9d1b21f974f9fbad9daec557a521ee6e080825f6e8"
|
||||
checksum = "00e5e5d9bf2475ac9d4f0d9edab68cc573dc2fd644b0dba36b0c30a92dd9eaa0"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_core",
|
||||
"serde_spanned",
|
||||
"toml_datetime",
|
||||
"toml_parser",
|
||||
@@ -1849,18 +1860,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "toml_datetime"
|
||||
version = "0.7.0"
|
||||
version = "0.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bade1c3e902f58d73d3f294cd7f20391c1cb2fbcb643b73566bc773971df91e3"
|
||||
checksum = "32f1085dec27c2b6632b04c80b3bb1b4300d6495d1e129693bdda7d91e72eec1"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml_parser"
|
||||
version = "1.0.2"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b551886f449aa90d4fe2bdaa9f4a2577ad2dde302c61ecf262d80b116db95c10"
|
||||
checksum = "4cf893c33be71572e0e9aa6dd15e6677937abd686b066eac3f8cd3531688a627"
|
||||
dependencies = [
|
||||
"winnow",
|
||||
]
|
||||
@@ -1916,9 +1927,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tracing-subscriber"
|
||||
version = "0.3.19"
|
||||
version = "0.3.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008"
|
||||
checksum = "2054a14f5307d601f88daf0553e1cbf472acc4f2c51afab632431cdcd72124d5"
|
||||
dependencies = [
|
||||
"nu-ansi-term",
|
||||
"sharded-slab",
|
||||
@@ -1942,9 +1953,9 @@ checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.18"
|
||||
version = "1.0.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
|
||||
checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-segmentation"
|
||||
@@ -1977,13 +1988,14 @@ checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd"
|
||||
|
||||
[[package]]
|
||||
name = "url"
|
||||
version = "2.5.6"
|
||||
version = "2.5.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "137a3c834eaf7139b73688502f3f1141a0337c5d8e4d9b536f9b8c796e26a7c4"
|
||||
checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b"
|
||||
dependencies = [
|
||||
"form_urlencoded",
|
||||
"idna",
|
||||
"percent-encoding",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2000,9 +2012,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
|
||||
|
||||
[[package]]
|
||||
name = "uuid"
|
||||
version = "1.18.0"
|
||||
version = "1.18.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f33196643e165781c20a5ead5582283a7dacbb87855d867fbc2df3f81eddc1be"
|
||||
checksum = "2f87b8aa10b915a06587d0dec516c282ff295b475d94abf425d62b57710070a2"
|
||||
dependencies = [
|
||||
"getrandom 0.3.3",
|
||||
"js-sys",
|
||||
@@ -2033,30 +2045,40 @@ checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.14.2+wasi-0.2.4"
|
||||
version = "0.14.7+wasi-0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3"
|
||||
checksum = "883478de20367e224c0090af9cf5f9fa85bed63a95c1abf3afc5c083ebc06e8c"
|
||||
dependencies = [
|
||||
"wit-bindgen-rt",
|
||||
"wasip2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasip2"
|
||||
version = "1.0.1+wasi-0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7"
|
||||
dependencies = [
|
||||
"wit-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.100"
|
||||
version = "0.2.104"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5"
|
||||
checksum = "c1da10c01ae9f1ae40cbfac0bac3b1e724b320abfcf52229f80b547c0d250e2d"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"once_cell",
|
||||
"rustversion",
|
||||
"wasm-bindgen-macro",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-backend"
|
||||
version = "0.2.100"
|
||||
version = "0.2.104"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6"
|
||||
checksum = "671c9a5a66f49d8a47345ab942e2cb93c7d1d0339065d4f8139c486121b43b19"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"log",
|
||||
@@ -2068,9 +2090,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.100"
|
||||
version = "0.2.104"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407"
|
||||
checksum = "7ca60477e4c59f5f2986c50191cd972e3a50d8a95603bc9434501cf156a9a119"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"wasm-bindgen-macro-support",
|
||||
@@ -2078,9 +2100,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro-support"
|
||||
version = "0.2.100"
|
||||
version = "0.2.104"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de"
|
||||
checksum = "9f07d2f20d4da7b26400c9f4a0511e6e0345b040694e8a75bd41d578fa4421d7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -2091,9 +2113,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-shared"
|
||||
version = "0.2.100"
|
||||
version = "0.2.104"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d"
|
||||
checksum = "bad67dc8b2a1a6e5448428adec4c3e84c43e561d8c9ee8a9e5aabeb193ec41d1"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
@@ -2122,9 +2144,9 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "windows-core"
|
||||
version = "0.61.2"
|
||||
version = "0.62.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3"
|
||||
checksum = "6844ee5416b285084d3d3fffd743b925a6c9385455f64f6d4fa3031c4c2749a9"
|
||||
dependencies = [
|
||||
"windows-implement",
|
||||
"windows-interface",
|
||||
@@ -2135,9 +2157,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windows-implement"
|
||||
version = "0.60.0"
|
||||
version = "0.60.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836"
|
||||
checksum = "edb307e42a74fb6de9bf3a02d9712678b22399c87e6fa869d6dfcd8c1b7754e0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -2146,9 +2168,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windows-interface"
|
||||
version = "0.59.1"
|
||||
version = "0.59.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8"
|
||||
checksum = "c0abd1ddbc6964ac14db11c7213d6532ef34bd9aa042c2e5935f59d7908b46a5"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -2157,28 +2179,37 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windows-link"
|
||||
version = "0.1.3"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a"
|
||||
checksum = "45e46c0661abb7180e7b9c281db115305d49ca1709ab8242adf09666d2173c65"
|
||||
|
||||
[[package]]
|
||||
name = "windows-result"
|
||||
version = "0.3.4"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6"
|
||||
checksum = "7084dcc306f89883455a206237404d3eaf961e5bd7e0f312f7c91f57eb44167f"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-strings"
|
||||
version = "0.4.2"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57"
|
||||
checksum = "7218c655a553b0bed4426cf54b20d7ba363ef543b52d515b3e48d7fd55318dda"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
|
||||
dependencies = [
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.59.0"
|
||||
@@ -2194,7 +2225,16 @@ version = "0.60.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb"
|
||||
dependencies = [
|
||||
"windows-targets 0.53.3",
|
||||
"windows-targets 0.53.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.61.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6f109e41dd4a3c848907eb83d5a42ea98b3769495597450cf6d153507b166f0f"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2215,9 +2255,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.53.3"
|
||||
version = "0.53.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91"
|
||||
checksum = "2d42b7b7f66d2a06854650af09cfdf8713e427a439c97ad65a6375318033ac4b"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
"windows_aarch64_gnullvm 0.53.0",
|
||||
@@ -2328,18 +2368,15 @@ checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486"
|
||||
|
||||
[[package]]
|
||||
name = "winnow"
|
||||
version = "0.7.12"
|
||||
version = "0.7.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f3edebf492c8125044983378ecb5766203ad3b4c2f7a922bd7dd207f6d443e95"
|
||||
checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf"
|
||||
|
||||
[[package]]
|
||||
name = "wit-bindgen-rt"
|
||||
version = "0.39.0"
|
||||
name = "wit-bindgen"
|
||||
version = "0.46.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
]
|
||||
checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59"
|
||||
|
||||
[[package]]
|
||||
name = "writeable"
|
||||
@@ -2373,18 +2410,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy"
|
||||
version = "0.8.26"
|
||||
version = "0.8.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f"
|
||||
checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c"
|
||||
dependencies = [
|
||||
"zerocopy-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy-derive"
|
||||
version = "0.8.26"
|
||||
version = "0.8.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181"
|
||||
checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "oxker"
|
||||
version = "0.11.1"
|
||||
version = "0.12.0"
|
||||
edition = "2024"
|
||||
authors = ["Jack Wills <email@mrjackwills.com>"]
|
||||
description = "A simple tui to view & control docker containers"
|
||||
|
||||
@@ -110,13 +110,14 @@ In application controls, these, amongst many other settings, can be customized w
|
||||
| button| result|
|
||||
|--|--|
|
||||
| ```( tab )``` or ```( shift+tab )``` | Change panel, clicking on a panel also changes the selected panel.|
|
||||
| ```( ↑ ↓ )``` or ```( j k )``` or ```( PgUp PgDown )``` or ```( Home End )```| Scroll line in selected panel - mouse wheel will also scroll.|
|
||||
| ```( ↑ ↓ )``` or ```( j k )``` or ```( Home End )```| Scroll line in selected panel - mouse wheel will also scroll.|
|
||||
| ```( ← → )``` | When logs panel selected, scroll horizontally across the text of the logs.|
|
||||
| ```( ctrl )``` | Increase scroll speed, used in conjuction with scroll keys.|
|
||||
| ```( ctrl )``` | Increase scroll speed, used in conjunction with scroll keys.|
|
||||
| ```( enter )```| Run selected docker command.|
|
||||
| ```( 1-9 )``` | Sort containers by heading, clicking on headings also sorts the selected column. |
|
||||
| ```( 0 )``` | Stop sorting.|
|
||||
| ```( F1 )``` or ```( / )``` | Enter filter mode. |
|
||||
| ```( # )``` | Enter log search mode. |
|
||||
| ```( - ) ``` or ```(=)``` | Reduce or increase the height of the logs panel.|
|
||||
| ```( \ )``` | Toggle the visibility of the logs panel.|
|
||||
| ```( e )``` | Exec into the selected container - not available on Windows.|
|
||||
|
||||
@@ -1,5 +1,2 @@
|
||||
[default.extend-words]
|
||||
ratatui = "ratatui"
|
||||
|
||||
[default]
|
||||
extend-ignore-words-re = ["[(?:[0-9a-fA-F]{8}|[0-9a-fA-F]{40})]"]
|
||||
|
||||
+36
-15
@@ -1,7 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
# rust create_release v0.6.2
|
||||
# 2025-02-22
|
||||
# rust create_release v0.6.3
|
||||
# 2025-09-20
|
||||
|
||||
STAR_LINE='****************************************'
|
||||
CWD=$(pwd)
|
||||
@@ -240,20 +240,29 @@ zig_build_aarch64_apple() {
|
||||
fi
|
||||
}
|
||||
|
||||
cargo_clean() {
|
||||
echo -e "${YELLOW}cargo clean${RESET}"
|
||||
cargo clean
|
||||
}
|
||||
|
||||
# Build all releases that GitHub workflow would
|
||||
# This will download GB's of docker images
|
||||
# $1 is 0 or 1, if 1 won't run ask_continue
|
||||
cross_build_all() {
|
||||
cargo clean
|
||||
if ask_yn "cargo clean"; then
|
||||
cargo_clean
|
||||
fi
|
||||
skip_confirm=$1
|
||||
cross_build_armv6_linux
|
||||
ask_continue
|
||||
[ "$skip_confirm" -ne 1 ] && ask_continue
|
||||
cross_build_aarch64_linux
|
||||
ask_continue
|
||||
[ "$skip_confirm" -ne 1 ] && ask_continue
|
||||
cross_build_x86_linux
|
||||
ask_continue
|
||||
[ "$skip_confirm" -ne 1 ] && ask_continue
|
||||
cross_build_x86_windows
|
||||
ask_continue
|
||||
[ "$skip_confirm" -ne 1 ] && ask_continue
|
||||
zig_build_aarch64_apple
|
||||
ask_continue
|
||||
[ "$skip_confirm" -ne 1 ] && ask_continue
|
||||
}
|
||||
|
||||
# $1 text to colourise
|
||||
@@ -304,13 +313,15 @@ build_container_armv6() {
|
||||
}
|
||||
|
||||
# Build all the containers, this get executed in the github action
|
||||
# $1 is 0 or 1, if 1 won't run ask_continue
|
||||
build_container_all() {
|
||||
skip_confirm=$1
|
||||
build_container_amd64
|
||||
ask_continue
|
||||
[ "$skip_confirm" -ne 1 ] && ask_continue
|
||||
build_container_arm64
|
||||
ask_continue
|
||||
[ "$skip_confirm" -ne 1 ] && ask_continue
|
||||
build_container_armv6
|
||||
ask_continue
|
||||
[ "$skip_confirm" -ne 1 ] && ask_continue
|
||||
}
|
||||
|
||||
# Full flow to create a new release
|
||||
@@ -322,8 +333,8 @@ release_flow() {
|
||||
get_git_remote_url
|
||||
|
||||
cargo_test
|
||||
cross_build_all
|
||||
build_container_all
|
||||
cross_build_all 0
|
||||
build_container_all 0
|
||||
cargo_publish_dry_run
|
||||
|
||||
cd "${CWD}" || error_close "Can't find ${CWD}"
|
||||
@@ -394,6 +405,7 @@ build_choice() {
|
||||
4 "aarch64 apple" off
|
||||
5 "x86 windows" off
|
||||
6 "all" off
|
||||
7 "all automatic" off
|
||||
)
|
||||
choices=$("${cmd[@]}" "${options[@]}" 2>&1 >/dev/tty)
|
||||
exitStatus=$?
|
||||
@@ -426,7 +438,11 @@ build_choice() {
|
||||
exit
|
||||
;;
|
||||
6)
|
||||
cross_build_all
|
||||
cross_build_all 0
|
||||
exit
|
||||
;;
|
||||
7)
|
||||
cross_build_all 1
|
||||
exit
|
||||
;;
|
||||
esac
|
||||
@@ -440,6 +456,7 @@ build_container_choice() {
|
||||
2 "aarch64" off
|
||||
3 "armv6" off
|
||||
4 "all" off
|
||||
5 "all automatic" off
|
||||
)
|
||||
choices=$("${cmd[@]}" "${options[@]}" 2>&1 >/dev/tty)
|
||||
exitStatus=$?
|
||||
@@ -464,7 +481,11 @@ build_container_choice() {
|
||||
exit
|
||||
;;
|
||||
4)
|
||||
build_container_all
|
||||
build_container_all 0
|
||||
exit
|
||||
;;
|
||||
5)
|
||||
build_container_all 1
|
||||
exit
|
||||
;;
|
||||
esac
|
||||
|
||||
@@ -31,6 +31,8 @@
|
||||
"use_cli": false,
|
||||
// Show the logs section - this can be changed during operation with the log_section_toggle key
|
||||
"show_logs": true,
|
||||
// Use case-sensitive matching for logs
|
||||
"log_search_case_sensitive": true,
|
||||
//////////////////
|
||||
// Custom Keymap //
|
||||
//////////////////
|
||||
@@ -67,6 +69,10 @@
|
||||
"/",
|
||||
"F1"
|
||||
],
|
||||
// Enter log search mode
|
||||
"log_search_mode": [
|
||||
"#"
|
||||
],
|
||||
// Quit at anytime
|
||||
"quit": [
|
||||
"q"
|
||||
@@ -75,14 +81,8 @@
|
||||
"save_logs": [
|
||||
"s"
|
||||
],
|
||||
// TODO "scroll_down_many" will be removed in the next release
|
||||
// Scroll down a list by many
|
||||
"scroll_down_many": [
|
||||
"pagedown"
|
||||
],
|
||||
// TODO rename in next release
|
||||
// Scroll down a list by one item
|
||||
"scroll_down_one": [
|
||||
"scroll_down": [
|
||||
"down",
|
||||
"j"
|
||||
],
|
||||
@@ -90,20 +90,16 @@
|
||||
"scroll_end": [
|
||||
"end"
|
||||
],
|
||||
// Modifier to scroll by 10 lines isntead of one, used in conjunction with scroll_up_x/scroll_down_x
|
||||
"scroll_many": ["control"],
|
||||
// Modifier to scroll by 10 lines instead of one, used in conjunction with scroll_up/scroll_down
|
||||
"scroll_many": [
|
||||
"control"
|
||||
],
|
||||
// Scroll up to the start of a list
|
||||
"scroll_start": [
|
||||
"home"
|
||||
],
|
||||
// TODO "scroll_up_many" will be removed in the next release
|
||||
// Scroll up a list by many
|
||||
"scroll_up_many": [
|
||||
"pageup"
|
||||
],
|
||||
// TODO rename in next release
|
||||
// Scroll up a list by one item
|
||||
"scroll_up_one": [
|
||||
"scroll_up": [
|
||||
"up",
|
||||
"k"
|
||||
],
|
||||
@@ -297,6 +293,17 @@
|
||||
// Highlighted text color
|
||||
"highlight": "magenta"
|
||||
},
|
||||
// The log search panel
|
||||
"log_search": {
|
||||
// Background color of panel
|
||||
"background": "reset",
|
||||
// color of text
|
||||
"text": "gray",
|
||||
// text color of the buttons text
|
||||
"button_text": "black",
|
||||
// Highlighted text color
|
||||
"highlight": "magenta"
|
||||
},
|
||||
// The logs panel, will only be applied if color_logs is false
|
||||
"logs": {
|
||||
// Background color of panel
|
||||
|
||||
@@ -43,6 +43,9 @@ use_cli = false
|
||||
# Show the logs section - this can be changed during operation with the log_section_toggle key
|
||||
show_logs = true
|
||||
|
||||
# Use case-sensitive matching for logs
|
||||
log_search_case_sensitive = true
|
||||
|
||||
#################
|
||||
# Custom Keymap #
|
||||
#################
|
||||
@@ -72,29 +75,25 @@ delete_confirm = ["y"]
|
||||
exec = ["e"]
|
||||
# Enter filter mode
|
||||
filter_mode = ["/", "F1"]
|
||||
|
||||
# Enter log search mode
|
||||
log_search_mode = ["#"]
|
||||
|
||||
# Quit at anytime
|
||||
quit = ["q"]
|
||||
# Save logs of selected container to file on disk
|
||||
save_logs = ["s"]
|
||||
# TODO "scroll_down_many" will be removed in the next release
|
||||
# scroll down a list by many
|
||||
scroll_down_many = ["pagedown"]
|
||||
# TODO rename in next release
|
||||
# scroll down a list by one item
|
||||
scroll_down_one = ["down", "j"]
|
||||
scroll_down = ["down", "j"]
|
||||
|
||||
# scroll down to the end of a list
|
||||
scroll_end = ["end"]
|
||||
# Modifier to scroll by 10 lines isntead of one, used in conjunction with scroll_up_x/scroll_down_x
|
||||
# Modifier to scroll by 10 lines instead of one, used in conjunction with scroll_up/scroll_down
|
||||
scroll_many = ["control"]
|
||||
# scroll up to the start of a list
|
||||
scroll_start = ["home"]
|
||||
# TODO "scroll_up_many" will be removed in the next release
|
||||
# scroll up a list by many
|
||||
scroll_up_many = ["pageup"]
|
||||
# TODO rename in next release
|
||||
# scroll up a list by one item
|
||||
scroll_up_one = ["up", "k"]
|
||||
scroll_up = ["up", "k"]
|
||||
# Horizontal scroll of the logs
|
||||
log_scroll_forward = ["right"]
|
||||
log_scroll_back = ["left"]
|
||||
@@ -123,6 +122,9 @@ log_section_height_decrease = ["-"]
|
||||
log_section_height_increase = ["+"]
|
||||
# Toggle visibility of the log section
|
||||
log_section_toggle = ["\\"]
|
||||
|
||||
|
||||
|
||||
# Force a complete clear & redraw of the screen
|
||||
force_redraw = ["f"]
|
||||
|
||||
@@ -200,6 +202,17 @@ selected_filter_text = "black"
|
||||
highlight = "magenta"
|
||||
|
||||
|
||||
# The log search panel
|
||||
[colors.log_search]
|
||||
# Background color of panel
|
||||
background = "reset"
|
||||
# color of text
|
||||
text = "gray"
|
||||
# text color of the buttons text
|
||||
button_text = "black"
|
||||
# Highlighted text color
|
||||
highlight = "magenta"
|
||||
|
||||
# The color the of Docker commands available for each container
|
||||
[colors.commands]
|
||||
# Background color of panel
|
||||
|
||||
+328
-21
@@ -22,6 +22,12 @@ const ONE_KB: f64 = 1000.0;
|
||||
const ONE_MB: f64 = ONE_KB * 1000.0;
|
||||
const ONE_GB: f64 = ONE_MB * 1000.0;
|
||||
|
||||
#[derive(Debug, Clone, Eq, Hash, PartialEq)]
|
||||
pub enum ScrollDirection {
|
||||
Next,
|
||||
Previous,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Eq, Hash, PartialEq)]
|
||||
pub struct ContainerId(String);
|
||||
|
||||
@@ -177,7 +183,14 @@ impl<T> StatefulList<T> {
|
||||
self.state.select(Some(0));
|
||||
}
|
||||
|
||||
pub fn next(&mut self) {
|
||||
pub fn scroll(&mut self, scroll: &ScrollDirection) {
|
||||
match scroll {
|
||||
ScrollDirection::Next => self.next(),
|
||||
ScrollDirection::Previous => self.previous(),
|
||||
}
|
||||
}
|
||||
|
||||
fn next(&mut self) {
|
||||
if !self.items.is_empty() {
|
||||
self.state.select(Some(
|
||||
self.state.selected().map_or(
|
||||
@@ -190,7 +203,7 @@ impl<T> StatefulList<T> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn previous(&mut self) {
|
||||
fn previous(&mut self) {
|
||||
if !self.items.is_empty() {
|
||||
self.state.select(Some(
|
||||
self.state
|
||||
@@ -600,6 +613,8 @@ impl LogsTz {
|
||||
pub struct Logs {
|
||||
lines: StatefulList<Text<'static>>,
|
||||
tz: HashSet<LogsTz>,
|
||||
search_results: Vec<usize>,
|
||||
search_term: Option<String>,
|
||||
offset: u16,
|
||||
max_log_len: usize,
|
||||
adjusted_max_width: usize,
|
||||
@@ -614,6 +629,8 @@ impl Default for Logs {
|
||||
lines,
|
||||
tz: HashSet::new(),
|
||||
offset: 0,
|
||||
search_term: None,
|
||||
search_results: vec![],
|
||||
adjusted_max_width: 0,
|
||||
adjust_max_width_text_len: 0,
|
||||
max_log_len: 0,
|
||||
@@ -621,16 +638,185 @@ impl Default for Logs {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Ord, PartialOrd, Hash)]
|
||||
pub enum LogsButton {
|
||||
Both,
|
||||
Next,
|
||||
Previous,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Hash)]
|
||||
pub struct LogSearch {
|
||||
pub term: Option<String>,
|
||||
pub result: Option<String>,
|
||||
pub buttons: Option<LogsButton>,
|
||||
}
|
||||
|
||||
/// LogSearch is used in FrameData
|
||||
impl From<&Logs> for LogSearch {
|
||||
fn from(l: &Logs) -> Self {
|
||||
let buttons = l.lines.state.selected().as_ref().and_then(|x| {
|
||||
let show_next = l.search_results.iter().any(|n| n > x);
|
||||
let show_previous = l.search_results.iter().any(|n| n < x);
|
||||
match (show_next, show_previous) {
|
||||
(true, true) => Some(LogsButton::Both),
|
||||
(true, false) => Some(LogsButton::Next),
|
||||
(false, true) => Some(LogsButton::Previous),
|
||||
(false, false) => None,
|
||||
}
|
||||
});
|
||||
Self {
|
||||
term: l.search_term.clone(),
|
||||
result: l.get_search_result(),
|
||||
buttons,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Logs {
|
||||
/// Only allow a new log line to be inserted if the log timestamp isn't in the tz HashSet
|
||||
pub fn insert(&mut self, line: Text<'static>, tz: LogsTz) {
|
||||
if self.tz.insert(tz) {
|
||||
self.max_log_len = self.max_log_len.max(line.width());
|
||||
self.lines.items.push(line);
|
||||
pub fn gen_log_search(&self) -> LogSearch {
|
||||
LogSearch::from(self)
|
||||
}
|
||||
|
||||
/// Scroll to the next or previous search result, accounts for when currently selected line isn't in the results vec
|
||||
pub fn search_scroll(&mut self, sd: &ScrollDirection) -> Option<()> {
|
||||
if let Some(current_selected) = self.lines.state.selected() {
|
||||
if let Some(current_position) = self
|
||||
.search_results
|
||||
.iter()
|
||||
.position(|i| i == ¤t_selected)
|
||||
{
|
||||
if let Some(new_index) = match sd {
|
||||
ScrollDirection::Next => current_position.checked_add(1),
|
||||
ScrollDirection::Previous => current_position.checked_sub(1),
|
||||
} {
|
||||
if let Some(f) = self.search_results.get(new_index) {
|
||||
self.lines.state.select(Some(*f));
|
||||
return Some(());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let range = match sd {
|
||||
ScrollDirection::Previous => (0..=current_selected).rev().collect::<Vec<_>>(),
|
||||
ScrollDirection::Next => (current_selected
|
||||
..=self
|
||||
.search_results
|
||||
.last()
|
||||
.map_or_else(|| current_selected, |i| *i))
|
||||
.collect::<Vec<_>>(),
|
||||
};
|
||||
for i in range {
|
||||
if self.search_results.contains(&i) {
|
||||
self.lines.state.select(Some(i));
|
||||
return Some(());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
/// Get a string x/y, where y is total matches found, and x is current ordered selected line
|
||||
/// WIll be padded by max chars of total matches
|
||||
fn get_search_result(&self) -> Option<String> {
|
||||
if self.search_results.is_empty() {
|
||||
return None;
|
||||
}
|
||||
Some(self.lines.state.selected().map_or_else(
|
||||
|| format!("{}", self.search_results.len()),
|
||||
|current_index| {
|
||||
self.search_results
|
||||
.iter()
|
||||
.position(|i| i == ¤t_index)
|
||||
.map_or_else(
|
||||
|| format!("{}", self.search_results.len()),
|
||||
|index| {
|
||||
let len = format!("{}", self.search_results.len());
|
||||
let len_width = len.chars().count();
|
||||
format!("{:>len_width$}/{len:>len_width$}", index + 1)
|
||||
},
|
||||
)
|
||||
},
|
||||
))
|
||||
}
|
||||
|
||||
/// Search through the logs for a matching string
|
||||
pub fn search(&mut self, case_sensitive: bool, scroll: bool) {
|
||||
if let Some(search_term) = self.search_term.as_ref() {
|
||||
let term = if case_sensitive {
|
||||
search_term.to_owned()
|
||||
} else {
|
||||
search_term.to_lowercase()
|
||||
};
|
||||
self.search_results = self
|
||||
.lines
|
||||
.items
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter_map(|(index, a)| {
|
||||
a.lines
|
||||
.iter()
|
||||
.any(|b| {
|
||||
b.spans.iter().any(|c| {
|
||||
if case_sensitive {
|
||||
c.content.contains(&term)
|
||||
} else {
|
||||
c.content.to_lowercase().contains(&term)
|
||||
}
|
||||
})
|
||||
})
|
||||
.then_some(index)
|
||||
})
|
||||
.collect();
|
||||
if !self.search_results.is_empty() && scroll {
|
||||
self.lines.state.select(self.search_results.last().copied());
|
||||
self.offset = 0;
|
||||
}
|
||||
} else {
|
||||
self.search_results.clear();
|
||||
}
|
||||
}
|
||||
|
||||
/// If scrolling horiztonally along the logs, display a counter of the position in the in the scroll, `x/y`
|
||||
/// Set a single char into the filter term
|
||||
pub fn search_term_push(&mut self, c: char, case_sensitive: bool) {
|
||||
if let Some(term) = self.search_term.as_mut() {
|
||||
term.push(c);
|
||||
} else {
|
||||
self.search_term = Some(format!("{c}"));
|
||||
}
|
||||
self.search(case_sensitive, true);
|
||||
}
|
||||
|
||||
/// Delete the final char of the filter term
|
||||
pub fn search_term_pop(&mut self, case_sensitive: bool) {
|
||||
if let Some(term) = self.search_term.as_mut() {
|
||||
term.pop();
|
||||
if term.is_empty() {
|
||||
self.search_term = None;
|
||||
}
|
||||
}
|
||||
self.search(case_sensitive, true);
|
||||
}
|
||||
|
||||
/// Remove the filter completely
|
||||
pub fn search_term_clear(&mut self) {
|
||||
self.search_term = None;
|
||||
self.search_results.clear();
|
||||
}
|
||||
|
||||
/// Only allow a new log line to be inserted if the log timestamp isn't in the tz HashSet
|
||||
pub fn insert(&mut self, line: Text<'static>, tz: LogsTz, case_sensitive: bool) {
|
||||
if self.tz.insert(tz) {
|
||||
self.max_log_len = self.max_log_len.max(line.width());
|
||||
self.lines.items.push(line);
|
||||
// Maybe - Ideally we'd re-render here
|
||||
if self.search_term.is_some() {
|
||||
self.search(case_sensitive, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// If scrolling horizontally along the logs, display a counter of the position in the in the scroll, `x/y`
|
||||
pub fn get_scroll_title(&mut self, width: u16) -> Option<String> {
|
||||
if self.horizontal_scroll_able(width) {
|
||||
let text_width = self.adjust_max_width_text_len;
|
||||
@@ -723,7 +909,7 @@ impl Logs {
|
||||
self.lines.get_state_title()
|
||||
}
|
||||
|
||||
/// Return true it currently selected cotnainer logs are wide enough to horizontally scroll
|
||||
/// Return true it currently selected container logs are wide enough to horizontally scroll
|
||||
pub fn horizontal_scroll_able(&mut self, width: u16) -> bool {
|
||||
if self.lines.items.is_empty() {
|
||||
return false;
|
||||
@@ -748,21 +934,27 @@ impl Logs {
|
||||
self.offset = self.offset.saturating_sub(1);
|
||||
}
|
||||
|
||||
/// Scroll lines down by one
|
||||
pub fn next(&mut self) {
|
||||
self.lines.next();
|
||||
}
|
||||
|
||||
/// Scroll lines up by one
|
||||
pub fn previous(&mut self) {
|
||||
self.lines.previous();
|
||||
}
|
||||
|
||||
/// Go to the end of the lines
|
||||
pub fn end(&mut self) {
|
||||
self.lines.end();
|
||||
}
|
||||
|
||||
/// Go to the start of the lines
|
||||
pub fn start(&mut self) {
|
||||
self.lines.start();
|
||||
}
|
||||
|
||||
/// Get total number of log lines
|
||||
pub const fn len(&self) -> usize {
|
||||
self.lines.items.len()
|
||||
}
|
||||
@@ -938,7 +1130,7 @@ mod tests {
|
||||
};
|
||||
|
||||
use crate::{
|
||||
app_data::{ContainerImage, Logs, LogsTz, RunningState},
|
||||
app_data::{ContainerImage, LogSearch, Logs, LogsTz, RunningState},
|
||||
ui::log_sanitizer,
|
||||
};
|
||||
|
||||
@@ -1075,9 +1267,9 @@ mod tests {
|
||||
let mut logs = Logs::default();
|
||||
let line = log_sanitizer::remove_ansi(input);
|
||||
|
||||
logs.insert(Text::from(line.clone()), tz.clone());
|
||||
logs.insert(Text::from(line.clone()), tz.clone());
|
||||
logs.insert(Text::from(line), tz);
|
||||
logs.insert(Text::from(line.clone()), tz.clone(), true);
|
||||
logs.insert(Text::from(line.clone()), tz.clone(), true);
|
||||
logs.insert(Text::from(line), tz, true);
|
||||
|
||||
assert_eq!(logs.lines.items.len(), 1);
|
||||
|
||||
@@ -1085,9 +1277,9 @@ mod tests {
|
||||
let (tz, _) = LogsTz::splitter(input);
|
||||
let line = log_sanitizer::remove_ansi(input);
|
||||
|
||||
logs.insert(Text::from(line.clone()), tz.clone());
|
||||
logs.insert(Text::from(line.clone()), tz.clone());
|
||||
logs.insert(Text::from(line), tz);
|
||||
logs.insert(Text::from(line.clone()), tz.clone(), true);
|
||||
logs.insert(Text::from(line.clone()), tz.clone(), true);
|
||||
logs.insert(Text::from(line), tz, true);
|
||||
|
||||
assert_eq!(logs.lines.items.len(), 2);
|
||||
}
|
||||
@@ -1150,15 +1342,15 @@ mod tests {
|
||||
|
||||
let input = "2023-01-14T19:13:30.783138328Z Hello world some long line".to_owned();
|
||||
let (tz, _) = LogsTz::splitter(&input);
|
||||
logs.insert(Text::from(input), tz);
|
||||
logs.insert(Text::from(input), tz, true);
|
||||
|
||||
let input = "2023-01-14T19:13:31.783138328Z Hello world some line".to_owned();
|
||||
let (tz, _) = LogsTz::splitter(&input);
|
||||
logs.insert(Text::from(input), tz);
|
||||
logs.insert(Text::from(input), tz, true);
|
||||
|
||||
let input = "2023-01-14T19:13:32.783138328Z Hello world".to_owned();
|
||||
let (tz, _) = LogsTz::splitter(&input);
|
||||
logs.insert(Text::from(input), tz);
|
||||
logs.insert(Text::from(input), tz, true);
|
||||
|
||||
logs.offset = 43;
|
||||
let result = logs.get_visible_logs(
|
||||
@@ -1188,14 +1380,14 @@ mod tests {
|
||||
|
||||
let input = "short".to_owned();
|
||||
let (tz, _) = LogsTz::splitter(&input);
|
||||
logs.insert(Text::from(input), tz);
|
||||
logs.insert(Text::from(input), tz, true);
|
||||
|
||||
let result = logs.get_scroll_title(10);
|
||||
assert!(result.is_none());
|
||||
|
||||
let input = "2023-01-14T19:13:30.783138328Z Hello world some long line".to_owned();
|
||||
let (tz, _) = LogsTz::splitter(&input);
|
||||
logs.insert(Text::from(input), tz);
|
||||
logs.insert(Text::from(input), tz, true);
|
||||
|
||||
let result = logs.get_scroll_title(10);
|
||||
assert_eq!(result, Some(" 0/51 → ".to_owned()));
|
||||
@@ -1211,4 +1403,119 @@ mod tests {
|
||||
let result = logs.get_scroll_title(10);
|
||||
assert_eq!(result, Some(" ← 51/51 ".to_owned()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
/// Test the log search
|
||||
fn test_logsearch() {
|
||||
let mut logs = Logs::default();
|
||||
|
||||
for i in 1..=10 {
|
||||
let input = if i % 2 == 0 {
|
||||
format!("{i}, hello world some long line {i}")
|
||||
} else {
|
||||
format!("{i}, Hello world some long line {i}")
|
||||
};
|
||||
let (tz, _) = LogsTz::splitter(&input);
|
||||
logs.insert(Text::from(input), tz, true);
|
||||
}
|
||||
|
||||
logs.search_term_push('H', true);
|
||||
assert_eq!(logs.search_results, [0, 2, 4, 6, 8]);
|
||||
logs.search_term_clear();
|
||||
logs.search_term_push('H', false);
|
||||
assert_eq!(logs.search_results, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
/// Test the LogSearch::From() methods
|
||||
fn test_logsearch_from() {
|
||||
let mut logs = Logs::default();
|
||||
|
||||
for i in 1..=10 {
|
||||
let input = format!("{i}, Hello world some long line {i}");
|
||||
let (tz, _) = LogsTz::splitter(&input);
|
||||
logs.insert(Text::from(input), tz, true);
|
||||
}
|
||||
|
||||
let log_search = LogSearch::from(&logs);
|
||||
assert_eq!(
|
||||
log_search,
|
||||
LogSearch {
|
||||
term: None,
|
||||
result: None,
|
||||
buttons: None
|
||||
}
|
||||
);
|
||||
|
||||
logs.search_term_push('H', true);
|
||||
let log_search = LogSearch::from(&logs);
|
||||
assert_eq!(
|
||||
log_search,
|
||||
LogSearch {
|
||||
term: Some("H".to_owned()),
|
||||
result: Some("10/10".to_owned()),
|
||||
buttons: Some(crate::app_data::LogsButton::Previous)
|
||||
}
|
||||
);
|
||||
|
||||
logs.previous();
|
||||
|
||||
let log_search = LogSearch::from(&logs);
|
||||
assert_eq!(
|
||||
log_search,
|
||||
LogSearch {
|
||||
term: Some("H".to_owned()),
|
||||
result: Some(" 9/10".to_owned()),
|
||||
buttons: Some(crate::app_data::LogsButton::Both)
|
||||
}
|
||||
);
|
||||
|
||||
logs.start();
|
||||
|
||||
let log_search = LogSearch::from(&logs);
|
||||
assert_eq!(
|
||||
log_search,
|
||||
LogSearch {
|
||||
term: Some("H".to_owned()),
|
||||
result: Some(" 1/10".to_owned()),
|
||||
buttons: Some(crate::app_data::LogsButton::Next)
|
||||
}
|
||||
);
|
||||
|
||||
logs.search_term_push('H', true);
|
||||
let log_search = LogSearch::from(&logs);
|
||||
assert_eq!(
|
||||
log_search,
|
||||
LogSearch {
|
||||
term: Some("HH".to_owned()),
|
||||
result: None,
|
||||
buttons: None
|
||||
}
|
||||
);
|
||||
|
||||
logs.search_term_clear();
|
||||
logs.search_term_push('2', true);
|
||||
let log_search = LogSearch::from(&logs);
|
||||
assert_eq!(logs.lines.state.selected(), Some(1));
|
||||
assert_eq!(
|
||||
log_search,
|
||||
LogSearch {
|
||||
term: Some("2".to_owned()),
|
||||
result: Some("1/1".to_owned()),
|
||||
buttons: None
|
||||
}
|
||||
);
|
||||
|
||||
logs.next();
|
||||
|
||||
let log_search = LogSearch::from(&logs);
|
||||
assert_eq!(
|
||||
log_search,
|
||||
LogSearch {
|
||||
term: Some("2".to_owned()),
|
||||
result: Some("1".to_owned()),
|
||||
buttons: Some(crate::app_data::LogsButton::Previous)
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
+86
-65
@@ -171,6 +171,19 @@ impl AppData {
|
||||
(self.filter.by, self.filter.term.as_ref())
|
||||
}
|
||||
|
||||
pub fn log_search_scroll(&mut self, np: &ScrollDirection) {
|
||||
if let Some(i) = self.get_mut_selected_container() {
|
||||
if i.logs.search_scroll(np).is_some() {
|
||||
self.rerender.update_draw();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn gen_log_search(&self) -> Option<LogSearch> {
|
||||
self.get_selected_container()
|
||||
.map(|i| i.logs.gen_log_search())
|
||||
}
|
||||
|
||||
/// Check if a given container can be inserted into the "visible" list, based on current filter term and filter_by
|
||||
fn can_insert(&self, container: &ContainerItem) -> bool {
|
||||
self.filter.term.as_ref().is_none_or(|term| {
|
||||
@@ -224,6 +237,31 @@ impl AppData {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn logs_search_clear(&mut self) {
|
||||
if let Some(selected_container) = self.get_mut_selected_container() {
|
||||
selected_container.logs.search_term_clear();
|
||||
self.rerender.update_draw();
|
||||
}
|
||||
}
|
||||
|
||||
/// Set a single char into the filter term
|
||||
pub fn log_search_push(&mut self, c: char) {
|
||||
let cs = self.config.log_search_case_sensitive;
|
||||
if let Some(selected_container) = self.get_mut_selected_container() {
|
||||
selected_container.logs.search_term_push(c, cs);
|
||||
self.rerender.update_draw();
|
||||
}
|
||||
}
|
||||
|
||||
/// Delete the final char of the filter term
|
||||
pub fn log_search_pop(&mut self) {
|
||||
let cs = self.config.log_search_case_sensitive;
|
||||
if let Some(selected_container) = self.get_mut_selected_container() {
|
||||
selected_container.logs.search_term_pop(cs);
|
||||
self.rerender.update_draw();
|
||||
}
|
||||
}
|
||||
|
||||
/// Re-filter the containers, used after the filter.by has been changed
|
||||
fn re_filter(&mut self) {
|
||||
self.containers.items.append(&mut self.hidden_containers);
|
||||
@@ -448,15 +486,8 @@ impl AppData {
|
||||
self.rerender.update_draw();
|
||||
}
|
||||
|
||||
/// Select the next container
|
||||
pub fn containers_next(&mut self) {
|
||||
self.containers.next();
|
||||
self.rerender.update_draw();
|
||||
}
|
||||
|
||||
/// select the previous container
|
||||
pub fn containers_previous(&mut self) {
|
||||
self.containers.previous();
|
||||
pub fn containers_scroll(&mut self, scroll: &ScrollDirection) {
|
||||
self.containers.scroll(scroll);
|
||||
self.rerender.update_draw();
|
||||
}
|
||||
|
||||
@@ -576,17 +607,10 @@ impl AppData {
|
||||
}
|
||||
|
||||
/// Change selected choice of docker commands of selected container
|
||||
pub fn docker_controls_next(&mut self) {
|
||||
pub fn docker_controls_scroll(&mut self, scroll: &ScrollDirection) {
|
||||
if let Some(i) = self.get_mut_selected_container() {
|
||||
i.docker_controls.next();
|
||||
self.rerender.update_draw();
|
||||
}
|
||||
}
|
||||
|
||||
/// Change selected choice of docker commands of selected container
|
||||
pub fn docker_controls_previous(&mut self) {
|
||||
if let Some(i) = self.get_mut_selected_container() {
|
||||
i.docker_controls.previous();
|
||||
i.docker_controls.scroll(scroll);
|
||||
// i.docker_controls.next();
|
||||
self.rerender.update_draw();
|
||||
}
|
||||
}
|
||||
@@ -637,40 +661,36 @@ impl AppData {
|
||||
})
|
||||
}
|
||||
|
||||
/// If scrolling horiztonally along the logs, display a counter of the position in the in the scroll, `x/y`
|
||||
/// If scrolling horizontally along the logs, display a counter of the position in the in the scroll, `x/y`
|
||||
pub fn get_scroll_title(&mut self, width: u16) -> Option<String> {
|
||||
self.get_mut_selected_container()
|
||||
.and_then(|i| i.logs.get_scroll_title(width))
|
||||
}
|
||||
|
||||
/// Increase the logs offset, basically moving an invisible cursor back
|
||||
pub fn log_back(&mut self) {
|
||||
if let Some(i) = self.get_mut_selected_container() {
|
||||
i.logs.back();
|
||||
self.rerender.update_draw();
|
||||
}
|
||||
}
|
||||
|
||||
/// Increase the logs offset, basically moving an invisible cursor forward
|
||||
pub fn log_forward(&mut self, width: u16) {
|
||||
if let Some(i) = self.get_mut_selected_container() {
|
||||
i.logs.forward(width);
|
||||
self.rerender.update_draw();
|
||||
pub fn logs_horizontal_scroll(&mut self, sd: &ScrollDirection, width: u16) {
|
||||
match sd {
|
||||
ScrollDirection::Next => {
|
||||
if let Some(i) = self.get_mut_selected_container() {
|
||||
i.logs.forward(width);
|
||||
self.rerender.update_draw();
|
||||
}
|
||||
}
|
||||
ScrollDirection::Previous => {
|
||||
if let Some(i) = self.get_mut_selected_container() {
|
||||
i.logs.back();
|
||||
self.rerender.update_draw();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// select next selected log line
|
||||
pub fn log_next(&mut self) {
|
||||
pub fn log_scroll(&mut self, scroll: &ScrollDirection) {
|
||||
if let Some(i) = self.get_mut_selected_container() {
|
||||
i.logs.next();
|
||||
self.rerender.update_draw();
|
||||
}
|
||||
}
|
||||
|
||||
/// select previous selected log line
|
||||
pub fn log_previous(&mut self) {
|
||||
if let Some(i) = self.get_mut_selected_container() {
|
||||
i.logs.previous();
|
||||
match scroll {
|
||||
ScrollDirection::Next => i.logs.next(),
|
||||
ScrollDirection::Previous => i.logs.previous(),
|
||||
}
|
||||
self.rerender.update_draw();
|
||||
}
|
||||
}
|
||||
@@ -857,7 +877,7 @@ impl AppData {
|
||||
// If removed container is currently selected, then change selected to previous
|
||||
// This will default to 0 in any edge cases
|
||||
if self.containers.state.selected().is_some() {
|
||||
self.containers.previous();
|
||||
self.containers.scroll(&ScrollDirection::Previous);
|
||||
}
|
||||
// Check is some, else can cause out of bounds error, if containers get removed before a docker update
|
||||
if self.containers.items.get(index).is_some() {
|
||||
@@ -959,6 +979,8 @@ impl AppData {
|
||||
let format = self.config.timestamp_format.clone();
|
||||
let config_tz = self.config.timezone.clone();
|
||||
|
||||
let cs = self.config.log_search_case_sensitive;
|
||||
|
||||
let show_timestamp = self.config.show_timestamp;
|
||||
|
||||
if let Some(container) = self.get_any_container_by_id(id) {
|
||||
@@ -985,7 +1007,7 @@ impl AppData {
|
||||
} else {
|
||||
log_sanitizer::remove_ansi(&i)
|
||||
};
|
||||
container.logs.insert(Text::from(lines), log_tz);
|
||||
container.logs.insert(Text::from(lines), log_tz, cs);
|
||||
}
|
||||
|
||||
// Set the logs selected row for each container
|
||||
@@ -1422,7 +1444,7 @@ mod tests {
|
||||
);
|
||||
|
||||
// Calling previous when at start has no effect
|
||||
app_data.containers_previous();
|
||||
app_data.containers_scroll(&ScrollDirection::Previous);
|
||||
let result = app_data.get_selected_container_id();
|
||||
assert_eq!(result, Some(ContainerId::from("1")));
|
||||
let result = app_data.get_selected_container_id_state_name();
|
||||
@@ -1445,7 +1467,7 @@ mod tests {
|
||||
|
||||
// Advance list state by 1
|
||||
app_data.containers_start();
|
||||
app_data.containers_next();
|
||||
app_data.containers.scroll(&ScrollDirection::Next);
|
||||
|
||||
let result = app_data.get_container_state();
|
||||
assert_eq!(result.selected(), Some(1));
|
||||
@@ -1489,7 +1511,7 @@ mod tests {
|
||||
);
|
||||
|
||||
// Calling previous when at end has no effect
|
||||
app_data.containers_next();
|
||||
app_data.containers.scroll(&ScrollDirection::Next);
|
||||
let result = app_data.get_selected_container_id();
|
||||
assert_eq!(result, Some(ContainerId::from("3")));
|
||||
let result = app_data.get_selected_container_id_state_name();
|
||||
@@ -1510,7 +1532,7 @@ mod tests {
|
||||
let mut app_data = gen_appdata(&containers);
|
||||
|
||||
app_data.containers_end();
|
||||
app_data.containers_previous();
|
||||
app_data.containers.scroll(&ScrollDirection::Previous);
|
||||
let result = app_data.get_container_state();
|
||||
assert_eq!(result.selected(), Some(1));
|
||||
assert_eq!(result.offset(), 0);
|
||||
@@ -1526,7 +1548,7 @@ mod tests {
|
||||
assert_eq!(result, None);
|
||||
|
||||
app_data.containers.start();
|
||||
app_data.containers.next();
|
||||
app_data.containers.scroll(&ScrollDirection::Next);
|
||||
|
||||
let result = app_data.get_selected_container();
|
||||
assert_eq!(result, Some(&containers[1]));
|
||||
@@ -1613,7 +1635,7 @@ mod tests {
|
||||
let mut app_data = gen_appdata(&containers);
|
||||
app_data.containers_start();
|
||||
app_data.docker_controls_start();
|
||||
app_data.docker_controls_next();
|
||||
app_data.docker_controls_scroll(&ScrollDirection::Next);
|
||||
|
||||
let result = app_data.selected_docker_controls();
|
||||
assert_eq!(result, Some(DockerCommand::Restart));
|
||||
@@ -1631,7 +1653,7 @@ mod tests {
|
||||
assert_eq!(result, Some(DockerCommand::Delete));
|
||||
|
||||
// Next has no effect when at end
|
||||
app_data.docker_controls_next();
|
||||
app_data.docker_controls_scroll(&ScrollDirection::Next);
|
||||
let result = app_data.selected_docker_controls();
|
||||
assert_eq!(result, Some(DockerCommand::Delete));
|
||||
}
|
||||
@@ -1643,14 +1665,14 @@ mod tests {
|
||||
let mut app_data = gen_appdata(&containers);
|
||||
app_data.containers_start();
|
||||
app_data.docker_controls_end();
|
||||
app_data.docker_controls_previous();
|
||||
app_data.docker_controls_scroll(&ScrollDirection::Previous);
|
||||
|
||||
let result = app_data.selected_docker_controls();
|
||||
assert_eq!(result, Some(DockerCommand::Stop));
|
||||
|
||||
// previous has no effect when at start
|
||||
app_data.docker_controls_start();
|
||||
app_data.docker_controls_previous();
|
||||
app_data.docker_controls_scroll(&ScrollDirection::Previous);
|
||||
let result = app_data.selected_docker_controls();
|
||||
assert_eq!(result, Some(DockerCommand::Pause));
|
||||
}
|
||||
@@ -1914,7 +1936,7 @@ mod tests {
|
||||
assert_eq!(result, " 3/3 - container_1 - image_1");
|
||||
|
||||
// Change log state to no longer be at the end
|
||||
app_data.log_previous();
|
||||
app_data.log_scroll(&ScrollDirection::Previous);
|
||||
let result = app_data.get_log_title();
|
||||
assert_eq!(result, " 2/3 - container_1 - image_1");
|
||||
}
|
||||
@@ -1935,7 +1957,7 @@ mod tests {
|
||||
assert_eq!(result, " - container_1 - image_1");
|
||||
|
||||
// change container
|
||||
app_data.containers_next();
|
||||
app_data.containers_scroll(&ScrollDirection::Next);
|
||||
let result = app_data.get_log_title();
|
||||
assert_eq!(result, " - container_2 - image_2");
|
||||
|
||||
@@ -1946,7 +1968,7 @@ mod tests {
|
||||
assert_eq!(result, " 3/3 - container_2 - image_2");
|
||||
|
||||
// Change log state to no longer be at the end
|
||||
app_data.log_previous();
|
||||
app_data.log_scroll(&ScrollDirection::Previous);
|
||||
let result = app_data.get_log_title();
|
||||
assert_eq!(result, " 2/3 - container_2 - image_2");
|
||||
}
|
||||
@@ -2053,8 +2075,7 @@ mod tests {
|
||||
let result = app_data.get_log_title();
|
||||
assert_eq!(result, " 1/3 - container_1 - image_1");
|
||||
|
||||
app_data.log_next();
|
||||
|
||||
app_data.log_scroll(&ScrollDirection::Next);
|
||||
let result = app_data.get_log_state();
|
||||
assert!(result.is_some());
|
||||
assert_eq!(result.as_ref().unwrap().selected(), Some(1));
|
||||
@@ -2063,7 +2084,7 @@ mod tests {
|
||||
let result = app_data.get_log_title();
|
||||
assert_eq!(result, " 2/3 - container_1 - image_1");
|
||||
|
||||
app_data.log_next();
|
||||
app_data.log_scroll(&ScrollDirection::Next);
|
||||
let result = app_data.get_log_state();
|
||||
assert!(result.is_some());
|
||||
assert_eq!(result.as_ref().unwrap().selected(), Some(2));
|
||||
@@ -2071,7 +2092,7 @@ mod tests {
|
||||
|
||||
let result = app_data.get_log_title();
|
||||
assert_eq!(result, " 3/3 - container_1 - image_1");
|
||||
app_data.log_next();
|
||||
app_data.log_scroll(&ScrollDirection::Next);
|
||||
|
||||
let result = app_data.get_log_state();
|
||||
assert!(result.is_some());
|
||||
@@ -2102,7 +2123,7 @@ mod tests {
|
||||
let result = app_data.get_log_title();
|
||||
assert_eq!(result, " 3/3 - container_1 - image_1");
|
||||
|
||||
app_data.log_previous();
|
||||
app_data.log_scroll(&ScrollDirection::Previous);
|
||||
|
||||
let result = app_data.get_log_state();
|
||||
assert!(result.is_some());
|
||||
@@ -2111,7 +2132,7 @@ mod tests {
|
||||
let result = app_data.get_log_title();
|
||||
assert_eq!(result, " 2/3 - container_1 - image_1");
|
||||
|
||||
app_data.log_previous();
|
||||
app_data.log_scroll(&ScrollDirection::Previous);
|
||||
let result = app_data.get_log_state();
|
||||
assert!(result.is_some());
|
||||
assert_eq!(result.as_ref().unwrap().selected(), Some(0));
|
||||
@@ -2119,7 +2140,7 @@ mod tests {
|
||||
let result = app_data.get_log_title();
|
||||
assert_eq!(result, " 1/3 - container_1 - image_1");
|
||||
|
||||
app_data.log_previous();
|
||||
app_data.log_scroll(&ScrollDirection::Previous);
|
||||
let result = app_data.get_log_state();
|
||||
assert!(result.is_some());
|
||||
assert_eq!(result.as_ref().unwrap().selected(), Some(0));
|
||||
@@ -2413,7 +2434,7 @@ mod tests {
|
||||
}
|
||||
|
||||
for _ in 0..=500 {
|
||||
app_data.log_next();
|
||||
app_data.log_scroll(&ScrollDirection::Next);
|
||||
}
|
||||
let result = app_data.get_logs(
|
||||
Size {
|
||||
|
||||
@@ -89,6 +89,24 @@ impl From<Option<ConfigColors>> for AppColors {
|
||||
Self::map_color(fc.text.as_deref(), &mut app_colors.filter.text);
|
||||
}
|
||||
|
||||
// Log search
|
||||
if let Some(ls) = config_colors.log_search {
|
||||
Self::map_color(
|
||||
ls.background.as_deref(),
|
||||
&mut app_colors.log_search.background,
|
||||
);
|
||||
Self::map_color(
|
||||
ls.highlight.as_deref(),
|
||||
&mut app_colors.log_search.highlight,
|
||||
);
|
||||
|
||||
Self::map_color(
|
||||
ls.button_text.as_deref(),
|
||||
&mut app_colors.log_search.button_text,
|
||||
);
|
||||
Self::map_color(ls.text.as_deref(), &mut app_colors.log_search.text);
|
||||
}
|
||||
|
||||
// Help Popup
|
||||
if let Some(hp) = config_colors.popup_help {
|
||||
Self::map_color(
|
||||
@@ -238,6 +256,7 @@ optional_config_struct!(
|
||||
ConfigContainers, background, icon, text, text_rx, text_tx;
|
||||
ConfigContainerState, background, dead, exited, paused, removing, restarting, running_healthy, running_unhealthy, unknown;
|
||||
ConfigFilter, background, text, selected_filter_background, selected_filter_text, highlight;
|
||||
ConfigLogSearch, background, text, button_text, highlight;
|
||||
ConfigHeadersBar, background, loading_spinner, text, text_selected;
|
||||
ConfigLogs, background, text
|
||||
);
|
||||
@@ -251,6 +270,7 @@ config_struct!(
|
||||
Containers, background, icon, text, text_rx, text_tx;
|
||||
ContainerState, dead, exited, paused, removing, restarting, running_healthy, running_unhealthy, unknown;
|
||||
Filter, background, text, selected_filter_background, selected_filter_text, highlight;
|
||||
LogSearch, background, text, button_text, highlight;
|
||||
HeadersBar, background, text_selected, loading_spinner, text;
|
||||
Logs, background, text;
|
||||
PopupDelete, background, text, text_highlight;
|
||||
@@ -269,6 +289,7 @@ pub struct ConfigColors {
|
||||
container_state: Option<ConfigContainerState>,
|
||||
containers: Option<ConfigContainers>,
|
||||
filter: Option<ConfigFilter>,
|
||||
log_search: Option<ConfigLogSearch>,
|
||||
headers_bar: Option<ConfigHeadersBar>,
|
||||
logs: Option<ConfigLogs>,
|
||||
popup_delete: Option<ConfigBackgroundTextHighlight>,
|
||||
@@ -397,6 +418,18 @@ impl Filter {
|
||||
}
|
||||
}
|
||||
|
||||
/// Default colours for the log search
|
||||
impl LogSearch {
|
||||
const fn new() -> Self {
|
||||
Self {
|
||||
background: Color::Reset,
|
||||
highlight: Color::Magenta,
|
||||
button_text: Color::Black,
|
||||
text: Color::Gray,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Default colours for the logs panel, only applied if color_logs is false
|
||||
impl Logs {
|
||||
const fn new() -> Self {
|
||||
@@ -458,6 +491,7 @@ pub struct AppColors {
|
||||
pub commands: Commands,
|
||||
pub container_state: ContainerState,
|
||||
pub containers: Containers,
|
||||
pub log_search: LogSearch,
|
||||
pub filter: Filter,
|
||||
pub headers_bar: HeadersBar,
|
||||
pub logs: Logs,
|
||||
@@ -477,6 +511,7 @@ impl AppColors {
|
||||
commands: Commands::new(),
|
||||
container_state: ContainerState::new(),
|
||||
containers: Containers::new(),
|
||||
log_search: LogSearch::new(),
|
||||
filter: Filter::new(),
|
||||
headers_bar: HeadersBar::new(),
|
||||
logs: Logs::new(),
|
||||
|
||||
+24
-11
@@ -43,6 +43,9 @@ use_cli = false
|
||||
# Show the logs section - this can be changed during operation with the log_section_toggle key
|
||||
show_logs = true
|
||||
|
||||
# Use case-sensitive matching for logs
|
||||
log_search_case_sensitive = true
|
||||
|
||||
#################
|
||||
# Custom Keymap #
|
||||
#################
|
||||
@@ -72,29 +75,25 @@ delete_confirm = ["y"]
|
||||
exec = ["e"]
|
||||
# Enter filter mode
|
||||
filter_mode = ["/", "F1"]
|
||||
|
||||
# Enter log search mode
|
||||
log_search_mode = ["#"]
|
||||
|
||||
# Quit at anytime
|
||||
quit = ["q"]
|
||||
# Save logs of selected container to file on disk
|
||||
save_logs = ["s"]
|
||||
# TODO "scroll_down_many" will be removed in the next release
|
||||
# scroll down a list by many
|
||||
scroll_down_many = ["pagedown"]
|
||||
# TODO rename in next release
|
||||
# scroll down a list by one item
|
||||
scroll_down_one = ["down", "j"]
|
||||
scroll_down = ["down", "j"]
|
||||
|
||||
# scroll down to the end of a list
|
||||
scroll_end = ["end"]
|
||||
# Modifier to scroll by 10 lines isntead of one, used in conjunction with scroll_up_x/scroll_down_x
|
||||
# Modifier to scroll by 10 lines instead of one, used in conjunction with scroll_up/scroll_down
|
||||
scroll_many = ["control"]
|
||||
# scroll up to the start of a list
|
||||
scroll_start = ["home"]
|
||||
# TODO "scroll_up_many" will be removed in the next release
|
||||
# scroll up a list by many
|
||||
scroll_up_many = ["pageup"]
|
||||
# TODO rename in next release
|
||||
# scroll up a list by one item
|
||||
scroll_up_one = ["up", "k"]
|
||||
scroll_up = ["up", "k"]
|
||||
# Horizontal scroll of the logs
|
||||
log_scroll_forward = ["right"]
|
||||
log_scroll_back = ["left"]
|
||||
@@ -123,6 +122,9 @@ log_section_height_decrease = ["-"]
|
||||
log_section_height_increase = ["+"]
|
||||
# Toggle visibility of the log section
|
||||
log_section_toggle = ["\\"]
|
||||
|
||||
|
||||
|
||||
# Force a complete clear & redraw of the screen
|
||||
force_redraw = ["f"]
|
||||
|
||||
@@ -200,6 +202,17 @@ selected_filter_text = "black"
|
||||
highlight = "magenta"
|
||||
|
||||
|
||||
# The log search panel
|
||||
[colors.log_search]
|
||||
# Background color of panel
|
||||
background = "reset"
|
||||
# color of text
|
||||
text = "gray"
|
||||
# text color of the buttons text
|
||||
button_text = "black"
|
||||
# Highlighted text color
|
||||
highlight = "magenta"
|
||||
|
||||
# The color the of Docker commands available for each container
|
||||
[colors.commands]
|
||||
# Background color of panel
|
||||
|
||||
+56
-79
@@ -37,38 +37,33 @@ macro_rules! config_struct {
|
||||
optional_config_struct!(
|
||||
ConfigKeymap,
|
||||
clear,
|
||||
force_redraw,
|
||||
delete_deny,
|
||||
delete_confirm,
|
||||
delete_deny,
|
||||
exec,
|
||||
filter_mode,
|
||||
log_section_height_increase,
|
||||
log_section_height_decrease,
|
||||
log_section_toggle,
|
||||
log_scroll_forward,
|
||||
force_redraw,
|
||||
log_scroll_back,
|
||||
log_scroll_forward,
|
||||
log_search_mode,
|
||||
log_section_height_decrease,
|
||||
log_section_height_increase,
|
||||
log_section_toggle,
|
||||
quit,
|
||||
save_logs,
|
||||
// TODO remove in next release
|
||||
scroll_down_many,
|
||||
// TODO rename in next release
|
||||
scroll_down_one,
|
||||
scroll_down,
|
||||
scroll_end,
|
||||
scroll_start,
|
||||
// TODO remove in next release
|
||||
scroll_up_many,
|
||||
// TODO rename in next release
|
||||
scroll_up_one,
|
||||
scroll_up,
|
||||
select_next_panel,
|
||||
select_previous_panel,
|
||||
sort_by_name,
|
||||
sort_by_state,
|
||||
sort_by_status,
|
||||
sort_by_cpu,
|
||||
sort_by_memory,
|
||||
sort_by_id,
|
||||
sort_by_image,
|
||||
sort_by_memory,
|
||||
sort_by_name,
|
||||
sort_by_rx,
|
||||
sort_by_state,
|
||||
sort_by_status,
|
||||
sort_by_tx,
|
||||
sort_reset,
|
||||
toggle_help,
|
||||
@@ -78,38 +73,33 @@ optional_config_struct!(
|
||||
config_struct!(
|
||||
Keymap,
|
||||
clear,
|
||||
delete_deny,
|
||||
delete_confirm,
|
||||
delete_deny,
|
||||
exec,
|
||||
filter_mode,
|
||||
force_redraw,
|
||||
log_section_height_increase,
|
||||
log_section_height_decrease,
|
||||
log_section_toggle,
|
||||
log_scroll_forward,
|
||||
log_scroll_back,
|
||||
log_scroll_forward,
|
||||
log_search_mode,
|
||||
log_section_height_decrease,
|
||||
log_section_height_increase,
|
||||
log_section_toggle,
|
||||
quit,
|
||||
save_logs,
|
||||
// TODO remove in next release
|
||||
scroll_down_many,
|
||||
// TODO rename in next release
|
||||
scroll_down_one,
|
||||
scroll_down,
|
||||
scroll_end,
|
||||
scroll_start,
|
||||
// TODO remove in next release
|
||||
scroll_up_many,
|
||||
// TODO rename in next release
|
||||
scroll_up_one,
|
||||
scroll_up,
|
||||
select_next_panel,
|
||||
select_previous_panel,
|
||||
sort_by_name,
|
||||
sort_by_state,
|
||||
sort_by_status,
|
||||
sort_by_cpu,
|
||||
sort_by_memory,
|
||||
sort_by_id,
|
||||
sort_by_image,
|
||||
sort_by_memory,
|
||||
sort_by_name,
|
||||
sort_by_rx,
|
||||
sort_by_state,
|
||||
sort_by_status,
|
||||
sort_by_tx,
|
||||
sort_reset,
|
||||
toggle_help,
|
||||
@@ -125,24 +115,19 @@ impl Keymap {
|
||||
exec: (KeyCode::Char('e'), None),
|
||||
filter_mode: (KeyCode::Char('/'), Some(KeyCode::F(1))),
|
||||
force_redraw: (KeyCode::Char('f'), None),
|
||||
log_scroll_back: (KeyCode::Left, None),
|
||||
log_scroll_forward: (KeyCode::Right, None),
|
||||
log_search_mode: (KeyCode::Char('#'), None),
|
||||
log_section_height_decrease: (KeyCode::Char('-'), None),
|
||||
log_section_height_increase: (KeyCode::Char('='), None),
|
||||
log_section_toggle: (KeyCode::Char('\\'), None),
|
||||
log_scroll_back: (KeyCode::Left, None),
|
||||
log_scroll_forward: (KeyCode::Right, None),
|
||||
quit: (KeyCode::Char('q'), None),
|
||||
save_logs: (KeyCode::Char('s'), None),
|
||||
// TODO remove in next release
|
||||
scroll_down_many: (KeyCode::PageDown, None),
|
||||
// TODO rename in next release
|
||||
scroll_down_one: (KeyCode::Down, Some(KeyCode::Char('j'))),
|
||||
scroll_down: (KeyCode::Down, Some(KeyCode::Char('j'))),
|
||||
scroll_end: (KeyCode::End, None),
|
||||
scroll_start: (KeyCode::Home, None),
|
||||
scroll_many: KeyModifiers::CONTROL,
|
||||
// TODO remove in next release
|
||||
scroll_up_many: (KeyCode::PageUp, None),
|
||||
// TODO rename in next release
|
||||
scroll_up_one: (KeyCode::Up, Some(KeyCode::Char('k'))),
|
||||
scroll_start: (KeyCode::Home, None),
|
||||
scroll_up: (KeyCode::Up, Some(KeyCode::Char('k'))),
|
||||
select_next_panel: (KeyCode::Tab, None),
|
||||
select_previous_panel: (KeyCode::BackTab, None),
|
||||
sort_by_cpu: (KeyCode::Char('4'), None),
|
||||
@@ -216,16 +201,11 @@ impl From<Option<ConfigKeymap>> for Keymap {
|
||||
update_keymap(ck.force_redraw, &mut keymap.force_redraw, &mut clash);
|
||||
update_keymap(ck.quit, &mut keymap.quit, &mut clash);
|
||||
update_keymap(ck.save_logs, &mut keymap.save_logs, &mut clash);
|
||||
update_keymap(
|
||||
ck.scroll_down_many,
|
||||
&mut keymap.scroll_down_many,
|
||||
&mut clash,
|
||||
);
|
||||
update_keymap(ck.scroll_down_one, &mut keymap.scroll_down_one, &mut clash);
|
||||
update_keymap(ck.scroll_down, &mut keymap.scroll_down, &mut clash);
|
||||
update_keymap(ck.scroll_end, &mut keymap.scroll_end, &mut clash);
|
||||
update_keymap(ck.scroll_start, &mut keymap.scroll_start, &mut clash);
|
||||
update_keymap(ck.scroll_up_many, &mut keymap.scroll_up_many, &mut clash);
|
||||
update_keymap(ck.scroll_up_one, &mut keymap.scroll_up_one, &mut clash);
|
||||
update_keymap(ck.scroll_up, &mut keymap.scroll_up, &mut clash);
|
||||
update_keymap(ck.log_search_mode, &mut keymap.log_search_mode, &mut clash);
|
||||
update_keymap(
|
||||
ck.log_scroll_forward,
|
||||
&mut keymap.log_scroll_forward,
|
||||
@@ -416,19 +396,18 @@ mod tests {
|
||||
filter_mode: None,
|
||||
force_redraw: None,
|
||||
log_scroll_back: None,
|
||||
log_search_mode: None,
|
||||
log_scroll_forward: None,
|
||||
log_section_height_decrease: None,
|
||||
log_section_height_increase: None,
|
||||
log_section_toggle: None,
|
||||
quit: None,
|
||||
save_logs: None,
|
||||
scroll_down_many: None,
|
||||
scroll_down_one: None,
|
||||
scroll_down: None,
|
||||
scroll_end: None,
|
||||
scroll_start: None,
|
||||
scroll_many: None,
|
||||
scroll_up_many: None,
|
||||
scroll_up_one: None,
|
||||
scroll_up: None,
|
||||
select_next_panel: None,
|
||||
select_previous_panel: None,
|
||||
sort_by_cpu: None,
|
||||
@@ -458,24 +437,23 @@ mod tests {
|
||||
let input = ConfigKeymap {
|
||||
clear: gen_v(("a", "b")),
|
||||
delete_confirm: gen_v(("c", "d")),
|
||||
delete_deny: gen_v(("e", "fd")),
|
||||
delete_deny: gen_v(("e", "f")),
|
||||
exec: gen_v(("g", "h")),
|
||||
filter_mode: gen_v(("i", "j")),
|
||||
force_redraw: gen_v(("k", "l")),
|
||||
log_scroll_back: gen_v(("s", "t")),
|
||||
log_scroll_forward: gen_v(("q", "r")),
|
||||
log_search_mode: gen_v(("1", "2")),
|
||||
log_section_height_decrease: gen_v(("m", "n")),
|
||||
log_section_height_increase: gen_v(("o", "p")),
|
||||
log_scroll_forward: gen_v(("q", "r")),
|
||||
log_scroll_back: gen_v(("s", "t")),
|
||||
log_section_toggle: gen_v(("u", "v")),
|
||||
quit: gen_v(("w", "x")),
|
||||
save_logs: gen_v(("y", "z")),
|
||||
scroll_down_many: gen_v(("1", "2")),
|
||||
scroll_down_one: gen_v(("3", "4")),
|
||||
scroll_down: gen_v(("3", "4")),
|
||||
scroll_end: gen_v(("5", "6")),
|
||||
scroll_many: Some(vec!["alt".to_owned()]),
|
||||
scroll_start: gen_v(("7", "8")),
|
||||
scroll_up_many: gen_v(("9", "0")),
|
||||
scroll_up_one: gen_v(("F1", "F2")),
|
||||
scroll_up: gen_v(("F1", "F2")),
|
||||
select_next_panel: gen_v(("F3", "F4")),
|
||||
select_previous_panel: gen_v(("F5", "F6")),
|
||||
sort_by_cpu: gen_v(("F7", "F8")),
|
||||
@@ -496,39 +474,38 @@ mod tests {
|
||||
|
||||
let expected = Keymap {
|
||||
clear: (KeyCode::Char('a'), Some(KeyCode::Char('b'))),
|
||||
delete_deny: (KeyCode::Char('e'), None),
|
||||
delete_confirm: (KeyCode::Char('c'), Some(KeyCode::Char('d'))),
|
||||
delete_deny: (KeyCode::Char('e'), Some(KeyCode::Char('f'))),
|
||||
exec: (KeyCode::Char('g'), Some(KeyCode::Char('h'))),
|
||||
filter_mode: (KeyCode::Char('i'), Some(KeyCode::Char('j'))),
|
||||
force_redraw: (KeyCode::Char('k'), Some(KeyCode::Char('l'))),
|
||||
log_section_height_increase: (KeyCode::Char('o'), Some(KeyCode::Char('p'))),
|
||||
log_section_height_decrease: (KeyCode::Char('m'), Some(KeyCode::Char('n'))),
|
||||
log_section_toggle: (KeyCode::Char('u'), Some(KeyCode::Char('v'))),
|
||||
log_scroll_forward: (KeyCode::Char('q'), Some(KeyCode::Char('r'))),
|
||||
log_scroll_back: (KeyCode::Char('s'), Some(KeyCode::Char('t'))),
|
||||
log_scroll_forward: (KeyCode::Char('q'), Some(KeyCode::Char('r'))),
|
||||
log_search_mode: (KeyCode::Char('1'), Some(KeyCode::Char('2'))),
|
||||
log_section_height_decrease: (KeyCode::Char('m'), Some(KeyCode::Char('n'))),
|
||||
log_section_height_increase: (KeyCode::Char('o'), Some(KeyCode::Char('p'))),
|
||||
log_section_toggle: (KeyCode::Char('u'), Some(KeyCode::Char('v'))),
|
||||
quit: (KeyCode::Char('w'), Some(KeyCode::Char('x'))),
|
||||
save_logs: (KeyCode::Char('y'), Some(KeyCode::Char('z'))),
|
||||
scroll_down_many: (KeyCode::Char('1'), Some(KeyCode::Char('2'))),
|
||||
scroll_down_one: (KeyCode::Char('3'), Some(KeyCode::Char('4'))),
|
||||
scroll_down: (KeyCode::Char('3'), Some(KeyCode::Char('4'))),
|
||||
scroll_end: (KeyCode::Char('5'), Some(KeyCode::Char('6'))),
|
||||
scroll_many: KeyModifiers::ALT,
|
||||
scroll_start: (KeyCode::Char('7'), Some(KeyCode::Char('8'))),
|
||||
scroll_up_many: (KeyCode::Char('9'), Some(KeyCode::Char('0'))),
|
||||
scroll_up_one: (KeyCode::F(1), Some(KeyCode::F(2))),
|
||||
scroll_up: (KeyCode::F(1), Some(KeyCode::F(2))),
|
||||
select_next_panel: (KeyCode::F(3), Some(KeyCode::F(4))),
|
||||
select_previous_panel: (KeyCode::F(5), Some(KeyCode::F(6))),
|
||||
sort_by_name: (KeyCode::Up, Some(KeyCode::Down)),
|
||||
sort_by_state: (KeyCode::Char('['), Some(KeyCode::Char(']'))),
|
||||
sort_by_status: (KeyCode::Tab, None),
|
||||
sort_by_cpu: (KeyCode::F(7), Some(KeyCode::F(8))),
|
||||
sort_by_memory: (KeyCode::Home, Some(KeyCode::End)),
|
||||
sort_by_id: (KeyCode::F(9), Some(KeyCode::F(10))),
|
||||
sort_by_image: (KeyCode::F(11), Some(KeyCode::F(12))),
|
||||
sort_by_memory: (KeyCode::Home, Some(KeyCode::End)),
|
||||
sort_by_name: (KeyCode::Up, Some(KeyCode::Down)),
|
||||
sort_by_rx: (KeyCode::Left, Some(KeyCode::Right)),
|
||||
sort_by_state: (KeyCode::Char('['), Some(KeyCode::Char(']'))),
|
||||
sort_by_status: (KeyCode::Tab, None),
|
||||
sort_by_tx: (KeyCode::PageDown, Some(KeyCode::PageUp)),
|
||||
sort_reset: (KeyCode::Char(','), Some(KeyCode::Char('.'))),
|
||||
toggle_help: (KeyCode::Char('-'), Some(KeyCode::Char('='))),
|
||||
toggle_mouse_capture: (KeyCode::Char('\\'), Some(KeyCode::Char('/'))),
|
||||
scroll_many: KeyModifiers::ALT,
|
||||
};
|
||||
assert_eq!(expected, result);
|
||||
}
|
||||
|
||||
+12
-6
@@ -13,6 +13,9 @@ pub use {color_parser::AppColors, keymap_parser::Keymap};
|
||||
mod parse_args;
|
||||
mod parse_config_file;
|
||||
|
||||
// TODO use a global pub static oncelock for the config
|
||||
// static CELL: OnceLock<usize> = OnceLock::new();
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[allow(clippy::struct_excessive_bools)]
|
||||
pub struct Config {
|
||||
@@ -23,14 +26,15 @@ pub struct Config {
|
||||
pub host: Option<String>,
|
||||
pub in_container: bool,
|
||||
pub keymap: Keymap,
|
||||
pub log_search_case_sensitive: bool,
|
||||
pub raw_logs: bool,
|
||||
pub save_dir: Option<PathBuf>,
|
||||
pub show_logs: bool,
|
||||
pub show_self: bool,
|
||||
pub show_std_err: bool,
|
||||
pub show_timestamp: bool,
|
||||
pub timezone: Option<TimeZone>,
|
||||
pub timestamp_format: String,
|
||||
pub show_logs: bool,
|
||||
pub timezone: Option<TimeZone>,
|
||||
pub use_cli: bool,
|
||||
}
|
||||
|
||||
@@ -44,15 +48,16 @@ impl From<&Args> for Config {
|
||||
host: args.host.clone(),
|
||||
in_container: Self::check_if_in_container(),
|
||||
keymap: Keymap::new(),
|
||||
log_search_case_sensitive: true,
|
||||
raw_logs: args.raw,
|
||||
save_dir: Self::try_get_logs_dir(args.save_dir.as_ref()),
|
||||
show_logs: true,
|
||||
show_self: !args.show_self,
|
||||
show_std_err: !args.no_std_err,
|
||||
show_timestamp: !args.timestamp,
|
||||
timezone: Self::parse_timezone(args.timezone.clone()),
|
||||
timestamp_format: Self::parse_timestamp_format(None),
|
||||
timezone: Self::parse_timezone(args.timezone.clone()),
|
||||
use_cli: args.use_cli,
|
||||
show_logs: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -67,15 +72,16 @@ impl From<ConfigFile> for Config {
|
||||
host: config_file.host,
|
||||
in_container: Self::check_if_in_container(),
|
||||
keymap: Keymap::from(config_file.keymap),
|
||||
log_search_case_sensitive: config_file.log_search_case_sensitive.unwrap_or(true),
|
||||
raw_logs: config_file.raw_logs.unwrap_or(false),
|
||||
save_dir: Self::try_get_logs_dir(config_file.save_dir.as_ref()),
|
||||
show_logs: config_file.show_logs.unwrap_or(true),
|
||||
show_self: config_file.show_self.unwrap_or(false),
|
||||
show_std_err: config_file.show_std_err.unwrap_or(true),
|
||||
show_timestamp: config_file.show_timestamp.unwrap_or(true),
|
||||
timezone: Self::parse_timezone(config_file.timezone),
|
||||
timestamp_format: Self::parse_timestamp_format(config_file.timestamp_format),
|
||||
timezone: Self::parse_timezone(config_file.timezone),
|
||||
use_cli: config_file.use_cli.unwrap_or(false),
|
||||
show_logs: config_file.show_logs.unwrap_or(true),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,15 +67,16 @@ pub struct ConfigFile {
|
||||
pub gui: Option<bool>,
|
||||
pub host: Option<String>,
|
||||
pub keymap: Option<ConfigKeymap>,
|
||||
pub log_search_case_sensitive: Option<bool>,
|
||||
pub raw_logs: Option<bool>,
|
||||
pub save_dir: Option<String>,
|
||||
pub show_logs: Option<bool>,
|
||||
pub show_self: Option<bool>,
|
||||
pub show_std_err: Option<bool>,
|
||||
pub show_timestamp: Option<bool>,
|
||||
pub timestamp_format: Option<String>,
|
||||
pub timezone: Option<String>,
|
||||
pub use_cli: Option<bool>,
|
||||
pub show_logs: Option<bool>,
|
||||
}
|
||||
|
||||
impl ConfigFile {
|
||||
|
||||
+110
-74
@@ -19,7 +19,7 @@ use uuid::Uuid;
|
||||
|
||||
mod message;
|
||||
use crate::{
|
||||
app_data::{AppData, DockerCommand, Header},
|
||||
app_data::{AppData, DockerCommand, Header, ScrollDirection},
|
||||
app_error::AppError,
|
||||
config,
|
||||
docker_data::DockerMessage,
|
||||
@@ -74,10 +74,12 @@ impl InputHandler {
|
||||
if contains(Status::DeleteConfirm) {
|
||||
self.button_intersect(mouse_event).await;
|
||||
} else if !contains(Status::Error)
|
||||
| !contains(Status::Help)
|
||||
| !contains(Status::DeleteConfirm)
|
||||
| !contains(Status::Filter)
|
||||
&& !contains(Status::Help)
|
||||
&& !contains(Status::DeleteConfirm)
|
||||
&& !contains(Status::Filter)
|
||||
&& !contains(Status::SearchLogs)
|
||||
{
|
||||
// TODO handle state where you want to scroll log search results with the mouse wheel
|
||||
self.mouse_press(mouse_event, modifider);
|
||||
}
|
||||
}
|
||||
@@ -294,23 +296,12 @@ impl InputHandler {
|
||||
}
|
||||
}
|
||||
|
||||
/// Advance the "cursor" along the logs
|
||||
fn logs_forward(&self, modifier: KeyModifiers) {
|
||||
fn logs_horizontal_scroll(&self, modifier: KeyModifiers, sd: &ScrollDirection) {
|
||||
let panel = self.gui_state.lock().get_selected_panel();
|
||||
if panel == SelectablePanel::Logs {
|
||||
for _ in 0..self.get_modifier_total(modifier) {
|
||||
let width = self.gui_state.lock().get_screen_width();
|
||||
self.app_data.lock().log_forward(width);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Retreat the "cursor" along the logs
|
||||
fn logs_back(&self, modifier: KeyModifiers) {
|
||||
let panel = self.gui_state.lock().get_selected_panel();
|
||||
if panel == SelectablePanel::Logs {
|
||||
for _ in 0..self.get_modifier_total(modifier) {
|
||||
self.app_data.lock().log_back();
|
||||
self.app_data.lock().logs_horizontal_scroll(sd, width);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -388,6 +379,66 @@ impl InputHandler {
|
||||
}
|
||||
}
|
||||
|
||||
/// Actions to take when Filter status active
|
||||
fn handle_search_logs(&self, key_code: KeyCode, modifier: KeyModifiers) {
|
||||
match key_code {
|
||||
KeyCode::Esc => {
|
||||
self.app_data.lock().logs_search_clear();
|
||||
self.gui_state.lock().status_del(Status::SearchLogs);
|
||||
}
|
||||
_ if KeyCode::Enter == key_code
|
||||
|| self.keymap.log_search_mode.0 == key_code
|
||||
|| self.keymap.log_search_mode.1 == Some(key_code) =>
|
||||
{
|
||||
self.gui_state.lock().status_del(Status::SearchLogs);
|
||||
}
|
||||
|
||||
_ if self.keymap.log_scroll_back.0 == key_code
|
||||
|| self.keymap.log_scroll_back.1 == Some(key_code) =>
|
||||
{
|
||||
self.logs_horizontal_scroll(modifier, &ScrollDirection::Previous);
|
||||
}
|
||||
|
||||
_ if self.keymap.log_scroll_forward.0 == key_code
|
||||
|| self.keymap.log_scroll_forward.1 == Some(key_code) =>
|
||||
{
|
||||
self.logs_horizontal_scroll(modifier, &ScrollDirection::Next);
|
||||
}
|
||||
|
||||
_ if self.keymap.scroll_down.0 == key_code => {
|
||||
self.app_data
|
||||
.lock()
|
||||
.log_search_scroll(&ScrollDirection::Next);
|
||||
// TODO should only do this is log_search_scroll returns some
|
||||
// Need to wait til app_data and gui_data is combined
|
||||
self.gui_state
|
||||
.lock()
|
||||
.set_logs_panel_selected(&self.app_data);
|
||||
//
|
||||
}
|
||||
|
||||
_ if self.keymap.scroll_up.0 == key_code => {
|
||||
self.app_data
|
||||
.lock()
|
||||
.log_search_scroll(&ScrollDirection::Previous);
|
||||
// TODO should only do this is log_search_scroll returns some
|
||||
// Need to wait til app_data and gui_data is combined
|
||||
self.gui_state
|
||||
.lock()
|
||||
.set_logs_panel_selected(&self.app_data);
|
||||
}
|
||||
|
||||
// handle up and down keys
|
||||
KeyCode::Backspace => {
|
||||
self.app_data.lock().log_search_pop();
|
||||
}
|
||||
KeyCode::Char(x) => {
|
||||
self.app_data.lock().log_search_push(x);
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
/// Actions to take when Filter status active
|
||||
fn handle_filter(&self, key_code: KeyCode) {
|
||||
match key_code {
|
||||
@@ -569,32 +620,16 @@ impl InputHandler {
|
||||
self.scroll_end_key();
|
||||
}
|
||||
|
||||
_ if self.keymap.scroll_up_one.0 == key_code
|
||||
|| self.keymap.scroll_up_one.1 == Some(key_code) =>
|
||||
_ if self.keymap.scroll_up.0 == key_code
|
||||
|| self.keymap.scroll_up.1 == Some(key_code) =>
|
||||
{
|
||||
self.scroll_up(modifier);
|
||||
self.scroll(modifier, &ScrollDirection::Previous);
|
||||
}
|
||||
|
||||
_ if self.keymap.scroll_up_many.0 == key_code
|
||||
|| self.keymap.scroll_up_many.1 == Some(key_code) =>
|
||||
_ if self.keymap.scroll_down.0 == key_code
|
||||
|| self.keymap.scroll_down.1 == Some(key_code) =>
|
||||
{
|
||||
for _ in 0..=6 {
|
||||
self.scroll_up(modifier);
|
||||
}
|
||||
}
|
||||
|
||||
_ if self.keymap.scroll_down_one.0 == key_code
|
||||
|| self.keymap.scroll_down_one.1 == Some(key_code) =>
|
||||
{
|
||||
self.scroll_down(modifier);
|
||||
}
|
||||
|
||||
_ if self.keymap.scroll_down_many.0 == key_code
|
||||
|| self.keymap.scroll_down_many.1 == Some(key_code) =>
|
||||
{
|
||||
for _ in 0..=6 {
|
||||
self.scroll_down(modifier);
|
||||
}
|
||||
self.scroll(modifier, &ScrollDirection::Next);
|
||||
}
|
||||
|
||||
_ if self.keymap.filter_mode.0 == key_code
|
||||
@@ -604,16 +639,27 @@ impl InputHandler {
|
||||
self.docker_tx.send(DockerMessage::Update).await.ok();
|
||||
}
|
||||
|
||||
_ if self.keymap.log_search_mode.0 == key_code
|
||||
|| self.keymap.log_search_mode.1 == Some(key_code) =>
|
||||
{
|
||||
if !self.gui_state.lock().get_show_logs() {
|
||||
self.gui_state.lock().toggle_show_logs();
|
||||
}
|
||||
self.gui_state.lock().status_push(Status::SearchLogs);
|
||||
}
|
||||
|
||||
_ if self.keymap.log_scroll_back.0 == key_code
|
||||
|| self.keymap.log_scroll_back.1 == Some(key_code) =>
|
||||
{
|
||||
self.logs_back(modifier);
|
||||
self.logs_horizontal_scroll(modifier, &ScrollDirection::Previous);
|
||||
// self.logs_back(modifier);
|
||||
}
|
||||
|
||||
_ if self.keymap.log_scroll_forward.0 == key_code
|
||||
|| self.keymap.log_scroll_forward.1 == Some(key_code) =>
|
||||
{
|
||||
self.logs_forward(modifier);
|
||||
self.logs_horizontal_scroll(modifier, &ScrollDirection::Next);
|
||||
// self.logs_forward(modifier);
|
||||
}
|
||||
|
||||
KeyCode::Enter => self.enter_key().await,
|
||||
@@ -631,13 +677,14 @@ impl InputHandler {
|
||||
let contains_exec = contains(Status::Exec);
|
||||
let contains_filter = contains(Status::Filter);
|
||||
let contains_delete = contains(Status::DeleteConfirm);
|
||||
let contains_search_logs = contains(Status::SearchLogs);
|
||||
|
||||
if !contains_exec {
|
||||
let is_q = || key_code == self.keymap.quit.0 || Some(key_code) == self.keymap.quit.1;
|
||||
if key_modifier == KeyModifiers::CONTROL && key_code == KeyCode::Char('c')
|
||||
|| is_q() && !contains_filter
|
||||
|| is_q() && !contains_filter && !contains_search_logs
|
||||
{
|
||||
// Always just quit on Ctrl + c/C or q/Q, unless in Filter status active
|
||||
// Always just quit on Ctrl + c/C or q/Q, unless in filter/search_logs mode, i.e. when user inmput can include the q key
|
||||
self.quit();
|
||||
}
|
||||
|
||||
@@ -647,6 +694,8 @@ impl InputHandler {
|
||||
self.handle_help(key_code);
|
||||
} else if contains_filter {
|
||||
self.handle_filter(key_code);
|
||||
} else if contains_search_logs {
|
||||
self.handle_search_logs(key_code, key_modifier);
|
||||
} else if contains_delete {
|
||||
self.handle_delete(key_code).await;
|
||||
} else {
|
||||
@@ -685,8 +734,8 @@ impl InputHandler {
|
||||
}
|
||||
} else {
|
||||
match mouse_event.kind {
|
||||
MouseEventKind::ScrollUp => self.scroll_up(modifier),
|
||||
MouseEventKind::ScrollDown => self.scroll_down(modifier),
|
||||
MouseEventKind::ScrollUp => self.scroll(modifier, &ScrollDirection::Previous),
|
||||
MouseEventKind::ScrollDown => self.scroll(modifier, &ScrollDirection::Next),
|
||||
MouseEventKind::Down(MouseButton::Left) => {
|
||||
let mouse_point = Rect::new(mouse_event.column, mouse_event.row, 1, 1);
|
||||
let header = self.gui_state.lock().get_intersect_header(mouse_point);
|
||||
@@ -706,38 +755,25 @@ impl InputHandler {
|
||||
}
|
||||
|
||||
/// Change state to next, depending which panel is currently in focus
|
||||
fn scroll_down(&self, modifier: KeyModifiers) {
|
||||
let selected_panel = self.gui_state.lock().get_selected_panel();
|
||||
match selected_panel {
|
||||
SelectablePanel::Containers => {
|
||||
for _ in 0..self.get_modifier_total(modifier) {
|
||||
self.app_data.lock().containers_next();
|
||||
fn scroll(&self, modifier: KeyModifiers, scroll: &ScrollDirection) {
|
||||
let status = self.gui_state.lock().get_status();
|
||||
if status.contains(&Status::SearchLogs) {
|
||||
self.app_data.lock().log_search_scroll(scroll);
|
||||
} else {
|
||||
let selected_panel = self.gui_state.lock().get_selected_panel();
|
||||
match selected_panel {
|
||||
SelectablePanel::Containers => {
|
||||
for _ in 0..self.get_modifier_total(modifier) {
|
||||
self.app_data.lock().containers_scroll(scroll);
|
||||
}
|
||||
}
|
||||
}
|
||||
SelectablePanel::Logs => {
|
||||
for _ in 0..self.get_modifier_total(modifier) {
|
||||
self.app_data.lock().log_next();
|
||||
SelectablePanel::Logs => {
|
||||
for _ in 0..self.get_modifier_total(modifier) {
|
||||
self.app_data.lock().log_scroll(scroll);
|
||||
}
|
||||
}
|
||||
SelectablePanel::Commands => self.app_data.lock().docker_controls_scroll(scroll),
|
||||
}
|
||||
SelectablePanel::Commands => self.app_data.lock().docker_controls_next(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Change state to previous, depending which panel is currently in focus
|
||||
fn scroll_up(&self, modifier: KeyModifiers) {
|
||||
let selected_panel = self.gui_state.lock().get_selected_panel();
|
||||
match selected_panel {
|
||||
SelectablePanel::Containers => {
|
||||
for _ in 0..self.get_modifier_total(modifier) {
|
||||
self.app_data.lock().containers_previous();
|
||||
}
|
||||
}
|
||||
SelectablePanel::Logs => {
|
||||
for _ in 0..self.get_modifier_total(modifier) {
|
||||
self.app_data.lock().log_previous();
|
||||
}
|
||||
}
|
||||
SelectablePanel::Commands => self.app_data.lock().docker_controls_previous(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#![allow(clippy::collapsible_if)]
|
||||
// #![allow(unused)]
|
||||
// Zigbuild is stuck on 1.87.0, which means Mac builds won't work when using collapsible ifs
|
||||
|
||||
use app_data::AppData;
|
||||
@@ -175,6 +176,7 @@ mod tests {
|
||||
show_std_err: false,
|
||||
in_container: false,
|
||||
save_dir: None,
|
||||
log_search_case_sensitive: true,
|
||||
raw_logs: false,
|
||||
show_self: false,
|
||||
app_colors: AppColors::new(),
|
||||
|
||||
@@ -59,6 +59,7 @@ mod tests {
|
||||
use ratatui::style::{Color, Modifier};
|
||||
|
||||
use crate::{
|
||||
app_data::ScrollDirection,
|
||||
config::AppColors,
|
||||
tests::gen_container_summary,
|
||||
ui::{
|
||||
@@ -169,7 +170,10 @@ mod tests {
|
||||
.app_data
|
||||
.lock()
|
||||
.update_containers(vec![gen_container_summary(1, "paused")]);
|
||||
setup.app_data.lock().docker_controls_next();
|
||||
setup
|
||||
.app_data
|
||||
.lock()
|
||||
.docker_controls_scroll(&ScrollDirection::Next);
|
||||
|
||||
setup
|
||||
.terminal
|
||||
@@ -363,7 +367,10 @@ mod tests {
|
||||
.app_data
|
||||
.lock()
|
||||
.update_containers(vec![gen_container_summary(1, "paused")]);
|
||||
setup.app_data.lock().docker_controls_next();
|
||||
setup
|
||||
.app_data
|
||||
.lock()
|
||||
.docker_controls_scroll(&ScrollDirection::Next);
|
||||
|
||||
setup
|
||||
.terminal
|
||||
|
||||
@@ -52,7 +52,7 @@ pub fn draw(area: Rect, colors: AppColors, frame: &mut Frame, fd: &FrameData) {
|
||||
line.extend_from_slice(&filter_by_spans(colors, fd));
|
||||
line.extend_from_slice(&[
|
||||
Span::styled(
|
||||
" term: ",
|
||||
" filter term: ",
|
||||
Style::default()
|
||||
.fg(colors.filter.highlight)
|
||||
.add_modifier(Modifier::BOLD),
|
||||
@@ -116,7 +116,7 @@ mod tests {
|
||||
assert_eq!(result_cell.bg, Color::Gray);
|
||||
assert_eq!(result_cell.fg, Color::Black);
|
||||
}
|
||||
47..=53 => {
|
||||
47..=60 => {
|
||||
assert_eq!(result_cell.bg, Color::Reset);
|
||||
assert_eq!(result_cell.fg, Color::Magenta);
|
||||
assert_eq!(result_cell.modifier, Modifier::BOLD);
|
||||
@@ -166,7 +166,7 @@ mod tests {
|
||||
assert_eq!(result_cell.bg, Color::Magenta);
|
||||
assert_eq!(result_cell.fg, Color::Black);
|
||||
}
|
||||
5..=11 | 27..=46 | 54..=55 => {
|
||||
5..=11 | 27..=46 | 61..=62 => {
|
||||
assert_eq!(result_cell.bg, Color::Reset);
|
||||
assert_eq!(result_cell.fg, Color::Gray);
|
||||
}
|
||||
@@ -174,7 +174,7 @@ mod tests {
|
||||
assert_eq!(result_cell.bg, Color::Gray);
|
||||
assert_eq!(result_cell.fg, Color::Black);
|
||||
}
|
||||
47..=53 => {
|
||||
47..=60 => {
|
||||
assert_eq!(result_cell.bg, Color::Reset);
|
||||
assert_eq!(result_cell.fg, Color::Magenta);
|
||||
assert_eq!(result_cell.modifier, Modifier::BOLD);
|
||||
@@ -222,7 +222,7 @@ mod tests {
|
||||
assert_eq!(result_cell.bg, Color::Gray);
|
||||
assert_eq!(result_cell.fg, Color::Black);
|
||||
}
|
||||
47..=53 => {
|
||||
47..=60 => {
|
||||
assert_eq!(result_cell.bg, Color::Reset);
|
||||
assert_eq!(result_cell.fg, Color::Magenta);
|
||||
assert_eq!(result_cell.modifier, Modifier::BOLD);
|
||||
@@ -273,7 +273,7 @@ mod tests {
|
||||
assert_eq!(result_cell.bg, Color::Blue);
|
||||
assert_eq!(result_cell.fg, Color::Yellow);
|
||||
}
|
||||
5..=11 | 27..=46 | 54..=55 => {
|
||||
5..=11 | 27..=46 | 61..=62 => {
|
||||
assert_eq!(result_cell.bg, Color::White);
|
||||
assert_eq!(result_cell.fg, Color::Magenta);
|
||||
}
|
||||
@@ -281,7 +281,7 @@ mod tests {
|
||||
assert_eq!(result_cell.bg, Color::Red);
|
||||
assert_eq!(result_cell.fg, Color::Yellow);
|
||||
}
|
||||
47..=53 => {
|
||||
47..=60 => {
|
||||
assert_eq!(result_cell.bg, Color::White);
|
||||
assert_eq!(result_cell.fg, Color::Blue);
|
||||
assert_eq!(result_cell.modifier, Modifier::BOLD);
|
||||
|
||||
+42
-60
@@ -106,8 +106,6 @@ impl HelpInfo {
|
||||
or(),
|
||||
button_item("j k"),
|
||||
or(),
|
||||
button_item("PgUp PgDown"),
|
||||
or(),
|
||||
button_item("Home End"),
|
||||
button_desc("scroll vertically"),
|
||||
]),
|
||||
@@ -119,7 +117,7 @@ impl HelpInfo {
|
||||
Line::from(vec![
|
||||
space(),
|
||||
button_item("ctrl"),
|
||||
button_desc("increase scroll speed, used in conjuction scroll keys"),
|
||||
button_desc("increase scroll speed, used in conjunction scroll keys"),
|
||||
]),
|
||||
Line::from(vec![
|
||||
space(),
|
||||
@@ -162,6 +160,11 @@ impl HelpInfo {
|
||||
button_item("/"),
|
||||
button_desc("enter filter mode"),
|
||||
]),
|
||||
Line::from(vec![
|
||||
space(),
|
||||
button_item("#"),
|
||||
button_desc("enter log search mode"),
|
||||
]),
|
||||
Line::from(vec![space(), button_item("0"), button_desc("stop sort")]),
|
||||
Line::from(vec![
|
||||
space(),
|
||||
@@ -277,10 +280,8 @@ impl HelpInfo {
|
||||
let descriptions = [
|
||||
or_secondary(km.select_next_panel, "select next panel"),
|
||||
or_secondary(km.select_previous_panel, "select previous panel"),
|
||||
or_secondary(km.scroll_down_one, "scroll list down by one"),
|
||||
or_secondary(km.scroll_up_one, "scroll list up by one"),
|
||||
or_secondary(km.scroll_down_many, "scroll list down by many"),
|
||||
or_secondary(km.scroll_up_many, "scroll list by up many"),
|
||||
or_secondary(km.scroll_down, "scroll list down by one"),
|
||||
or_secondary(km.scroll_up, "scroll list up by one"),
|
||||
or_secondary(km.scroll_end, "scroll list to end"),
|
||||
or_secondary(km.scroll_start, "scroll list to start"),
|
||||
or_secondary(km.log_scroll_forward, "horizontal scroll logs right"),
|
||||
@@ -288,7 +289,7 @@ impl HelpInfo {
|
||||
Line::from(vec![
|
||||
space(),
|
||||
button_item(km.scroll_many.to_string().as_str()),
|
||||
button_desc("increase scroll speed, used in conjuction scroll keys"),
|
||||
button_desc("increase scroll speed, used in conjunction scroll keys"),
|
||||
]),
|
||||
Line::from(vec![
|
||||
space(),
|
||||
@@ -310,6 +311,7 @@ impl HelpInfo {
|
||||
"toggle mouse capture - if disabled, text on screen can be selected & copied",
|
||||
),
|
||||
or_secondary(km.filter_mode, "enter filter mode"),
|
||||
or_secondary(km.log_search_mode, "enter log search mode"),
|
||||
or_secondary(km.sort_reset, "reset container sorting"),
|
||||
or_secondary(km.sort_by_name, "sort containers by name"),
|
||||
or_secondary(km.sort_by_state, "sort containers by state"),
|
||||
@@ -462,7 +464,7 @@ mod tests {
|
||||
/// This test is incredibly annoying
|
||||
/// println!("{} {} {} {} {}", row_index, result_cell_index, result_cell.symbol(), result_cell.bg, result_cell.fg);
|
||||
fn test_draw_blocks_help() {
|
||||
let mut setup = test_setup(87, 37, true, true);
|
||||
let mut setup = test_setup(87, 39, true, true);
|
||||
let tz = setup.app_data.lock().config.timezone.clone();
|
||||
|
||||
setup
|
||||
@@ -482,45 +484,32 @@ mod tests {
|
||||
|
||||
for (row_index, result_row) in get_result(&setup) {
|
||||
for (result_cell_index, result_cell) in result_row.iter().enumerate() {
|
||||
println!(
|
||||
"{} {} {} {} {}",
|
||||
row_index,
|
||||
result_cell_index,
|
||||
result_cell.symbol(),
|
||||
result_cell.bg,
|
||||
result_cell.fg
|
||||
);
|
||||
match (row_index, result_cell_index) {
|
||||
// first & last row, and first & last char on each row, is reset/reset, making sure that the help info is centered in the given area
|
||||
(0 | 36, _) | (0..=35, 0 | 86) => {
|
||||
(0 | 38, _) | (0..=37, 0 | 86) => {
|
||||
assert_eq!(result_cell.bg, Color::Reset);
|
||||
assert_eq!(result_cell.fg, Color::Reset);
|
||||
}
|
||||
// border is red on black
|
||||
(1 | 34, _) | (1..=31, 1 | 85) => {
|
||||
assert_eq!(result_cell.bg, Color::Magenta);
|
||||
assert_eq!(result_cell.fg, Color::Black);
|
||||
}
|
||||
// Buttons
|
||||
(2..=10, 2..=85)
|
||||
(2..=10, 2..=84)
|
||||
| (12, 19..=66)
|
||||
| (14, 2..=10 | 13..=27)
|
||||
| (15, 2..=10 | 13..=21 | 24..=40 | 43..=56)
|
||||
| (16 | 27 | 29, 2..=10)
|
||||
| (15, 2..=10 | 13..=21 | 24..=37)
|
||||
| (16 | 28 | 30, 2..=10)
|
||||
| (19..=26 | 29 | 31, 2..=8)
|
||||
| (17, 2..=11)
|
||||
| (18 | 26, 2..=12)
|
||||
| (19 | 20 | 21 | 22 | 24 | 25 | 28 | 23 | 30, 2..=8)
|
||||
| (18 | 27, 2..=12)
|
||||
| (24, 2..=9 | 12..=18) => {
|
||||
assert_eq!(result_cell.bg, Color::Magenta);
|
||||
assert_eq!(result_cell.fg, Color::White);
|
||||
}
|
||||
// The URL is yellow and underlined
|
||||
(33, 25..=60) => {
|
||||
// The URL is white on yellow and underlined
|
||||
(34, 25..=60) => {
|
||||
assert_eq!(result_cell.bg, Color::Magenta);
|
||||
assert_eq!(result_cell.fg, Color::White);
|
||||
assert_eq!(result_cell.modifier, Modifier::UNDERLINED);
|
||||
}
|
||||
// The rest is red on black
|
||||
// The rest is black on magenta
|
||||
_ => {
|
||||
assert_eq!(result_cell.bg, Color::Magenta);
|
||||
assert_eq!(result_cell.fg, Color::Black);
|
||||
@@ -535,7 +524,7 @@ mod tests {
|
||||
/// This test is incredibly annoying
|
||||
/// println!("{} {} {} {} {}", row_index, result_cell_index, result_cell.symbol(), result_cell.bg, result_cell.fg);
|
||||
fn test_draw_blocks_help_custom_colors() {
|
||||
let mut setup = test_setup(87, 37, true, true);
|
||||
let mut setup = test_setup(87, 39, true, true);
|
||||
let mut colors = AppColors::new();
|
||||
let tz = setup.app_data.lock().config.timezone.clone();
|
||||
|
||||
@@ -561,35 +550,30 @@ mod tests {
|
||||
for (result_cell_index, result_cell) in result_row.iter().enumerate() {
|
||||
match (row_index, result_cell_index) {
|
||||
// first & last row, and first & last char on each row, is reset/reset, making sure that the help info is centered in the given area
|
||||
(0 | 36, _) | (0..=35, 0 | 86) => {
|
||||
(0 | 38, _) | (0..=37, 0 | 86) => {
|
||||
assert_eq!(result_cell.bg, Color::Reset);
|
||||
assert_eq!(result_cell.fg, Color::Reset);
|
||||
}
|
||||
// border is red on black
|
||||
(1 | 34, _) | (1..=31, 1 | 85) => {
|
||||
assert_eq!(result_cell.bg, Color::Black);
|
||||
assert_eq!(result_cell.fg, Color::Red);
|
||||
}
|
||||
// Buttons
|
||||
(2..=10, 2..=85)
|
||||
(2..=10, 2..=84)
|
||||
| (12, 19..=66)
|
||||
| (14, 2..=10 | 13..=27)
|
||||
| (15, 2..=10 | 13..=21 | 24..=40 | 43..=56)
|
||||
| (16 | 27 | 29, 2..=10)
|
||||
| (15, 2..=10 | 13..=21 | 24..=37)
|
||||
| (16 | 28 | 30, 2..=10)
|
||||
| (19..=26 | 29 | 31, 2..=8)
|
||||
| (17, 2..=11)
|
||||
| (18 | 26, 2..=12)
|
||||
| (19 | 20 | 21 | 22 | 24 | 25 | 28 | 23 | 30, 2..=8)
|
||||
| (18 | 27, 2..=12)
|
||||
| (24, 2..=9 | 12..=18) => {
|
||||
assert_eq!(result_cell.bg, Color::Black);
|
||||
assert_eq!(result_cell.fg, Color::Yellow);
|
||||
}
|
||||
// The URL is yellow and underlined
|
||||
(33, 25..=60) => {
|
||||
// The URL is white on yellow and underlined
|
||||
(34, 25..=60) => {
|
||||
assert_eq!(result_cell.bg, Color::Black);
|
||||
assert_eq!(result_cell.fg, Color::Yellow);
|
||||
assert_eq!(result_cell.modifier, Modifier::UNDERLINED);
|
||||
}
|
||||
// The rest is red on black
|
||||
// The rest is black on magenta
|
||||
_ => {
|
||||
assert_eq!(result_cell.bg, Color::Black);
|
||||
assert_eq!(result_cell.fg, Color::Red);
|
||||
@@ -610,6 +594,7 @@ mod tests {
|
||||
delete_deny: (KeyCode::Char('c'), None),
|
||||
exec: (KeyCode::Char('d'), None),
|
||||
filter_mode: (KeyCode::Char('e'), None),
|
||||
log_search_mode: (KeyCode::Char('7'), None),
|
||||
force_redraw: (KeyCode::Char('f'), None),
|
||||
log_scroll_back: (KeyCode::Char('g'), None),
|
||||
log_scroll_forward: (KeyCode::Char('h'), None),
|
||||
@@ -618,13 +603,11 @@ mod tests {
|
||||
log_section_toggle: (KeyCode::Char('k'), None),
|
||||
quit: (KeyCode::Char('l'), None),
|
||||
save_logs: (KeyCode::Char('m'), None),
|
||||
scroll_down_many: (KeyCode::Char('n'), None),
|
||||
scroll_down_one: (KeyCode::Char('o'), None),
|
||||
scroll_down: (KeyCode::Char('o'), None),
|
||||
scroll_end: (KeyCode::Char('p'), None),
|
||||
scroll_many: KeyModifiers::ALT,
|
||||
scroll_start: (KeyCode::Char('q'), None),
|
||||
scroll_up_many: (KeyCode::Char('r'), None),
|
||||
scroll_up_one: (KeyCode::Char('s'), None),
|
||||
scroll_up: (KeyCode::Char('s'), None),
|
||||
select_next_panel: (KeyCode::Char('t'), None),
|
||||
select_previous_panel: (KeyCode::Char('u'), None),
|
||||
sort_by_cpu: (KeyCode::Char('v'), None),
|
||||
@@ -662,6 +645,7 @@ mod tests {
|
||||
delete_deny: (KeyCode::Char('c'), Some(KeyCode::Char('C'))),
|
||||
exec: (KeyCode::Char('d'), Some(KeyCode::Char('D'))),
|
||||
filter_mode: (KeyCode::Char('e'), Some(KeyCode::Char('E'))),
|
||||
log_search_mode: (KeyCode::Char('m'), Some(KeyCode::Char('M'))),
|
||||
force_redraw: (KeyCode::Char('f'), Some(KeyCode::Char('F'))),
|
||||
log_scroll_back: (KeyCode::Char('f'), Some(KeyCode::Char('F'))),
|
||||
log_scroll_forward: (KeyCode::Char('g'), Some(KeyCode::Char('G'))),
|
||||
@@ -670,13 +654,11 @@ mod tests {
|
||||
log_section_toggle: (KeyCode::Char('j'), Some(KeyCode::Char('J'))),
|
||||
quit: (KeyCode::Char('k'), Some(KeyCode::Char('K'))),
|
||||
save_logs: (KeyCode::Char('l'), Some(KeyCode::Char('L'))),
|
||||
scroll_down_many: (KeyCode::Char('m'), Some(KeyCode::Char('M'))),
|
||||
scroll_down_one: (KeyCode::Char('n'), Some(KeyCode::Char('N'))),
|
||||
scroll_down: (KeyCode::Char('n'), Some(KeyCode::Char('N'))),
|
||||
scroll_end: (KeyCode::Char('o'), Some(KeyCode::Char('O'))),
|
||||
scroll_many: KeyModifiers::ALT,
|
||||
scroll_start: (KeyCode::Char('p'), Some(KeyCode::Char('P'))),
|
||||
scroll_up_many: (KeyCode::Char('q'), Some(KeyCode::Char('Q'))),
|
||||
scroll_up_one: (KeyCode::Char('r'), Some(KeyCode::Char('R'))),
|
||||
scroll_up: (KeyCode::Char('r'), Some(KeyCode::Char('R'))),
|
||||
select_next_panel: (KeyCode::Char('s'), Some(KeyCode::Char('S'))),
|
||||
select_previous_panel: (KeyCode::Char('t'), Some(KeyCode::Char('T'))),
|
||||
sort_by_cpu: (KeyCode::Char('u'), Some(KeyCode::Char('U'))),
|
||||
@@ -705,6 +687,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
/// Help panel will show custom keymap if in use, with either one or two definition for each entry
|
||||
#[allow(clippy::todo)]
|
||||
fn test_draw_blocks_help_one_and_two_definitions() {
|
||||
let mut setup = test_setup(110, 50, true, true);
|
||||
|
||||
@@ -714,6 +697,7 @@ mod tests {
|
||||
delete_deny: (KeyCode::Char('c'), Some(KeyCode::Char('C'))),
|
||||
exec: (KeyCode::Char('d'), None),
|
||||
filter_mode: (KeyCode::Char('e'), Some(KeyCode::Char('E'))),
|
||||
log_search_mode: (KeyCode::Char('8'), None),
|
||||
force_redraw: (KeyCode::Char('f'), None),
|
||||
log_scroll_back: (KeyCode::Char('g'), Some(KeyCode::Char('G'))),
|
||||
log_scroll_forward: (KeyCode::Char('h'), None),
|
||||
@@ -722,13 +706,11 @@ mod tests {
|
||||
log_section_toggle: (KeyCode::Char('k'), Some(KeyCode::Char('K'))),
|
||||
quit: (KeyCode::Char('l'), None),
|
||||
save_logs: (KeyCode::Char('m'), Some(KeyCode::Char('M'))),
|
||||
scroll_down_many: (KeyCode::Char('n'), None),
|
||||
scroll_down_one: (KeyCode::Char('o'), Some(KeyCode::Char('O'))),
|
||||
scroll_down: (KeyCode::Char('o'), Some(KeyCode::Char('O'))),
|
||||
scroll_end: (KeyCode::Char('p'), None),
|
||||
scroll_many: KeyModifiers::ALT,
|
||||
scroll_start: (KeyCode::Char('q'), Some(KeyCode::Char('Q'))),
|
||||
scroll_up_many: (KeyCode::Char('r'), None),
|
||||
scroll_up_one: (KeyCode::Char('s'), Some(KeyCode::Char('S'))),
|
||||
scroll_up: (KeyCode::Char('s'), Some(KeyCode::Char('S'))),
|
||||
select_next_panel: (KeyCode::Char('t'), None),
|
||||
select_previous_panel: (KeyCode::Char('u'), Some(KeyCode::Char('U'))),
|
||||
sort_by_cpu: (KeyCode::Char('v'), None),
|
||||
@@ -742,7 +724,7 @@ mod tests {
|
||||
sort_by_tx: (KeyCode::Char('3'), None),
|
||||
sort_reset: (KeyCode::Char('4'), Some(KeyCode::Char('5'))),
|
||||
toggle_help: (KeyCode::Char('5'), None),
|
||||
toggle_mouse_capture: (KeyCode::Char('6'), Some(KeyCode::Char('7'))),
|
||||
toggle_mouse_capture: (KeyCode::Char('6'), Some(KeyCode::Char('#'))),
|
||||
};
|
||||
|
||||
let tz = setup.app_data.lock().config.timezone.clone();
|
||||
@@ -759,7 +741,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_draw_blocks_help_show_timezone() {
|
||||
let mut setup = test_setup(87, 37, true, true);
|
||||
let mut setup = test_setup(87, 39, true, true);
|
||||
|
||||
setup
|
||||
.terminal
|
||||
|
||||
@@ -81,7 +81,7 @@ mod tests {
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::{
|
||||
app_data::{ContainerImage, ContainerName},
|
||||
app_data::{ContainerImage, ContainerName, ScrollDirection},
|
||||
config::AppColors,
|
||||
ui::{
|
||||
FrameData, Status,
|
||||
@@ -309,7 +309,7 @@ mod tests {
|
||||
);
|
||||
})
|
||||
.unwrap();
|
||||
setup.app_data.lock().log_previous();
|
||||
setup.app_data.lock().log_scroll(&ScrollDirection::Previous);
|
||||
let fd = FrameData::from((&setup.app_data, &setup.gui_state));
|
||||
|
||||
setup
|
||||
|
||||
@@ -23,6 +23,7 @@ pub mod info;
|
||||
pub mod logs;
|
||||
pub mod popup;
|
||||
pub mod ports;
|
||||
pub mod search_logs;
|
||||
|
||||
pub const NAME_TEXT: &str = r#"
|
||||
88
|
||||
@@ -160,19 +161,11 @@ pub mod tests {
|
||||
fn from(data: (&Arc<Mutex<AppData>>, &Arc<Mutex<GuiState>>)) -> Self {
|
||||
let (mut app_data, gui_data) = (data.0.lock(), data.1.lock());
|
||||
|
||||
// let container_section_height = app_data.get_container_len();
|
||||
// let container_section_height = if container_section_height < 12 {
|
||||
// u16::try_from(container_section_height + 5).unwrap_or_default()
|
||||
// } else {
|
||||
// 12
|
||||
// };
|
||||
|
||||
let (filter_by, filter_term) = app_data.get_filter();
|
||||
Self {
|
||||
chart_data: app_data.get_chart_data(),
|
||||
color_logs: app_data.config.color_logs,
|
||||
columns: app_data.get_width(),
|
||||
// container_section_height,
|
||||
container_title: app_data.get_container_title(),
|
||||
delete_confirm: gui_data.get_delete_container(),
|
||||
filter_by,
|
||||
@@ -182,6 +175,7 @@ pub mod tests {
|
||||
show_logs: gui_data.get_show_logs(),
|
||||
info_text: gui_data.info_box_text.clone(),
|
||||
is_loading: gui_data.is_loading(),
|
||||
log_search: app_data.gen_log_search(),
|
||||
loading_icon: gui_data.get_loading().to_string(),
|
||||
log_height: gui_data.get_log_height(),
|
||||
log_title: app_data.get_log_title(),
|
||||
@@ -230,7 +224,6 @@ pub mod tests {
|
||||
/// Just a shorthand for when enumerating over result cells
|
||||
pub fn get_result(
|
||||
setup: &'_ TuiTestSetup,
|
||||
// w: u16,
|
||||
) -> std::iter::Enumerate<std::slice::Chunks<'_, ratatui::buffer::Cell>> {
|
||||
setup
|
||||
.terminal
|
||||
|
||||
@@ -0,0 +1,479 @@
|
||||
use crossterm::event::KeyCode;
|
||||
use ratatui::{
|
||||
Frame,
|
||||
layout::{Constraint, Direction, Layout, Rect},
|
||||
style::{Modifier, Style},
|
||||
text::{Line, Span},
|
||||
widgets::Paragraph,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
app_data::LogsButton,
|
||||
config::{AppColors, Keymap},
|
||||
ui::FrameData,
|
||||
};
|
||||
|
||||
// background, text, selected_text, highlight;
|
||||
/// Draw the filter bar
|
||||
pub fn draw(area: Rect, colors: AppColors, frame: &mut Frame, fd: &FrameData, keymap: &Keymap) {
|
||||
let style_but = Style::default()
|
||||
.fg(colors.log_search.button_text)
|
||||
.bg(colors.log_search.highlight);
|
||||
let style_desc = Style::default()
|
||||
.fg(colors.log_search.text)
|
||||
.bg(colors.log_search.background);
|
||||
let space = || Span::from(" ");
|
||||
|
||||
let mut line = vec![
|
||||
Span::styled(" Esc ", style_but),
|
||||
Span::styled(" clear ", style_desc),
|
||||
space(),
|
||||
];
|
||||
line.extend([Span::styled(
|
||||
" search term: ",
|
||||
Style::default()
|
||||
.fg(colors.log_search.highlight)
|
||||
.bg(colors.log_search.background)
|
||||
.add_modifier(Modifier::BOLD),
|
||||
)]);
|
||||
|
||||
if let Some(log_search) = fd.log_search.as_ref() {
|
||||
line.extend([
|
||||
Span::styled(
|
||||
log_search
|
||||
.term
|
||||
.as_ref()
|
||||
.map_or(String::new(), std::clone::Clone::clone),
|
||||
Style::default()
|
||||
.fg(colors.log_search.text)
|
||||
.bg(colors.log_search.background),
|
||||
),
|
||||
space(),
|
||||
]);
|
||||
}
|
||||
|
||||
let left_text = Paragraph::new(Line::from(line))
|
||||
.alignment(ratatui::layout::Alignment::Left)
|
||||
.style(Style::default().bg(colors.log_search.background));
|
||||
let mut line = vec![];
|
||||
if let Some(log_search) = fd.log_search.as_ref() {
|
||||
if let Some(buttons) = log_search.buttons.as_ref() {
|
||||
let down = if keymap.scroll_down.0 == KeyCode::Down {
|
||||
"↑".to_owned()
|
||||
} else {
|
||||
keymap.scroll_down.0.to_string()
|
||||
};
|
||||
let up = if keymap.scroll_up.0 == KeyCode::Up {
|
||||
"↓".to_owned()
|
||||
} else {
|
||||
keymap.scroll_up.0.to_string()
|
||||
};
|
||||
let next = [
|
||||
space(),
|
||||
Span::styled(format!(" {up} "), style_but),
|
||||
Span::styled(" next ", style_desc),
|
||||
];
|
||||
let previous = [
|
||||
space(),
|
||||
Span::styled(format!(" {down} "), style_but),
|
||||
Span::styled(" previous ", style_desc),
|
||||
];
|
||||
|
||||
match buttons {
|
||||
LogsButton::Both => line.extend(previous.into_iter().chain(next)),
|
||||
LogsButton::Next => line.extend(next),
|
||||
LogsButton::Previous => line.extend(previous),
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(results) = log_search.result.as_ref() {
|
||||
line.extend([
|
||||
Span::styled(
|
||||
" matches: ",
|
||||
Style::default()
|
||||
.fg(colors.log_search.highlight)
|
||||
.bg(colors.log_search.background)
|
||||
.add_modifier(Modifier::BOLD),
|
||||
),
|
||||
Span::styled(
|
||||
results,
|
||||
Style::default()
|
||||
.fg(colors.log_search.text)
|
||||
.bg(colors.log_search.background),
|
||||
),
|
||||
]);
|
||||
}
|
||||
}
|
||||
let right_text = Paragraph::new(Line::from(line))
|
||||
.alignment(ratatui::layout::Alignment::Right)
|
||||
.style(Style::default().bg(colors.log_search.background));
|
||||
|
||||
let line_split = Layout::default()
|
||||
.direction(Direction::Horizontal)
|
||||
.constraints(vec![Constraint::Percentage(50), Constraint::Percentage(50)])
|
||||
.split(area);
|
||||
frame.render_widget(left_text, line_split[0]);
|
||||
frame.render_widget(right_text, line_split[1]);
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[allow(clippy::unwrap_used)]
|
||||
mod tests {
|
||||
|
||||
use crossterm::event::KeyCode;
|
||||
use insta::assert_snapshot;
|
||||
use ratatui::style::{Color, Modifier};
|
||||
|
||||
use crate::{
|
||||
config::{AppColors, Keymap},
|
||||
ui::{
|
||||
FrameData,
|
||||
draw_blocks::tests::{get_result, insert_logs, test_setup},
|
||||
},
|
||||
};
|
||||
|
||||
#[test]
|
||||
/// Filter row is drawn correctly & colors are correct
|
||||
/// Colours change when filter_by option is changed
|
||||
fn test_draw_blocks_log_search_row() {
|
||||
let mut setup = test_setup(140, 1, true, true);
|
||||
|
||||
setup
|
||||
.gui_state
|
||||
.lock()
|
||||
.status_push(crate::ui::Status::SearchLogs);
|
||||
setup
|
||||
.terminal
|
||||
.draw(|f| {
|
||||
super::draw(setup.area, AppColors::new(), f, &setup.fd, &Keymap::new());
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
assert_snapshot!(setup.terminal.backend());
|
||||
|
||||
for (_, result_row) in get_result(&setup) {
|
||||
for (result_cell_index, result_cell) in result_row.iter().enumerate() {
|
||||
match result_cell_index {
|
||||
0..=4 => {
|
||||
assert_eq!(result_cell.bg, Color::Magenta);
|
||||
assert_eq!(result_cell.fg, Color::Black);
|
||||
}
|
||||
5..=11 => {
|
||||
assert_eq!(result_cell.bg, Color::Reset);
|
||||
assert_eq!(result_cell.fg, Color::Gray);
|
||||
}
|
||||
13..=26 => {
|
||||
assert_eq!(result_cell.bg, Color::Reset);
|
||||
assert_eq!(result_cell.fg, Color::Magenta);
|
||||
assert_eq!(result_cell.modifier, Modifier::BOLD);
|
||||
}
|
||||
_ => {
|
||||
assert_eq!(result_cell.bg, Color::Reset);
|
||||
assert_eq!(result_cell.fg, Color::Reset);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
/// Log item found, previous button visible
|
||||
fn test_draw_blocks_log_search_match_previous() {
|
||||
let mut setup = test_setup(140, 1, true, true);
|
||||
|
||||
insert_logs(&setup);
|
||||
setup
|
||||
.gui_state
|
||||
.lock()
|
||||
.status_push(crate::ui::Status::SearchLogs);
|
||||
|
||||
setup.app_data.lock().log_search_push('e');
|
||||
|
||||
let fd = FrameData::from((&setup.app_data, &setup.gui_state));
|
||||
|
||||
setup
|
||||
.terminal
|
||||
.draw(|f| {
|
||||
super::draw(setup.area, AppColors::new(), f, &fd, &Keymap::new());
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
assert_snapshot!(setup.terminal.backend());
|
||||
|
||||
for (_, result_row) in get_result(&setup) {
|
||||
for (result_cell_index, result_cell) in result_row.iter().enumerate() {
|
||||
match result_cell_index {
|
||||
0..=4 | 114..=116 => {
|
||||
assert_eq!(result_cell.bg, Color::Magenta);
|
||||
assert_eq!(result_cell.fg, Color::Black);
|
||||
}
|
||||
5..=11 | 27 | 117..=126 | 137..=139 => {
|
||||
assert_eq!(result_cell.bg, Color::Reset);
|
||||
assert_eq!(result_cell.fg, Color::Gray);
|
||||
}
|
||||
13..=26 | 127..=136 => {
|
||||
assert_eq!(result_cell.bg, Color::Reset);
|
||||
assert_eq!(result_cell.fg, Color::Magenta);
|
||||
assert_eq!(result_cell.modifier, Modifier::BOLD);
|
||||
}
|
||||
_ => {
|
||||
assert_eq!(result_cell.bg, Color::Reset);
|
||||
assert_eq!(result_cell.fg, Color::Reset);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
/// Log item found, next button visible
|
||||
fn test_draw_blocks_log_search_match_next() {
|
||||
let mut setup = test_setup(140, 1, true, true);
|
||||
|
||||
insert_logs(&setup);
|
||||
|
||||
setup
|
||||
.gui_state
|
||||
.lock()
|
||||
.status_push(crate::ui::Status::SearchLogs);
|
||||
|
||||
setup.app_data.lock().log_search_push('e');
|
||||
setup
|
||||
.app_data
|
||||
.lock()
|
||||
.log_scroll(&crate::app_data::ScrollDirection::Previous);
|
||||
setup
|
||||
.app_data
|
||||
.lock()
|
||||
.log_scroll(&crate::app_data::ScrollDirection::Previous);
|
||||
|
||||
let fd = FrameData::from((&setup.app_data, &setup.gui_state));
|
||||
setup
|
||||
.terminal
|
||||
.draw(|f| {
|
||||
super::draw(setup.area, AppColors::new(), f, &fd, &Keymap::new());
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
assert_snapshot!(setup.terminal.backend());
|
||||
|
||||
for (_, result_row) in get_result(&setup) {
|
||||
for (result_cell_index, result_cell) in result_row.iter().enumerate() {
|
||||
match result_cell_index {
|
||||
0..=4 | 118..=120 => {
|
||||
assert_eq!(result_cell.bg, Color::Magenta);
|
||||
assert_eq!(result_cell.fg, Color::Black);
|
||||
}
|
||||
5..=11 | 27 | 121..=126 | 137..=139 => {
|
||||
assert_eq!(result_cell.bg, Color::Reset);
|
||||
assert_eq!(result_cell.fg, Color::Gray);
|
||||
}
|
||||
13..=26 | 127..=136 => {
|
||||
assert_eq!(result_cell.bg, Color::Reset);
|
||||
assert_eq!(result_cell.fg, Color::Magenta);
|
||||
assert_eq!(result_cell.modifier, Modifier::BOLD);
|
||||
}
|
||||
_ => {
|
||||
assert_eq!(result_cell.bg, Color::Reset);
|
||||
assert_eq!(result_cell.fg, Color::Reset);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
/// Log item found, next & previous button visible
|
||||
fn test_draw_blocks_log_search_match_both_next_previous() {
|
||||
let mut setup = test_setup(140, 1, true, true);
|
||||
|
||||
insert_logs(&setup);
|
||||
|
||||
setup
|
||||
.gui_state
|
||||
.lock()
|
||||
.status_push(crate::ui::Status::SearchLogs);
|
||||
|
||||
setup.app_data.lock().log_search_push('e');
|
||||
setup
|
||||
.app_data
|
||||
.lock()
|
||||
.log_scroll(&crate::app_data::ScrollDirection::Previous);
|
||||
|
||||
let fd = FrameData::from((&setup.app_data, &setup.gui_state));
|
||||
setup
|
||||
.terminal
|
||||
.draw(|f| {
|
||||
super::draw(setup.area, AppColors::new(), f, &fd, &Keymap::new());
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
assert_snapshot!(setup.terminal.backend());
|
||||
|
||||
for (_, result_row) in get_result(&setup) {
|
||||
for (result_cell_index, result_cell) in result_row.iter().enumerate() {
|
||||
match result_cell_index {
|
||||
0..=4 | 104..=106 | 118..=120 => {
|
||||
assert_eq!(result_cell.bg, Color::Magenta);
|
||||
assert_eq!(result_cell.fg, Color::Black);
|
||||
}
|
||||
5..=11 | 27 | 107..=116 | 121..=126 | 137..=139 => {
|
||||
assert_eq!(result_cell.bg, Color::Reset);
|
||||
assert_eq!(result_cell.fg, Color::Gray);
|
||||
}
|
||||
13..=26 | 127..=136 => {
|
||||
assert_eq!(result_cell.bg, Color::Reset);
|
||||
assert_eq!(result_cell.fg, Color::Magenta);
|
||||
assert_eq!(result_cell.modifier, Modifier::BOLD);
|
||||
}
|
||||
_ => {
|
||||
assert_eq!(result_cell.bg, Color::Reset);
|
||||
assert_eq!(result_cell.fg, Color::Reset);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
/// No log item found
|
||||
fn test_draw_blocks_log_search_match_none() {
|
||||
let mut setup = test_setup(140, 1, true, true);
|
||||
|
||||
insert_logs(&setup);
|
||||
|
||||
setup
|
||||
.gui_state
|
||||
.lock()
|
||||
.status_push(crate::ui::Status::SearchLogs);
|
||||
|
||||
setup.app_data.lock().log_search_push('z');
|
||||
let fd = FrameData::from((&setup.app_data, &setup.gui_state));
|
||||
|
||||
setup
|
||||
.terminal
|
||||
.draw(|f| {
|
||||
super::draw(setup.area, AppColors::new(), f, &fd, &Keymap::new());
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
assert_snapshot!(setup.terminal.backend());
|
||||
|
||||
for (_, result_row) in get_result(&setup) {
|
||||
for (result_cell_index, result_cell) in result_row.iter().enumerate() {
|
||||
match result_cell_index {
|
||||
0..=4 => {
|
||||
assert_eq!(result_cell.bg, Color::Magenta);
|
||||
assert_eq!(result_cell.fg, Color::Black);
|
||||
}
|
||||
5..=11 | 27 => {
|
||||
assert_eq!(result_cell.bg, Color::Reset);
|
||||
assert_eq!(result_cell.fg, Color::Gray);
|
||||
}
|
||||
13..=26 => {
|
||||
assert_eq!(result_cell.bg, Color::Reset);
|
||||
assert_eq!(result_cell.fg, Color::Magenta);
|
||||
assert_eq!(result_cell.modifier, Modifier::BOLD);
|
||||
}
|
||||
_ => {
|
||||
assert_eq!(result_cell.bg, Color::Reset);
|
||||
assert_eq!(result_cell.fg, Color::Reset);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
/// Custom keymap for scroll buttons
|
||||
fn test_draw_blocks_log_search_keymap() {
|
||||
let mut setup = test_setup(140, 1, true, true);
|
||||
|
||||
insert_logs(&setup);
|
||||
|
||||
let mut keymap = setup.app_data.lock().config.keymap.clone();
|
||||
keymap.scroll_up = (KeyCode::Char('a'), None);
|
||||
keymap.scroll_down = (KeyCode::Char('b'), None);
|
||||
|
||||
setup
|
||||
.gui_state
|
||||
.lock()
|
||||
.status_push(crate::ui::Status::SearchLogs);
|
||||
|
||||
setup.app_data.lock().log_search_push('e');
|
||||
setup
|
||||
.app_data
|
||||
.lock()
|
||||
.log_scroll(&crate::app_data::ScrollDirection::Previous);
|
||||
let fd = FrameData::from((&setup.app_data, &setup.gui_state));
|
||||
|
||||
setup
|
||||
.terminal
|
||||
.draw(|f| {
|
||||
super::draw(setup.area, AppColors::new(), f, &fd, &keymap);
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
assert_snapshot!(setup.terminal.backend());
|
||||
}
|
||||
|
||||
#[test]
|
||||
/// Custom colours applied
|
||||
fn test_draw_blocks_log_search_colors() {
|
||||
let mut setup = test_setup(140, 1, true, true);
|
||||
|
||||
insert_logs(&setup);
|
||||
|
||||
setup
|
||||
.gui_state
|
||||
.lock()
|
||||
.status_push(crate::ui::Status::SearchLogs);
|
||||
|
||||
setup.app_data.lock().log_search_push('e');
|
||||
setup
|
||||
.app_data
|
||||
.lock()
|
||||
.log_scroll(&crate::app_data::ScrollDirection::Previous);
|
||||
|
||||
let mut colors = AppColors::new();
|
||||
|
||||
colors.log_search.background = Color::White;
|
||||
colors.log_search.highlight = Color::Blue;
|
||||
colors.log_search.button_text = Color::Yellow;
|
||||
colors.log_search.text = Color::Magenta;
|
||||
|
||||
let fd = FrameData::from((&setup.app_data, &setup.gui_state));
|
||||
setup
|
||||
.terminal
|
||||
.draw(|f| {
|
||||
super::draw(setup.area, colors, f, &fd, &Keymap::new());
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
assert_snapshot!(setup.terminal.backend());
|
||||
|
||||
for (_, result_row) in get_result(&setup) {
|
||||
for (result_cell_index, result_cell) in result_row.iter().enumerate() {
|
||||
match result_cell_index {
|
||||
0..=4 | 104..=106 | 118..=120 => {
|
||||
assert_eq!(result_cell.bg, Color::Blue);
|
||||
assert_eq!(result_cell.fg, Color::Yellow);
|
||||
}
|
||||
5..=11 | 27 | 107..=116 | 121..=126 | 137..=139 => {
|
||||
assert_eq!(result_cell.bg, Color::White);
|
||||
assert_eq!(result_cell.fg, Color::Magenta);
|
||||
}
|
||||
13..=26 | 127..=136 => {
|
||||
assert_eq!(result_cell.bg, Color::White);
|
||||
assert_eq!(result_cell.fg, Color::Blue);
|
||||
assert_eq!(result_cell.modifier, Modifier::BOLD);
|
||||
}
|
||||
_ => {
|
||||
assert_eq!(result_cell.bg, Color::White);
|
||||
assert_eq!(result_cell.fg, Color::Reset);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -2,4 +2,4 @@
|
||||
source: src/ui/draw_blocks/filter.rs
|
||||
expression: setup.terminal.backend()
|
||||
---
|
||||
" Esc clear ← by → Name Image Status All term: "
|
||||
" Esc clear ← by → Name Image Status All filter term: "
|
||||
|
||||
+1
-1
@@ -2,4 +2,4 @@
|
||||
source: src/ui/draw_blocks/filter.rs
|
||||
expression: setup.terminal.backend()
|
||||
---
|
||||
" Esc clear ← by → Name Image Status All term: cd "
|
||||
" Esc clear ← by → Name Image Status All filter term: cd "
|
||||
|
||||
+1
-1
@@ -2,4 +2,4 @@
|
||||
source: src/ui/draw_blocks/filter.rs
|
||||
expression: setup.terminal.backend()
|
||||
---
|
||||
" Esc clear ← by → Name Image Status All term: "
|
||||
" Esc clear ← by → Name Image Status All filter term: "
|
||||
|
||||
+1
-1
@@ -2,4 +2,4 @@
|
||||
source: src/ui/draw_blocks/filter.rs
|
||||
expression: setup.terminal.backend()
|
||||
---
|
||||
" Esc clear ← by → Name Image Status All term: cd "
|
||||
" Esc clear ← by → Name Image Status All filter term: cd "
|
||||
|
||||
+4
-2
@@ -17,9 +17,9 @@ expression: setup.terminal.backend()
|
||||
" │ A simple tui to view & control docker containers │ "
|
||||
" │ │ "
|
||||
" │ ( tab ) or ( shift+tab ) change panels │ "
|
||||
" │ ( ↑ ↓ ) or ( j k ) or ( PgUp PgDown ) or ( Home End ) scroll vertically │ "
|
||||
" │ ( ↑ ↓ ) or ( j k ) or ( Home End ) scroll vertically │ "
|
||||
" │ ( ← → ) horizontal scroll across logs │ "
|
||||
" │ ( ctrl ) increase scroll speed, used in conjuction scroll keys │ "
|
||||
" │ ( ctrl ) increase scroll speed, used in conjunction scroll keys │ "
|
||||
" │ ( enter ) send docker container command │ "
|
||||
" │ ( e ) exec into a container │ "
|
||||
" │ ( f ) force clear the screen & redraw the gui │ "
|
||||
@@ -27,6 +27,7 @@ expression: setup.terminal.backend()
|
||||
" │ ( s ) save logs to file │ "
|
||||
" │ ( m ) toggle mouse capture - if disabled, text on screen can be selected & copied │ "
|
||||
" │ ( F1 ) or ( / ) enter filter mode │ "
|
||||
" │ ( # ) enter log search mode │ "
|
||||
" │ ( 0 ) stop sort │ "
|
||||
" │ ( 1 - 9 ) sort by header - or click header │ "
|
||||
" │ ( - = ) change log section height │ "
|
||||
@@ -37,5 +38,6 @@ expression: setup.terminal.backend()
|
||||
" │ currently an early work in progress, all and any input appreciated │ "
|
||||
" │ https://github.com/mrjackwills/oxker │ "
|
||||
" │ │ "
|
||||
" │ │ "
|
||||
" ╰───────────────────────────────────────────────────────────────────────────────────╯ "
|
||||
" "
|
||||
|
||||
+4
-2
@@ -17,9 +17,9 @@ expression: setup.terminal.backend()
|
||||
" │ A simple tui to view & control docker containers │ "
|
||||
" │ │ "
|
||||
" │ ( tab ) or ( shift+tab ) change panels │ "
|
||||
" │ ( ↑ ↓ ) or ( j k ) or ( PgUp PgDown ) or ( Home End ) scroll vertically │ "
|
||||
" │ ( ↑ ↓ ) or ( j k ) or ( Home End ) scroll vertically │ "
|
||||
" │ ( ← → ) horizontal scroll across logs │ "
|
||||
" │ ( ctrl ) increase scroll speed, used in conjuction scroll keys │ "
|
||||
" │ ( ctrl ) increase scroll speed, used in conjunction scroll keys │ "
|
||||
" │ ( enter ) send docker container command │ "
|
||||
" │ ( e ) exec into a container │ "
|
||||
" │ ( f ) force clear the screen & redraw the gui │ "
|
||||
@@ -27,6 +27,7 @@ expression: setup.terminal.backend()
|
||||
" │ ( s ) save logs to file │ "
|
||||
" │ ( m ) toggle mouse capture - if disabled, text on screen can be selected & copied │ "
|
||||
" │ ( F1 ) or ( / ) enter filter mode │ "
|
||||
" │ ( # ) enter log search mode │ "
|
||||
" │ ( 0 ) stop sort │ "
|
||||
" │ ( 1 - 9 ) sort by header - or click header │ "
|
||||
" │ ( - = ) change log section height │ "
|
||||
@@ -37,5 +38,6 @@ expression: setup.terminal.backend()
|
||||
" │ currently an early work in progress, all and any input appreciated │ "
|
||||
" │ https://github.com/mrjackwills/oxker │ "
|
||||
" │ │ "
|
||||
" │ │ "
|
||||
" ╰───────────────────────────────────────────────────────────────────────────────────╯ "
|
||||
" "
|
||||
|
||||
+3
-3
@@ -19,13 +19,11 @@ expression: setup.terminal.backend()
|
||||
" │ ( u ) select previous panel │ "
|
||||
" │ ( o ) scroll list down by one │ "
|
||||
" │ ( s ) scroll list up by one │ "
|
||||
" │ ( n ) scroll list down by many │ "
|
||||
" │ ( r ) scroll list by up many │ "
|
||||
" │ ( p ) scroll list to end │ "
|
||||
" │ ( q ) scroll list to start │ "
|
||||
" │ ( h ) horizontal scroll logs right │ "
|
||||
" │ ( g ) horizontal scroll logs left │ "
|
||||
" │ ( Alt ) increase scroll speed, used in conjuction scroll keys │ "
|
||||
" │ ( Alt ) increase scroll speed, used in conjunction scroll keys │ "
|
||||
" │ ( enter ) send docker container command │ "
|
||||
" │ ( d ) exec into a container │ "
|
||||
" │ ( f ) force clear the screen & redraw the gui │ "
|
||||
@@ -33,6 +31,7 @@ expression: setup.terminal.backend()
|
||||
" │ ( m ) save logs to file │ "
|
||||
" │ ( 6 ) toggle mouse capture - if disabled, text on screen can be selected & copied │ "
|
||||
" │ ( e ) enter filter mode │ "
|
||||
" │ ( 7 ) enter log search mode │ "
|
||||
" │ ( 4 ) reset container sorting │ "
|
||||
" │ ( z ) sort containers by name │ "
|
||||
" │ ( 1 ) sort containers by state │ "
|
||||
@@ -51,4 +50,5 @@ expression: setup.terminal.backend()
|
||||
" │ │ "
|
||||
" │ currently an early work in progress, all and any input appreciated │ "
|
||||
" │ https://github.com/mrjackwills/oxker │ "
|
||||
" │ │ "
|
||||
" ╰────────────────────────────────────────────────────────────────────────────────────╯ "
|
||||
|
||||
+3
-3
@@ -19,13 +19,11 @@ expression: setup.terminal.backend()
|
||||
" │ ( t ) or ( T ) select previous panel │ "
|
||||
" │ ( n ) or ( N ) scroll list down by one │ "
|
||||
" │ ( r ) or ( R ) scroll list up by one │ "
|
||||
" │ ( m ) or ( M ) scroll list down by many │ "
|
||||
" │ ( q ) or ( Q ) scroll list by up many │ "
|
||||
" │ ( o ) or ( O ) scroll list to end │ "
|
||||
" │ ( p ) or ( P ) scroll list to start │ "
|
||||
" │ ( g ) or ( G ) horizontal scroll logs right │ "
|
||||
" │ ( f ) or ( F ) horizontal scroll logs left │ "
|
||||
" │ ( Alt ) increase scroll speed, used in conjuction scroll keys │ "
|
||||
" │ ( Alt ) increase scroll speed, used in conjunction scroll keys │ "
|
||||
" │ ( enter ) send docker container command │ "
|
||||
" │ ( d ) or ( D ) exec into a container │ "
|
||||
" │ ( f ) or ( F ) force clear the screen & redraw the gui │ "
|
||||
@@ -33,6 +31,7 @@ expression: setup.terminal.backend()
|
||||
" │ ( l ) or ( L ) save logs to file │ "
|
||||
" │ ( 5 ) or ( Page Down ) toggle mouse capture - if disabled, text on screen can be selected & copied │ "
|
||||
" │ ( e ) or ( E ) enter filter mode │ "
|
||||
" │ ( m ) or ( M ) enter log search mode │ "
|
||||
" │ ( 3 ) or ( 6 ) reset container sorting │ "
|
||||
" │ ( y ) or ( Y ) sort containers by name │ "
|
||||
" │ ( 0 ) or ( 9 ) sort containers by state │ "
|
||||
@@ -51,4 +50,5 @@ expression: setup.terminal.backend()
|
||||
" │ │ "
|
||||
" │ currently an early work in progress, all and any input appreciated │ "
|
||||
" │ https://github.com/mrjackwills/oxker │ "
|
||||
" │ │ "
|
||||
" ╰────────────────────────────────────────────────────────────────────────────────────────────────────╯ "
|
||||
|
||||
+4
-4
@@ -19,20 +19,19 @@ expression: setup.terminal.backend()
|
||||
" │ ( u ) or ( U ) select previous panel │ "
|
||||
" │ ( o ) or ( O ) scroll list down by one │ "
|
||||
" │ ( s ) or ( S ) scroll list up by one │ "
|
||||
" │ ( n ) scroll list down by many │ "
|
||||
" │ ( r ) scroll list by up many │ "
|
||||
" │ ( p ) scroll list to end │ "
|
||||
" │ ( q ) or ( Q ) scroll list to start │ "
|
||||
" │ ( h ) horizontal scroll logs right │ "
|
||||
" │ ( g ) or ( G ) horizontal scroll logs left │ "
|
||||
" │ ( Alt ) increase scroll speed, used in conjuction scroll keys │ "
|
||||
" │ ( Alt ) increase scroll speed, used in conjunction scroll keys │ "
|
||||
" │ ( enter ) send docker container command │ "
|
||||
" │ ( d ) exec into a container │ "
|
||||
" │ ( f ) force clear the screen & redraw the gui │ "
|
||||
" │ ( 5 ) toggle this help information - or click heading │ "
|
||||
" │ ( m ) or ( M ) save logs to file │ "
|
||||
" │ ( 6 ) or ( 7 ) toggle mouse capture - if disabled, text on screen can be selected & copied │ "
|
||||
" │ ( 6 ) or ( # ) toggle mouse capture - if disabled, text on screen can be selected & copied │ "
|
||||
" │ ( e ) or ( E ) enter filter mode │ "
|
||||
" │ ( 8 ) enter log search mode │ "
|
||||
" │ ( 4 ) or ( 5 ) reset container sorting │ "
|
||||
" │ ( z ) sort containers by name │ "
|
||||
" │ ( 1 ) sort containers by state │ "
|
||||
@@ -51,4 +50,5 @@ expression: setup.terminal.backend()
|
||||
" │ │ "
|
||||
" │ currently an early work in progress, all and any input appreciated │ "
|
||||
" │ https://github.com/mrjackwills/oxker │ "
|
||||
" │ │ "
|
||||
" ╰────────────────────────────────────────────────────────────────────────────────────────────╯ "
|
||||
|
||||
+4
-2
@@ -18,9 +18,9 @@ expression: setup.terminal.backend()
|
||||
" │ logs timezone: Asia/Tokyo │ "
|
||||
" │ │ "
|
||||
" │ ( tab ) or ( shift+tab ) change panels │ "
|
||||
" │ ( ↑ ↓ ) or ( j k ) or ( PgUp PgDown ) or ( Home End ) scroll vertically │ "
|
||||
" │ ( ↑ ↓ ) or ( j k ) or ( Home End ) scroll vertically │ "
|
||||
" │ ( ← → ) horizontal scroll across logs │ "
|
||||
" │ ( ctrl ) increase scroll speed, used in conjuction scroll keys │ "
|
||||
" │ ( ctrl ) increase scroll speed, used in conjunction scroll keys │ "
|
||||
" │ ( enter ) send docker container command │ "
|
||||
" │ ( e ) exec into a container │ "
|
||||
" │ ( f ) force clear the screen & redraw the gui │ "
|
||||
@@ -28,6 +28,7 @@ expression: setup.terminal.backend()
|
||||
" │ ( s ) save logs to file │ "
|
||||
" │ ( m ) toggle mouse capture - if disabled, text on screen can be selected & copied │ "
|
||||
" │ ( F1 ) or ( / ) enter filter mode │ "
|
||||
" │ ( # ) enter log search mode │ "
|
||||
" │ ( 0 ) stop sort │ "
|
||||
" │ ( 1 - 9 ) sort by header - or click header │ "
|
||||
" │ ( - = ) change log section height │ "
|
||||
@@ -38,4 +39,5 @@ expression: setup.terminal.backend()
|
||||
" │ currently an early work in progress, all and any input appreciated │ "
|
||||
" │ https://github.com/mrjackwills/oxker │ "
|
||||
" │ │ "
|
||||
" │ │ "
|
||||
" ╰───────────────────────────────────────────────────────────────────────────────────╯ "
|
||||
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
---
|
||||
source: src/ui/draw_blocks/search_logs.rs
|
||||
expression: setup.terminal.backend()
|
||||
---
|
||||
" Esc clear search term: e ↑ previous ↓ next matches: 2/3"
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
---
|
||||
source: src/ui/draw_blocks/search_logs.rs
|
||||
expression: setup.terminal.backend()
|
||||
---
|
||||
" Esc clear search term: e b previous a next matches: 2/3"
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
---
|
||||
source: src/ui/draw_blocks/search_logs.rs
|
||||
expression: setup.terminal.backend()
|
||||
---
|
||||
" Esc clear search term: e ↑ previous ↓ next matches: 2/3"
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
---
|
||||
source: src/ui/draw_blocks/search_logs.rs
|
||||
expression: setup.terminal.backend()
|
||||
---
|
||||
" Esc clear search term: e ↓ next matches: 1/3"
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
---
|
||||
source: src/ui/draw_blocks/search_logs.rs
|
||||
expression: setup.terminal.backend()
|
||||
---
|
||||
" Esc clear search term: z "
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
---
|
||||
source: src/ui/draw_blocks/search_logs.rs
|
||||
expression: setup.terminal.backend()
|
||||
---
|
||||
" Esc clear search term: e ↑ previous matches: 3/3"
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
---
|
||||
source: src/ui/draw_blocks/search_logs.rs
|
||||
expression: setup.terminal.backend()
|
||||
---
|
||||
" Esc clear search term: "
|
||||
+10
-10
@@ -18,9 +18,9 @@ expression: setup.terminal.backend()
|
||||
"│ │ A simple tui to view & control docker containers │ │"
|
||||
"│ │ │ │"
|
||||
"│ │ ( tab ) or ( shift+tab ) change panels │ │"
|
||||
"│ │ ( ↑ ↓ ) or ( j k ) or ( PgUp PgDown ) or ( Home End ) scroll vertically │ │"
|
||||
"│ │ ( ↑ ↓ ) or ( j k ) or ( Home End ) scroll vertically │ │"
|
||||
"│ │ ( ← → ) horizontal scroll across logs │ │"
|
||||
"│ │ ( ctrl ) increase scroll speed, used in conjuction scroll keys │ │"
|
||||
"│ │ ( ctrl ) increase scroll speed, used in conjunction scroll keys │ │"
|
||||
"│ │ ( enter ) send docker container command │ │"
|
||||
"│ │ ( e ) exec into a container │ │"
|
||||
"│ │ ( f ) force clear the screen & redraw the gui │ │"
|
||||
@@ -28,16 +28,16 @@ expression: setup.terminal.backend()
|
||||
"│ │ ( s ) save logs to file │ │"
|
||||
"│ │ ( m ) toggle mouse capture - if disabled, text on screen can be selected & copied │ │"
|
||||
"│ │ ( F1 ) or ( / ) enter filter mode │ │"
|
||||
"│ │ ( # ) enter log search mode │ │"
|
||||
"│ │ ( 0 ) stop sort │ │"
|
||||
"│ │ ( 1 - 9 ) sort by header - or click header │ │"
|
||||
"│ │ ( - = ) change log section height │ │"
|
||||
"╰────────────────────────────────────│ ( \ ) toggle log section visibility │────────────────────────────────────╯"
|
||||
"╭───────────────────────── cpu 03.00%│ ( esc ) close dialog │──────╮╭────────── ports ───────────╮"
|
||||
"│10.00%│ •• │ ( q ) quit at any time │ ││ ip private public│"
|
||||
"│ │ • • │ │ ││ 8001 │"
|
||||
"│ │ •• • │ currently an early work in progress, all and any input appreciated │ ││127.0.0.1 8003 8003│"
|
||||
"│ │ • • │ https://github.com/mrjackwills/oxker │ ││ │"
|
||||
"│ │ •• • • │ │ ││ │"
|
||||
"╰────────────────────────────────────│ ( - = ) change log section height │────────────────────────────────────╯"
|
||||
"╭───────────────────────── cpu 03.00%│ ( \ ) toggle log section visibility │──────╮╭────────── ports ───────────╮"
|
||||
"│10.00%│ •• │ ( esc ) close dialog │ ││ ip private public│"
|
||||
"│ │ • • │ ( q ) quit at any time │ ││ 8001 │"
|
||||
"│ │ •• • │ │ ││127.0.0.1 8003 8003│"
|
||||
"│ │ • • │ currently an early work in progress, all and any input appreciated │ ││ │"
|
||||
"│ │ •• • • │ https://github.com/mrjackwills/oxker │ ││ │"
|
||||
"│ │• •• │ │ ││ │"
|
||||
"│ │• • ╰────────────────────────────────────────────────────────────────────────────────────╯ ││ │"
|
||||
"│ │ ││ │ ││ │"
|
||||
|
||||
+1
-1
@@ -31,4 +31,4 @@ expression: setup.terminal.backend()
|
||||
"│ │• •• ││ │• •• ││ │"
|
||||
"│ │ ││ │ ││ │"
|
||||
"╰───────────────────────────────────────────────────────────────╯╰───────────────────────────────────────────────────────────────╯╰────────────────────────────╯"
|
||||
" Esc clear ← by → Name Image Status All term: r_1 "
|
||||
" Esc clear ← by → Name Image Status All filter term: r_1 "
|
||||
|
||||
@@ -170,6 +170,7 @@ pub enum Status {
|
||||
Help,
|
||||
Init,
|
||||
Logs,
|
||||
SearchLogs,
|
||||
}
|
||||
|
||||
/// Global gui_state, stored in an Arc<Mutex>
|
||||
@@ -411,6 +412,16 @@ impl GuiState {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_logs_panel_selected(&mut self, app_data: &Arc<Mutex<AppData>>) {
|
||||
self.selected_panel = SelectablePanel::Logs;
|
||||
if (app_data.lock().get_container_len() == 0
|
||||
&& self.get_selected_panel() == SelectablePanel::Commands)
|
||||
|| (self.log_height == 0 && self.get_selected_panel() == SelectablePanel::Logs)
|
||||
{
|
||||
self.selected_panel = self.selected_panel.next();
|
||||
}
|
||||
self.rerender.update_draw();
|
||||
}
|
||||
/// Change to next selectable panel
|
||||
pub fn selectable_panel_next(&mut self, app_data: &Arc<Mutex<AppData>>) {
|
||||
self.selected_panel = self.selected_panel.next();
|
||||
|
||||
+14
-9
@@ -30,8 +30,8 @@ pub use self::color_match::*;
|
||||
pub use self::gui_state::{DeleteButton, GuiState, SelectablePanel, Status};
|
||||
use crate::{
|
||||
app_data::{
|
||||
AppData, Columns, ContainerId, ContainerPorts, CpuTuple, FilterBy, Header, MemTuple,
|
||||
SortedOrder, State,
|
||||
AppData, Columns, ContainerId, ContainerPorts, CpuTuple, FilterBy, Header, LogSearch,
|
||||
MemTuple, SortedOrder, State,
|
||||
},
|
||||
app_error::AppError,
|
||||
config::{AppColors, Keymap},
|
||||
@@ -218,10 +218,6 @@ impl Ui {
|
||||
}
|
||||
|
||||
while self.is_running.load(Ordering::SeqCst) {
|
||||
// if self.redraw.get_clear() {
|
||||
// self.terminal.clear().ok();
|
||||
// continue;
|
||||
// }
|
||||
if self.should_redraw(&mut drawn_at, docker_interval_ms) {
|
||||
let fd = FrameData::from(&*self);
|
||||
|
||||
@@ -287,6 +283,7 @@ impl Ui {
|
||||
}
|
||||
|
||||
/// Frequent data required by multiple frame drawing functions, can reduce mutex reads by placing it all in here
|
||||
/// TODO refactor this
|
||||
#[derive(Debug, Clone)]
|
||||
#[allow(clippy::struct_excessive_bools)]
|
||||
pub struct FrameData {
|
||||
@@ -294,6 +291,7 @@ pub struct FrameData {
|
||||
color_logs: bool,
|
||||
columns: Columns,
|
||||
container_title: String,
|
||||
log_search: Option<LogSearch>,
|
||||
delete_confirm: Option<ContainerId>,
|
||||
filter_by: FilterBy,
|
||||
filter_term: Option<String>,
|
||||
@@ -327,6 +325,7 @@ impl From<&Ui> for FrameData {
|
||||
filter_by,
|
||||
filter_term: filter_term.cloned(),
|
||||
has_containers: app_data.get_container_len() > 0,
|
||||
log_search: app_data.gen_log_search(),
|
||||
has_error: app_data.get_error(),
|
||||
info_text: gui_data.info_box_text.clone(),
|
||||
is_loading: gui_data.is_loading(),
|
||||
@@ -353,9 +352,12 @@ fn draw_frame(
|
||||
fd: &FrameData,
|
||||
gui_state: &Arc<Mutex<GuiState>>,
|
||||
) {
|
||||
let contains_filter = fd.status.contains(&Status::Filter);
|
||||
let contains_search_logs = fd.status.contains(&Status::SearchLogs);
|
||||
|
||||
let whole_layout = Layout::default()
|
||||
.direction(Direction::Vertical)
|
||||
.constraints(if fd.status.contains(&Status::Filter) {
|
||||
.constraints(if contains_filter || contains_search_logs {
|
||||
vec![Constraint::Max(1), Constraint::Min(1), Constraint::Max(1)]
|
||||
} else {
|
||||
vec![Constraint::Max(1), Constraint::Min(1)]
|
||||
@@ -364,9 +366,12 @@ fn draw_frame(
|
||||
|
||||
draw_blocks::headers::draw(whole_layout[0], colors, f, fd, gui_state, keymap);
|
||||
|
||||
// If required, draw filter bar
|
||||
if let Some(rect) = whole_layout.get(2) {
|
||||
draw_blocks::filter::draw(*rect, colors, f, fd);
|
||||
if contains_filter {
|
||||
draw_blocks::filter::draw(*rect, colors, f, fd);
|
||||
} else {
|
||||
draw_blocks::search_logs::draw(*rect, colors, f, fd, keymap);
|
||||
}
|
||||
}
|
||||
|
||||
let upper_main = Layout::default()
|
||||
|
||||
Reference in New Issue
Block a user