diff --git a/.github/release-body.md b/.github/release-body.md
index c3b48a8..f17bc3a 100644
--- a/.github/release-body.md
+++ b/.github/release-body.md
@@ -1,6 +1,16 @@
-### 2025-06-19
+### 2025-08-21
-### Reverts
-+ Bollard update rolled back, closes #66, [aac9c6b598ce6c23b14f5a8b0116e662b18074d2]
+### Chores
++ Dependencies updated, [ced885e0128b6d5d3a3c7cb97d7e53bc2da64893], [f9b40ea03d0e70e235c28646ff3f9ebb468a904d]
++ Rust 1.89 linting, [79d19ceeb81ae60bc5562683e405d6e74e6f2578]
++ GitHub workflow updated, [08384200558fa1b9d378ea62ea832708caebaa91], [6573af1ed7d382a81c1305397e904066bb8395a8]
+
+### 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` [c190f0206cc55b8e45b8373f9be954e828c18b3b], [8939ac0345326633e794cc10a981a1f3c5c07549]
++ Force clear screen & redraw of UI. By default uses `f` key, `config.toml` updated with `force_redraw` [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, [c5bbffdb5f9e800951e4060aa6aee8e00db589aa]
+
+### Refactors
++ remove macos cfg none-const functions, Zigbuild now uses Rust 1.87.0, [eb686e2c952e04da74b3e12c0bfa015ec4615e1d]
see CHANGELOG.md for more details
diff --git a/.github/screenshot_01.png b/.github/screenshot_01.png
index 567dd3a..f39df48 100644
Binary files a/.github/screenshot_01.png and b/.github/screenshot_01.png differ
diff --git a/.github/workflows/create_release_and_build.yml b/.github/workflows/create_release_and_build.yml
index c3e89ca..7b03691 100644
--- a/.github/workflows/create_release_and_build.yml
+++ b/.github/workflows/create_release_and_build.yml
@@ -31,7 +31,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout code
- uses: actions/checkout@v4
+ uses: actions/checkout@v5
# Install stable rust, and associated tools
- name: install rust
@@ -82,10 +82,10 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout code
- uses: actions/checkout@v4
+ uses: actions/checkout@v5
- name: Setup | Artifacts
- uses: actions/download-artifact@v4
+ uses: actions/download-artifact@v5
- name: Update Release
uses: ncipollo/release-action@v1
@@ -107,7 +107,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout code
- uses: actions/checkout@v4
+ uses: actions/checkout@v5
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
@@ -121,26 +121,25 @@ jobs:
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
+
+ - name: Set up Docker Buildx
+ uses: docker/setup-buildx-action@v3
- - name: Write release version to env
- run: |
- CURRENT_SEMVER=${GITHUB_REF_NAME#v}
- echo "CURRENT_SEMVER=$CURRENT_SEMVER" >> $GITHUB_ENV
-
- - uses: docker/setup-buildx-action@v3
- id: buildx
+ - name: Build and push Docker image
+ uses: docker/build-push-action@v6
with:
- install: true
- - name: Build for Dockerhub & ghcr.io
- run: |
- docker build --platform linux/arm/v6,linux/arm64,linux/amd64 \
- -t ${{ secrets.DOCKERHUB_USERNAME }}/oxker:latest \
- -t ${{ secrets.DOCKERHUB_USERNAME }}/oxker:${{env.CURRENT_SEMVER}} \
- -t ghcr.io/${{ github.repository_owner }}/${{ github.ref_name }}:latest \
- -t ghcr.io/${{ github.repository_owner }}/${{ github.ref_name }}:${{env.CURRENT_SEMVER}} \
- --provenance=false --sbom=false \
- --push \
- -f containerised/Dockerfile .
+ context: .
+ file: ./containerised/Dockerfile
+ push: true
+ tags: |
+ ${{ secrets.DOCKERHUB_USERNAME }}/{{ github.event.repository.name }}:latest
+ ${{ secrets.DOCKERHUB_USERNAME }}/{{ github.event.repository.name }}:${{env.CURRENT_SEMVER}}
+ ghcr.io/${{ github.repository_owner }}/${{ github.event.repository.name }}:latest
+ ghcr.io/${{ github.repository_owner }}/${{ github.event.repository.name }}:${{ env.CURRENT_SEMVER }}
+ platforms: linux/arm/v6,linux/arm64,linux/amd64
+ provenance: false
+ sbom: false
+
########################
# Publish to crates.io #
########################
@@ -152,7 +151,7 @@ jobs:
steps:
- name: update rust stable
run: rustup update stable
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v5
- name: Publish Dry Run
run: cargo publish --dry-run
@@ -165,7 +164,7 @@ jobs:
steps:
- name: update rust stable
run: rustup update stable
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v5
- name: Publish
run: cargo publish
diff --git a/.gitignore b/.gitignore
index 5388e4b..ee5b384 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,5 @@
/target
/releases
+/binaries
# Used in the zigbuild for aarch64-apple-darwin
.intentionally-empty-file.o
\ No newline at end of file
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9d8a280..d17d0fe 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,19 @@
+# v0.11.0
+### 2025-08-21
+
+### Chores
++ Dependencies updated, [ced885e0](https://github.com/mrjackwills/oxker/commit/ced885e0128b6d5d3a3c7cb97d7e53bc2da64893), [f9b40ea0](https://github.com/mrjackwills/oxker/commit/f9b40ea03d0e70e235c28646ff3f9ebb468a904d)
++ Rust 1.89 linting, [79d19cee](https://github.com/mrjackwills/oxker/commit/79d19ceeb81ae60bc5562683e405d6e74e6f2578)
++ GitHub workflow updated, [08384200](https://github.com/mrjackwills/oxker/commit/08384200558fa1b9d378ea62ea832708caebaa91), [6573af1e](https://github.com/mrjackwills/oxker/commit/6573af1ed7d382a81c1305397e904066bb8395a8)
+
+### 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)
+
+### Refactors
++ remove macos cfg none-const functions, Zigbuild now uses Rust 1.87.0, [eb686e2c](https://github.com/mrjackwills/oxker/commit/eb686e2c952e04da74b3e12c0bfa015ec4615e1d)
+
# v0.10.5
### 2025-06-19
@@ -11,7 +27,7 @@
+ .devcontainer updated, [324f8268](https://github.com/mrjackwills/oxker/commit/324f8268278081504d5357f2ed89b78ca2c25d04)
+ dependencies updated, [0ace9dd6](https://github.com/mrjackwills/oxker/commit/0ace9dd662144a589341779a64d7fcd8de7d9978), [a6360075](https://github.com/mrjackwills/oxker/commit/a636007547280b3b3db69374601dbece4bc21eef)
+ Rust 1.87.0 linting, [395b1aa7](https://github.com/mrjackwills/oxker/commit/395b1aa7e997a528e4f21e66f5f859001c1c3ec1), [67e5888e](https://github.com/mrjackwills/oxker/commit/67e5888e008cfd504c10e47f678f9351c838be99)
-
+back
### Docs
+ example config files updated, [63ab7de7](https://github.com/mrjackwills/oxker/commit/63ab7de72897de460f31181c5a42befbee2f91d3), [8fb5ac4a](https://github.com/mrjackwills/oxker/commit/8fb5ac4a945b75f3fcd118c53be1202ccbc43c59)
+ README.md updated, link to directories crate, closes [#65](https://github.com/mrjackwills/oxker/issues/65), [c2bfe329](https://github.com/mrjackwills/oxker/commit/c2bfe3296563daf4b7f077469f3eeff6895720b0)
diff --git a/Cargo.lock b/Cargo.lock
index bc3647a..7d2cf58 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -40,9 +40,9 @@ dependencies = [
[[package]]
name = "anstream"
-version = "0.6.19"
+version = "0.6.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "301af1932e46185686725e0fad2f8f2aa7da69dd70bf6ecc44d6b703844a3933"
+checksum = "3ae563653d1938f79b1ab1b5e668c87c76a9930414574a6583a7b7e11a8e6192"
dependencies = [
"anstyle",
"anstyle-parse",
@@ -70,35 +70,41 @@ dependencies = [
[[package]]
name = "anstyle-query"
-version = "1.1.3"
+version = "1.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6c8bdeb6047d8983be085bab0ba1472e6dc604e7041dbf6fcd5e71523014fae9"
+checksum = "9e231f6134f61b71076a3eab506c379d4f36122f2af15a9ff04415ea4c3339e2"
dependencies = [
- "windows-sys 0.59.0",
+ "windows-sys 0.60.2",
]
[[package]]
name = "anstyle-wincon"
-version = "3.0.9"
+version = "3.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "403f75924867bb1033c59fbf0797484329750cfbe3c4325cd33127941fabc882"
+checksum = "3e0633414522a32ffaac8ac6cc8f748e090c5717661fddeea04219e2344f5f2a"
dependencies = [
"anstyle",
"once_cell_polyfill",
- "windows-sys 0.59.0",
+ "windows-sys 0.60.2",
]
[[package]]
name = "anyhow"
-version = "1.0.98"
+version = "1.0.99"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487"
+checksum = "b0674a1ddeecb70197781e945de4b3b8ffb61fa939a5597bcf48503737663100"
+
+[[package]]
+name = "atomic-waker"
+version = "1.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0"
[[package]]
name = "autocfg"
-version = "1.4.0"
+version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
+checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
[[package]]
name = "backtrace"
@@ -123,15 +129,15 @@ checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
[[package]]
name = "bitflags"
-version = "2.9.1"
+version = "2.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967"
+checksum = "6a65b545ab31d687cff52899d4890855fec459eb6afe0da6417b8a18da87aa29"
[[package]]
name = "bollard"
-version = "0.18.1"
+version = "0.19.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "97ccca1260af6a459d75994ad5acc1651bcabcbdbc41467cc9786519ab854c30"
+checksum = "8796b390a5b4c86f9f2e8173a68c2791f4fa6b038b84e96dbc01c016d1e6722c"
dependencies = [
"base64",
"bollard-stubs",
@@ -162,20 +168,21 @@ dependencies = [
[[package]]
name = "bollard-stubs"
-version = "1.47.1-rc.27.3.1"
+version = "1.49.0-rc.28.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3f179cfbddb6e77a5472703d4b30436bff32929c0aa8a9008ecf23d1d3cdd0da"
+checksum = "2e7814991259013d5a5bee4ae28657dae0747d843cf06c40f7fc0c2894d6fa38"
dependencies = [
"serde",
+ "serde_json",
"serde_repr",
"serde_with",
]
[[package]]
name = "bumpalo"
-version = "3.18.1"
+version = "3.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "793db76d6187cd04dff33004d8e6c9cc4e05cd330500379d2394209271b4aeee"
+checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43"
[[package]]
name = "bytes"
@@ -197,27 +204,27 @@ checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53"
[[package]]
name = "castaway"
-version = "0.2.3"
+version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0abae9be0aaf9ea96a3b1b8b1b55c602ca751eba1b1500220cea4ecbafe7c0d5"
+checksum = "dec551ab6e7578819132c713a93c022a05d60159dc86e7a7050223577484c55a"
dependencies = [
"rustversion",
]
[[package]]
name = "cc"
-version = "1.2.27"
+version = "1.2.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d487aa071b5f64da6f19a3e848e3578944b726ee5a4854b82172f02aa876bfdc"
+checksum = "3ee0f8803222ba5a7e2777dd72ca451868909b1ac410621b676adf07280e9b5f"
dependencies = [
"shlex",
]
[[package]]
name = "cfg-if"
-version = "1.0.1"
+version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268"
+checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9"
[[package]]
name = "chrono"
@@ -234,9 +241,9 @@ dependencies = [
[[package]]
name = "clap"
-version = "4.5.40"
+version = "4.5.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "40b6887a1d8685cebccf115538db5c0efe625ccac9696ad45c409d96566e910f"
+checksum = "1fc0e74a703892159f5ae7d3aac52c8e6c392f5ae5f359c70b5881d60aaac318"
dependencies = [
"clap_builder",
"clap_derive",
@@ -244,9 +251,9 @@ dependencies = [
[[package]]
name = "clap_builder"
-version = "4.5.40"
+version = "4.5.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e0c66c08ce9f0c698cbce5c0279d0bb6ac936d8674174fe48f736533b964f59e"
+checksum = "b3e7f4214277f3c7aa526a59dd3fbe306a370daee1f8b7b8c987069cd8e888a8"
dependencies = [
"anstream",
"anstyle",
@@ -258,9 +265,9 @@ dependencies = [
[[package]]
name = "clap_derive"
-version = "4.5.40"
+version = "4.5.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d2c7947ae4cc3d851207c1adb5b5e260ff0cca11446b1d6d1423788e442257ce"
+checksum = "14cb31bb0a7d536caef2639baa7fad459e15c3144efefa6dbd1c84562c4739f6"
dependencies = [
"heck",
"proc-macro2",
@@ -349,7 +356,7 @@ dependencies = [
"document-features",
"mio",
"parking_lot",
- "rustix 1.0.7",
+ "rustix 1.0.8",
"signal-hook",
"signal-hook-mio",
"winapi",
@@ -473,9 +480,9 @@ dependencies = [
[[package]]
name = "dyn-clone"
-version = "1.0.19"
+version = "1.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1c7a8fb8a9fbf66c1f703fe16184d10ca0ee9d23be5b4436400408ba54a95005"
+checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555"
[[package]]
name = "either"
@@ -497,12 +504,12 @@ checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
[[package]]
name = "errno"
-version = "0.3.12"
+version = "0.3.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cea14ef9355e3beab063703aa9dab15afd25f0667c341310c1e5274bb1d0da18"
+checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad"
dependencies = [
"libc",
- "windows-sys 0.59.0",
+ "windows-sys 0.60.2",
]
[[package]]
@@ -519,9 +526,9 @@ checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
[[package]]
name = "form_urlencoded"
-version = "1.2.1"
+version = "1.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456"
+checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf"
dependencies = [
"percent-encoding",
]
@@ -615,9 +622,9 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
[[package]]
name = "hashbrown"
-version = "0.15.4"
+version = "0.15.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5"
+checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1"
dependencies = [
"allocator-api2",
"equivalent",
@@ -684,19 +691,21 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
[[package]]
name = "hyper"
-version = "1.6.0"
+version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80"
+checksum = "eb3aa54a13a0dfe7fbe3a59e0c76093041720fdc77b110cc0fc260fafb4dc51e"
dependencies = [
+ "atomic-waker",
"bytes",
"futures-channel",
- "futures-util",
+ "futures-core",
"http",
"http-body",
"httparse",
"httpdate",
"itoa",
"pin-project-lite",
+ "pin-utils",
"smallvec",
"tokio",
"want",
@@ -719,9 +728,9 @@ dependencies = [
[[package]]
name = "hyper-util"
-version = "0.1.14"
+version = "0.1.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dc2fdfdbff08affe55bb779f33b053aa1fe5dd5b54c257343c17edfa55711bdb"
+checksum = "8d9b05277c7e8da2c93a568989bb6207bef0112e8d17df7a6eda4a3cf143bc5e"
dependencies = [
"bytes",
"futures-channel",
@@ -871,9 +880,9 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
[[package]]
name = "idna"
-version = "1.0.3"
+version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e"
+checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de"
dependencies = [
"idna_adapter",
"smallvec",
@@ -903,12 +912,12 @@ dependencies = [
[[package]]
name = "indexmap"
-version = "2.9.0"
+version = "2.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e"
+checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661"
dependencies = [
"equivalent",
- "hashbrown 0.15.4",
+ "hashbrown 0.15.5",
"serde",
]
@@ -931,9 +940,9 @@ dependencies = [
[[package]]
name = "instability"
-version = "0.3.7"
+version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0bf9fed6d91cfb734e7476a06bde8300a1b94e217e1b523b6f0cd1a01998c71d"
+checksum = "435d80800b936787d62688c927b6490e887c7ef5ff9ce922c6c6050fca75eb9a"
dependencies = [
"darling",
"indoc",
@@ -942,6 +951,17 @@ dependencies = [
"syn",
]
+[[package]]
+name = "io-uring"
+version = "0.7.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d93587f37623a1a17d94ef2bc9ada592f5465fe7732084ab7beefabe5c77c0c4"
+dependencies = [
+ "bitflags",
+ "cfg-if",
+ "libc",
+]
+
[[package]]
name = "is_terminal_polyfill"
version = "1.70.1"
@@ -1023,15 +1043,15 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
[[package]]
name = "libc"
-version = "0.2.174"
+version = "0.2.175"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776"
+checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543"
[[package]]
name = "libredox"
-version = "0.1.3"
+version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d"
+checksum = "391290121bad3d37fbddad76d8f5d1c1c314cfc646d143d7e07a3086ddff0ce3"
dependencies = [
"bitflags",
"libc",
@@ -1057,9 +1077,9 @@ checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956"
[[package]]
name = "litrs"
-version = "0.4.1"
+version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5"
+checksum = "f5e54036fe321fd421e10d732f155734c4e4afd610dd556d9a82833ab3ee0bed"
[[package]]
name = "lock_api"
@@ -1083,7 +1103,7 @@ version = "0.12.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38"
dependencies = [
- "hashbrown 0.15.4",
+ "hashbrown 0.15.5",
]
[[package]]
@@ -1173,7 +1193,7 @@ checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
[[package]]
name = "oxker"
-version = "0.10.5"
+version = "0.11.0"
dependencies = [
"anyhow",
"bollard",
@@ -1228,9 +1248,9 @@ checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
[[package]]
name = "percent-encoding"
-version = "2.3.1"
+version = "2.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
+checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220"
[[package]]
name = "pin-project-lite"
@@ -1285,9 +1305,9 @@ dependencies = [
[[package]]
name = "proc-macro2"
-version = "1.0.95"
+version = "1.0.101"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778"
+checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de"
dependencies = [
"unicode-ident",
]
@@ -1309,9 +1329,9 @@ checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
[[package]]
name = "rand"
-version = "0.9.1"
+version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97"
+checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1"
dependencies = [
"rand_chacha",
"rand_core",
@@ -1359,18 +1379,18 @@ dependencies = [
[[package]]
name = "redox_syscall"
-version = "0.5.13"
+version = "0.5.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0d04b7d0ee6b4a0207a0a7adb104d23ecb0b47d6beae7152d0fa34b692b29fd6"
+checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77"
dependencies = [
"bitflags",
]
[[package]]
name = "redox_users"
-version = "0.5.0"
+version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dd6f9d3d47bdd2ad6945c5015a226ec6155d0bcdfd8f7cd29f86b71f8de99d2b"
+checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac"
dependencies = [
"getrandom 0.2.16",
"libredox",
@@ -1399,9 +1419,9 @@ dependencies = [
[[package]]
name = "rustc-demangle"
-version = "0.1.25"
+version = "0.1.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "989e6739f80c4ad5b13e0fd7fe89531180375b18520cc8c82080e4dc4035b84f"
+checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace"
[[package]]
name = "rustix"
@@ -1418,22 +1438,22 @@ dependencies = [
[[package]]
name = "rustix"
-version = "1.0.7"
+version = "1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266"
+checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8"
dependencies = [
"bitflags",
"errno",
"libc",
"linux-raw-sys 0.9.4",
- "windows-sys 0.59.0",
+ "windows-sys 0.60.2",
]
[[package]]
name = "rustversion"
-version = "1.0.21"
+version = "1.0.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d"
+checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
[[package]]
name = "ryu"
@@ -1453,6 +1473,18 @@ dependencies = [
"serde_json",
]
+[[package]]
+name = "schemars"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "82d20c4491bc164fa2f6c5d44565947a52ad80b9505d8e36f8d54c27c739fcd0"
+dependencies = [
+ "dyn-clone",
+ "ref-cast",
+ "serde",
+ "serde_json",
+]
+
[[package]]
name = "scopeguard"
version = "1.2.0"
@@ -1481,9 +1513,9 @@ dependencies = [
[[package]]
name = "serde_json"
-version = "1.0.140"
+version = "1.0.143"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373"
+checksum = "d401abef1d108fbd9cbaebc3e46611f4b1021f714a0597a71f41ee463f5f4a5a"
dependencies = [
"itoa",
"memchr",
@@ -1515,9 +1547,9 @@ dependencies = [
[[package]]
name = "serde_spanned"
-version = "0.6.9"
+version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3"
+checksum = "40734c41988f7306bb04f0ecf60ec0f3f1caa34290e4e8ea471dcd3346483b83"
dependencies = [
"serde",
]
@@ -1536,16 +1568,17 @@ dependencies = [
[[package]]
name = "serde_with"
-version = "3.13.0"
+version = "3.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bf65a400f8f66fb7b0552869ad70157166676db75ed8181f8104ea91cf9d0b42"
+checksum = "f2c45cd61fefa9db6f254525d46e392b852e0e61d9a1fd36e5bd183450a556d5"
dependencies = [
"base64",
"chrono",
"hex",
"indexmap 1.9.3",
- "indexmap 2.9.0",
- "schemars",
+ "indexmap 2.10.0",
+ "schemars 0.9.0",
+ "schemars 1.0.4",
"serde",
"serde_derive",
"serde_json",
@@ -1590,9 +1623,9 @@ dependencies = [
[[package]]
name = "signal-hook-registry"
-version = "1.4.5"
+version = "1.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9203b8055f63a2a00e2f593bb0510367fe707d7ff1e5c872de2f537b339e5410"
+checksum = "b2a4719bff48cee6b39d12c020eeb490953ad2443b7055bd0b21fca26bd8c28b"
dependencies = [
"libc",
]
@@ -1605,9 +1638,9 @@ checksum = "bbbb5d9659141646ae647b42fe094daf6c6192d1620870b449d9557f748b2daa"
[[package]]
name = "slab"
-version = "0.4.10"
+version = "0.4.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "04dc19736151f35336d325007ac991178d504a119863a2fcb3758cdb5e52c50d"
+checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589"
[[package]]
name = "smallvec"
@@ -1617,12 +1650,12 @@ checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
[[package]]
name = "socket2"
-version = "0.5.10"
+version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678"
+checksum = "233504af464074f9d066d7b5416c5f9b894a5862a6506e306f7b816cdd6f1807"
dependencies = [
"libc",
- "windows-sys 0.52.0",
+ "windows-sys 0.59.0",
]
[[package]]
@@ -1667,9 +1700,9 @@ dependencies = [
[[package]]
name = "syn"
-version = "2.0.103"
+version = "2.0.106"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e4307e30089d6fd6aff212f2da3a1f9e32f3223b1f010fb09b7c95f90f3ca1e8"
+checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6"
dependencies = [
"proc-macro2",
"quote",
@@ -1689,18 +1722,18 @@ dependencies = [
[[package]]
name = "thiserror"
-version = "2.0.12"
+version = "2.0.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708"
+checksum = "3467d614147380f2e4e374161426ff399c91084acd2363eaf549172b3d5e60c0"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
-version = "2.0.12"
+version = "2.0.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d"
+checksum = "6c5e1be1c48b9172ee610da68fd9cd2770e7a4056cb3fc98710ee6906f0c7960"
dependencies = [
"proc-macro2",
"quote",
@@ -1759,20 +1792,22 @@ dependencies = [
[[package]]
name = "tokio"
-version = "1.45.1"
+version = "1.47.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "75ef51a33ef1da925cea3e4eb122833cb377c61439ca401b770f54902b806779"
+checksum = "89e49afdadebb872d3145a5638b59eb0691ea23e46ca484037cfab3b76b95038"
dependencies = [
"backtrace",
"bytes",
+ "io-uring",
"libc",
"mio",
"parking_lot",
"pin-project-lite",
"signal-hook-registry",
+ "slab",
"socket2",
"tokio-macros",
- "windows-sys 0.52.0",
+ "windows-sys 0.59.0",
]
[[package]]
@@ -1788,9 +1823,9 @@ dependencies = [
[[package]]
name = "tokio-util"
-version = "0.7.15"
+version = "0.7.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "66a539a9ad6d5d281510d5bd368c973d636c02dbf8a67300bfb6b950696ad7df"
+checksum = "14307c986784f72ef81c89db7d9e28d6ac26d16213b109ea501696195e6e3ce5"
dependencies = [
"bytes",
"futures-core",
@@ -1801,35 +1836,32 @@ dependencies = [
[[package]]
name = "toml"
-version = "0.8.23"
+version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362"
+checksum = "75129e1dc5000bfbaa9fee9d1b21f974f9fbad9daec557a521ee6e080825f6e8"
dependencies = [
"serde",
"serde_spanned",
"toml_datetime",
- "toml_edit",
+ "toml_parser",
+ "winnow",
]
[[package]]
name = "toml_datetime"
-version = "0.6.11"
+version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c"
+checksum = "bade1c3e902f58d73d3f294cd7f20391c1cb2fbcb643b73566bc773971df91e3"
dependencies = [
"serde",
]
[[package]]
-name = "toml_edit"
-version = "0.22.27"
+name = "toml_parser"
+version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a"
+checksum = "b551886f449aa90d4fe2bdaa9f4a2577ad2dde302c61ecf262d80b116db95c10"
dependencies = [
- "indexmap 2.9.0",
- "serde",
- "serde_spanned",
- "toml_datetime",
"winnow",
]
@@ -1945,9 +1977,9 @@ checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd"
[[package]]
name = "url"
-version = "2.5.4"
+version = "2.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60"
+checksum = "137a3c834eaf7139b73688502f3f1141a0337c5d8e4d9b536f9b8c796e26a7c4"
dependencies = [
"form_urlencoded",
"idna",
@@ -1968,9 +2000,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
[[package]]
name = "uuid"
-version = "1.17.0"
+version = "1.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3cf4199d1e5d15ddd86a694e4d0dffa9c323ce759fea589f00fef9d81cc1931d"
+checksum = "f33196643e165781c20a5ead5582283a7dacbb87855d867fbc2df3f81eddc1be"
dependencies = [
"getrandom 0.3.3",
"js-sys",
@@ -2147,15 +2179,6 @@ 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"
@@ -2171,7 +2194,7 @@ version = "0.60.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb"
dependencies = [
- "windows-targets 0.53.2",
+ "windows-targets 0.53.3",
]
[[package]]
@@ -2192,10 +2215,11 @@ dependencies = [
[[package]]
name = "windows-targets"
-version = "0.53.2"
+version = "0.53.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c66f69fcc9ce11da9966ddb31a40968cad001c5bedeb5c2b82ede4253ab48aef"
+checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91"
dependencies = [
+ "windows-link",
"windows_aarch64_gnullvm 0.53.0",
"windows_aarch64_msvc 0.53.0",
"windows_i686_gnu 0.53.0",
@@ -2304,12 +2328,9 @@ checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486"
[[package]]
name = "winnow"
-version = "0.7.11"
+version = "0.7.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "74c7b26e3480b707944fc872477815d29a8e429d2f93a1ce000f5fa84a15cbcd"
-dependencies = [
- "memchr",
-]
+checksum = "f3edebf492c8125044983378ecb5766203ad3b4c2f7a922bd7dd207f6d443e95"
[[package]]
name = "wit-bindgen-rt"
@@ -2352,18 +2373,18 @@ dependencies = [
[[package]]
name = "zerocopy"
-version = "0.8.25"
+version = "0.8.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a1702d9583232ddb9174e01bb7c15a2ab8fb1bc6f227aa1233858c351a3ba0cb"
+checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f"
dependencies = [
"zerocopy-derive",
]
[[package]]
name = "zerocopy-derive"
-version = "0.8.25"
+version = "0.8.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "28a6e20d751156648aa063f3800b706ee209a32c0b4d9f24be3d980b01be55ef"
+checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181"
dependencies = [
"proc-macro2",
"quote",
@@ -2404,9 +2425,9 @@ dependencies = [
[[package]]
name = "zerovec"
-version = "0.11.2"
+version = "0.11.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4a05eb080e015ba39cc9e23bbe5e7fb04d5fb040350f99f34e338d5fdd294428"
+checksum = "e7aa2bd55086f1ab526693ecbe444205da57e25f4489879da80635a46d90e73b"
dependencies = [
"yoke",
"zerofrom",
diff --git a/Cargo.toml b/Cargo.toml
index 3d0ea62..83e4ff0 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "oxker"
-version = "0.10.5"
+version = "0.11.0"
edition = "2024"
authors = ["Jack Wills "]
description = "A simple tui to view & control docker containers"
@@ -27,7 +27,7 @@ similar_names = "allow"
[dependencies]
anyhow = "1.0"
-bollard = "0.18"
+bollard = "0.19"
cansi = "2.2"
clap = { version = "4.5", features = ["color", "derive", "unicode"] }
crossterm = "0.29"
@@ -39,12 +39,12 @@ ratatui = "0.29"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
serde_jsonc = "1.0"
-tokio = { version = "1.45", features = ["full"] }
+tokio = { version = "1.47", features = ["full"] }
tokio-util = "0.7"
-toml = { version = "0.8", default-features = false, features = ["parse"] }
+toml = { version = "0.9", default-features = false, features = ["parse", "serde"] }
tracing = "0.1"
tracing-subscriber = "0.3"
-uuid = { version = "1.17", features = ["fast-rng", "v4"] }
+uuid = { version = "1.18", features = ["fast-rng", "v4"] }
[profile.release]
lto = true
diff --git a/README.md b/README.md
index 83837ae..1c85e30 100644
--- a/README.md
+++ b/README.md
@@ -105,7 +105,9 @@ 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 )```| Change selected line in selected panel, mouse scroll also changes selected line.|
+| ```( ↑ ↓ )``` or ```( j k )``` or ```( PgUp PgDown )``` 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 scroll keys.|
| ```( enter )```| Run selected docker command.|
| ```( 1-9 )``` | Sort containers by heading, clicking on headings also sorts the selected column. |
| ```( 0 )``` | Stop sorting.|
@@ -113,6 +115,7 @@ In application controls, these, amongst many other settings, can be customized w
| ```( - ) ``` 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.|
+| ```( f )``` | Force clear the screen & redraw the gui.|
| ```( h )``` | Toggle help menu.|
| ```( m )``` | Toggle mouse capture - if disabled, text on screen can be selected.|
| ```( q )``` | Quit.|
diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml
index 7af255b..7c58aac 100644
--- a/docker/docker-compose.yml
+++ b/docker/docker-compose.yml
@@ -4,7 +4,7 @@ networks:
name: oxker-examaple-net
services:
postgres:
- image: postgres:alpine3.21
+ image: postgres:17-alpine
container_name: postgres
environment:
- POSTGRES_PASSWORD=never_use_this_password_in_production
@@ -18,7 +18,7 @@ services:
limits:
memory: 1024M
redis:
- image: redis:alpine3.21
+ image: redis:latest
container_name: redis
ipc: private
restart: always
diff --git a/example_config/example.config.jsonc b/example_config/example.config.jsonc
index 230e982..8abb678 100644
--- a/example_config/example.config.jsonc
+++ b/example_config/example.config.jsonc
@@ -42,6 +42,7 @@
// 3) F1-F12
// 4) backspace, tab, backtab, delete, end, esc, home, insert, pagedown, pageup, left, right, up, down
// Each definition can have two keys associated with it
+ // WARNING "scroll_many" only accepts control, alt, shift, with no secondary option
// If any key clashes are found, oxker will revert to it's default keymap
"keymap": {
// Clear any popup boxes, filter panel, or help panel
@@ -74,10 +75,12 @@
"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",
@@ -87,19 +90,30 @@
"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"],
// 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"
],
+ // Horizontal scroll of the logs
+ "log_scroll_forward": [
+ "right"
+ ],
+ "log_scroll_back": [
+ "left"
+ ],
// Select next panel
"select_next_panel": [
"tab"
@@ -159,6 +173,10 @@
// Toggle visibility of the log section
"log_section_toggle": [
"\\"
+ ],
+ // Force a complete clear & redraw of the screen
+ "force_redraw": [
+ "f"
]
},
////////////////////
diff --git a/example_config/example.config.toml b/example_config/example.config.toml
index 3c71386..182e7c5 100644
--- a/example_config/example.config.toml
+++ b/example_config/example.config.toml
@@ -55,8 +55,10 @@ show_logs = true
# 3) F1-F12
# 4) backspace, tab, backtab, delete, end, esc, home, insert, pagedown, pageup, left, right, up, down
-
# Each definition can have two keys associated with it
+
+# WARNING "scroll_many" only accepts control, alt, shift, with no secondary option
+
# If any key clashes are found, oxker will revert to it's default keymap
[keymap]
@@ -74,18 +76,28 @@ filter_mode = ["/", "F1"]
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 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
+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"]
+# Horizontal scroll of the logs
+log_scroll_forward = ["right"]
+log_scroll_back = ["left"]
# Select next panel
select_next_panel = ["tab"]
# Select previous panel
@@ -108,10 +120,11 @@ toggle_help = ["h"]
toggle_mouse_capture = ["m"]
# Reduce the height of the logs list section
log_section_height_decrease = ["-"]
-# Increase the height of the logs list section
log_section_height_increase = ["+"]
# Toggle visibility of the log section
log_section_toggle = ["\\"]
+# Force a complete clear & redraw of the screen
+force_redraw = ["f"]
#################
# Custom Colors #
@@ -186,6 +199,7 @@ selected_filter_text = "black"
# Highlighted text color
highlight = "magenta"
+
# The color the of Docker commands available for each container
[colors.commands]
# Background color of panel
diff --git a/src/app_data/container_state.rs b/src/app_data/container_state.rs
index de27aac..d31550e 100644
--- a/src/app_data/container_state.rs
+++ b/src/app_data/container_state.rs
@@ -8,8 +8,10 @@ use std::{
use bollard::service::Port;
use jiff::{Timestamp, tz::TimeZone};
use ratatui::{
+ layout::Size,
style::Color,
- widgets::{ListItem, ListState},
+ text::{Line, Text},
+ widgets::ListState,
};
use crate::config::AppColors;
@@ -30,14 +32,6 @@ impl From<&str> for ContainerId {
}
impl ContainerId {
- // TODO remove this once zigbuild uses Rust v1.87.0
- #[cfg(target_os = "macos")]
- #[allow(clippy::missing_const_for_fn)]
- pub fn get(&self) -> &str {
- self.0.as_str()
- }
-
- #[cfg(not(target_os = "macos"))]
pub const fn get(&self) -> &str {
self.0.as_str()
}
@@ -84,14 +78,6 @@ macro_rules! unit_struct {
}
impl $name {
- #[cfg(target_os = "macos")]
- #[allow(clippy::missing_const_for_fn)]
- // TODO remove this once zigbuild uses Rust v1.87.0
- pub fn get(&self) -> &str {
- self.0.as_str()
- }
-
- #[cfg(not(target_os = "macos"))]
pub const fn get(&self) -> &str {
self.0.as_str()
}
@@ -215,6 +201,7 @@ impl StatefulList {
}
/// Return the current status of the select list, e.g. 2/5,
+ /// MAYBE add up down arrows, check if at start or end etc
pub fn get_state_title(&self) -> String {
if self.items.is_empty() {
String::new()
@@ -342,6 +329,54 @@ impl From<(&str, &ContainerStatus)> for State {
}
}
+/// Need status, to check if container is unhealthy or not
+impl
+ From<(
+ &bollard::secret::ContainerSummaryStateEnum,
+ &ContainerStatus,
+ )> for State
+{
+ fn from(
+ (input, status): (
+ &bollard::secret::ContainerSummaryStateEnum,
+ &ContainerStatus,
+ ),
+ ) -> Self {
+ match input {
+ bollard::secret::ContainerSummaryStateEnum::DEAD => Self::Dead,
+ bollard::secret::ContainerSummaryStateEnum::EXITED => Self::Exited,
+ bollard::secret::ContainerSummaryStateEnum::PAUSED => Self::Paused,
+ bollard::secret::ContainerSummaryStateEnum::REMOVING => Self::Removing,
+ bollard::secret::ContainerSummaryStateEnum::RESTARTING => Self::Restarting,
+ bollard::secret::ContainerSummaryStateEnum::RUNNING => {
+ if status.unhealthy() {
+ Self::Running(RunningState::Unhealthy)
+ } else {
+ Self::Running(RunningState::Healthy)
+ }
+ }
+ _ => Self::Unknown,
+ }
+ }
+}
+
+/// Again, need status, to check if container is unhealthy or not
+impl
+ From<(
+ Option<&bollard::secret::ContainerSummaryStateEnum>,
+ &ContainerStatus,
+ )> for State
+{
+ fn from(
+ (input, status): (
+ Option<&bollard::secret::ContainerSummaryStateEnum>,
+ &ContainerStatus,
+ ),
+ ) -> Self {
+ input.map_or(Self::Unknown, |input| Self::from((input, status)))
+ }
+}
+
/// Again, need status, to check if container is unhealthy or not
impl From<(Option, &ContainerStatus)> for State {
fn from((input, status): (Option, &ContainerStatus)) -> Self {
@@ -563,81 +598,177 @@ impl LogsTz {
/// stateful list dependent on whether the timestamp is in the HashSet or not
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Logs {
- logs: StatefulList>,
+ lines: StatefulList>,
tz: HashSet,
+ offset: u16,
+ max_log_len: usize,
+ adjusted_max_width: usize,
+ adjust_max_width_text_len: usize,
}
impl Default for Logs {
fn default() -> Self {
- let mut logs = StatefulList::new(vec![]);
- logs.end();
+ let mut lines = StatefulList::new(vec![]);
+ lines.end();
Self {
- logs,
+ lines,
tz: HashSet::new(),
+ offset: 0,
+ adjusted_max_width: 0,
+ adjust_max_width_text_len: 0,
+ max_log_len: 0,
}
}
}
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: ListItem<'static>, tz: LogsTz) {
+ pub fn insert(&mut self, line: Text<'static>, tz: LogsTz) {
if self.tz.insert(tz) {
- self.logs.items.push(line);
+ self.max_log_len = self.max_log_len.max(line.width());
+ self.lines.items.push(line);
}
}
- /// Get the logs vec, but instead of cloning to whole vec, only clone items with x of the currently selected index
+ /// If scrolling horiztonally 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 {
+ if self.horizontal_scroll_able(width) {
+ let text_width = self.adjust_max_width_text_len;
+ let arrow_left = if self.offset > 0 { " ←" } else { " " };
+ let arrow_right = if usize::from(self.offset) < self.adjusted_max_width {
+ "→ "
+ } else {
+ " "
+ };
+ Some(format!(
+ "{left} {offset:>text_width$}/{adjusted_max_width} {right}",
+ offset = self.offset,
+ adjusted_max_width = self.adjusted_max_width,
+ left = arrow_left,
+ right = arrow_right,
+ ))
+ } else {
+ None
+ }
+ }
+
+ /// Format a log lone. Only return screen width amount of chars
+ /// If offset set, remove `char_offset` number of chars from a Text
+ /// `text` *should* only be a single line, so just use the .first() method rather than trying to iterate
+ fn format_log_line(text: &Text<'static>, char_offset: usize, width: u16) -> Text<'static> {
+ let mut skipped = 0;
+ text.lines.first().map_or_else(Text::default, |line| {
+ Text::from(Line::from(
+ line.spans
+ .iter()
+ .filter_map(|span| {
+ if skipped >= char_offset {
+ Some(ratatui::text::Span::styled(
+ span.content.chars().take(width.into()).collect::(),
+ span.style,
+ ))
+ } else {
+ let span_len = span.content.chars().count();
+ if skipped + span_len <= char_offset {
+ skipped += span_len;
+ None
+ } else {
+ let start_index = char_offset - skipped;
+ skipped = char_offset;
+ Some(ratatui::text::Span::styled(
+ span.content
+ .chars()
+ .skip(start_index)
+ .take(width.into())
+ .collect::(),
+ span.style,
+ ))
+ }
+ }
+ })
+ .collect::>(),
+ ))
+ })
+ }
+
+ /// Get the logs vec, but instead of cloning to whole vec, only clone items within x of the currently selected index, as well as only the current screen widths number of chars
/// Where x is the abs different of the index plus the panel height & a padding
+ /// Take into account the char offset, so that can scroll a line
/// The rest can be just empty list items
- pub fn to_vec(&self, height: usize, padding: usize) -> Vec> {
- let current_index = self.logs.state.selected().unwrap_or_default();
- self.logs
+ pub fn get_visible_logs(&self, size: Size, padding: usize) -> Vec> {
+ let current_index = self.lines.state.selected().unwrap_or_default();
+ let height_padding = usize::from(size.height) + padding;
+ let char_offset = if usize::from(self.offset) > self.max_log_len {
+ self.max_log_len
+ } else {
+ self.offset.into()
+ };
+
+ self.lines
.items
.iter()
.enumerate()
.map(|(index, item)| {
- if current_index.abs_diff(index) <= height + padding {
- item.clone()
+ if current_index.abs_diff(index) <= height_padding {
+ Self::format_log_line(item, char_offset, size.width)
} else {
- ListItem::from("")
+ Text::from("")
}
})
.collect()
}
+
/// The rest of the methods are basically forwarding from the underlying StatefulList
pub fn get_state_title(&self) -> String {
- self.logs.get_state_title()
+ self.lines.get_state_title()
+ }
+
+ /// Return true it currently selected cotnainer 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;
+ }
+ self.adjusted_max_width = self.max_log_len.saturating_sub(width.into()) + 4;
+ self.adjust_max_width_text_len = self.adjusted_max_width.to_string().chars().count();
+ self.max_log_len + 4 > usize::from(width)
+ }
+
+ /// Add a padding so one char will always be visilbe?
+ pub fn forward(&mut self, width: u16) {
+ let offset = usize::from(self.offset);
+ if self.horizontal_scroll_able(width) {
+ if self.adjusted_max_width > 0 && offset < self.adjusted_max_width {
+ self.offset = self.offset.saturating_add(1);
+ }
+ }
+ }
+
+ /// Reduce the char offset
+ pub const fn back(&mut self) {
+ self.offset = self.offset.saturating_sub(1);
}
pub fn next(&mut self) {
- self.logs.next();
+ self.lines.next();
}
pub fn previous(&mut self) {
- self.logs.previous();
+ self.lines.previous();
}
pub fn end(&mut self) {
- self.logs.end();
+ self.lines.end();
}
pub fn start(&mut self) {
- self.logs.start();
+ self.lines.start();
}
- // TODO remove this once zigbuild uses Rust v1.87.0
- #[cfg(target_os = "macos")]
- #[allow(clippy::missing_const_for_fn)]
- pub fn len(&self) -> usize {
- self.logs.items.len()
- }
-
- #[cfg(not(target_os = "macos"))]
pub const fn len(&self) -> usize {
- self.logs.items.len()
+ self.lines.items.len()
}
pub const fn state(&mut self) -> &mut ListState {
- &mut self.logs.state
+ &mut self.lines.state
}
}
@@ -801,7 +932,10 @@ impl Columns {
mod tests {
use jiff::tz::TimeZone;
- use ratatui::widgets::ListItem;
+ use ratatui::{
+ layout::Size,
+ text::{Line, Text},
+ };
use crate::{
app_data::{ContainerImage, Logs, LogsTz, RunningState},
@@ -941,21 +1075,21 @@ mod tests {
let mut logs = Logs::default();
let line = log_sanitizer::remove_ansi(input);
- logs.insert(ListItem::new(line.clone()), tz.clone());
- logs.insert(ListItem::new(line.clone()), tz.clone());
- logs.insert(ListItem::new(line), tz);
+ logs.insert(Text::from(line.clone()), tz.clone());
+ logs.insert(Text::from(line.clone()), tz.clone());
+ logs.insert(Text::from(line), tz);
- assert_eq!(logs.logs.items.len(), 1);
+ assert_eq!(logs.lines.items.len(), 1);
let input = "2023-01-15T19:13:30.783138328Z Lorem ipsum dolor sit amet";
let (tz, _) = LogsTz::splitter(input);
let line = log_sanitizer::remove_ansi(input);
- logs.insert(ListItem::new(line.clone()), tz.clone());
- logs.insert(ListItem::new(line.clone()), tz.clone());
- logs.insert(ListItem::new(line), tz);
+ logs.insert(Text::from(line.clone()), tz.clone());
+ logs.insert(Text::from(line.clone()), tz.clone());
+ logs.insert(Text::from(line), tz);
- assert_eq!(logs.logs.items.len(), 2);
+ assert_eq!(logs.lines.items.len(), 2);
}
#[test]
@@ -1008,4 +1142,73 @@ mod tests {
let input = State::from(("oxker", &healthy));
assert_eq!(input, State::Unknown);
}
+
+ #[test]
+ /// Test the format_log_line methods, should ideally check colours are being correct kept as well
+ fn test_to_vec() {
+ let mut logs = Logs::default();
+
+ 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);
+
+ 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);
+
+ let input = "2023-01-14T19:13:32.783138328Z Hello world".to_owned();
+ let (tz, _) = LogsTz::splitter(&input);
+ logs.insert(Text::from(input), tz);
+
+ logs.offset = 43;
+ let result = logs.get_visible_logs(
+ Size {
+ width: 14,
+ height: 10,
+ },
+ 10,
+ );
+ assert_eq!(
+ vec![
+ Text::from(Line::from("some long line")),
+ Text::from(Line::from("some line")),
+ Text::from(Line::default())
+ ],
+ result
+ );
+ }
+
+ #[test]
+ /// Test the get_scroll_title methods
+ fn test_scroll_title() {
+ let mut logs = Logs::default();
+
+ let result = logs.get_scroll_title(10);
+ assert!(result.is_none());
+
+ let input = "short".to_owned();
+ let (tz, _) = LogsTz::splitter(&input);
+ logs.insert(Text::from(input), tz);
+
+ 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);
+
+ let result = logs.get_scroll_title(10);
+ assert_eq!(result, Some(" 0/51 → ".to_owned()));
+
+ logs.forward(10);
+
+ let result = logs.get_scroll_title(10);
+ assert_eq!(result, Some(" ← 1/51 → ".to_owned()));
+
+ for _ in 0..=49 {
+ logs.forward(10);
+ }
+ let result = logs.get_scroll_title(10);
+ assert_eq!(result, Some(" ← 51/51 ".to_owned()));
+ }
}
diff --git a/src/app_data/mod.rs b/src/app_data/mod.rs
index 3301476..ab7993e 100644
--- a/src/app_data/mod.rs
+++ b/src/app_data/mod.rs
@@ -1,7 +1,7 @@
use bollard::models::ContainerSummary;
use core::fmt;
use parking_lot::Mutex;
-use ratatui::widgets::{ListItem, ListState};
+use ratatui::{layout::Size, text::Text, widgets::ListState};
use std::{
hash::Hash,
sync::Arc,
@@ -122,7 +122,7 @@ pub struct AppData {
error: Option,
filter: Filter,
hidden_containers: Vec,
- redraw: Arc,
+ rerender: Arc,
sorted_by: Option<(Header, SortedOrder)>,
current_sorted_id: Vec,
pub config: Config,
@@ -137,7 +137,7 @@ pub struct AppData {
pub filter: Filter,
pub hidden_containers: Vec,
pub current_sorted_id: Vec,
- pub redraw: Arc,
+ pub rerender: Arc,
pub sorted_by: Option<(Header, SortedOrder)>,
}
@@ -151,7 +151,7 @@ impl AppData {
error: None,
filter: Filter::new(),
hidden_containers: vec![],
- redraw: Arc::clone(redraw),
+ rerender: Arc::clone(redraw),
sorted_by: None,
}
}
@@ -192,7 +192,7 @@ impl AppData {
/// sets the state to start if any filtering has occurred
/// Also search in the "hidden" vec for items and insert back into the main containers vec
fn filter_containers(&mut self) {
- self.redraw.update();
+ self.rerender.update_draw();
let pre_len = self.get_container_len();
if !self.hidden_containers.is_empty() {
@@ -296,7 +296,7 @@ impl AppData {
/// Remove the sorted header & order, and sort by default - created datetime
pub fn reset_sorted(&mut self) {
self.set_sorted(None);
- self.redraw.update();
+ self.rerender.update_draw();
}
/// Sort containers based on a given header, if headings match, and already ascending, remove sorting
@@ -392,7 +392,7 @@ impl AppData {
self.containers.items.sort_by(sort_closure);
if pre_order != self.get_current_ids() {
- self.redraw.update();
+ self.rerender.update_draw();
}
} else if self.current_sorted_id != self.get_current_ids() {
self.containers.items.sort_by(|a, b| {
@@ -400,20 +400,13 @@ impl AppData {
.cmp(&b.created)
.then_with(|| a.name.get().cmp(b.name.get()))
});
- self.redraw.update();
+ self.rerender.update_draw();
self.current_sorted_id = self.get_current_ids();
}
}
/// Container state methods
/// Get the total number of none "hidden" containers
- // TODO remove this once zigbuild uses Rust v1.87.0
- #[cfg(target_os = "macos")]
- pub fn get_container_len(&self) -> usize {
- self.containers.items.len()
- }
-
- #[cfg(not(target_os = "macos"))]
pub const fn get_container_len(&self) -> usize {
self.containers.items.len()
}
@@ -446,25 +439,25 @@ impl AppData {
/// Select the first container
pub fn containers_start(&mut self) {
self.containers.start();
- self.redraw.update();
+ self.rerender.update_draw();
}
/// select the last container
pub fn containers_end(&mut self) {
self.containers.end();
- self.redraw.update();
+ self.rerender.update_draw();
}
/// Select the next container
pub fn containers_next(&mut self) {
self.containers.next();
- self.redraw.update();
+ self.rerender.update_draw();
}
/// select the previous container
pub fn containers_previous(&mut self) {
self.containers.previous();
- self.redraw.update();
+ self.rerender.update_draw();
}
/// Get ListState of containers
@@ -586,7 +579,7 @@ impl AppData {
pub fn docker_controls_next(&mut self) {
if let Some(i) = self.get_mut_selected_container() {
i.docker_controls.next();
- self.redraw.update();
+ self.rerender.update_draw();
}
}
@@ -594,7 +587,7 @@ impl AppData {
pub fn docker_controls_previous(&mut self) {
if let Some(i) = self.get_mut_selected_container() {
i.docker_controls.previous();
- self.redraw.update();
+ self.rerender.update_draw();
}
}
@@ -602,7 +595,7 @@ impl AppData {
pub fn docker_controls_start(&mut self) {
if let Some(i) = self.get_mut_selected_container() {
i.docker_controls.start();
- self.redraw.update();
+ self.rerender.update_draw();
}
}
@@ -610,7 +603,7 @@ impl AppData {
pub fn docker_controls_end(&mut self) {
if let Some(i) = self.get_mut_selected_container() {
i.docker_controls.end();
- self.redraw.update();
+ self.rerender.update_draw();
}
}
@@ -644,11 +637,33 @@ impl AppData {
})
}
+ /// If scrolling horiztonally 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 {
+ 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();
+ }
+ }
+
/// select next selected log line
pub fn log_next(&mut self) {
if let Some(i) = self.get_mut_selected_container() {
i.logs.next();
- self.redraw.update();
+ self.rerender.update_draw();
}
}
@@ -656,7 +671,7 @@ impl AppData {
pub fn log_previous(&mut self) {
if let Some(i) = self.get_mut_selected_container() {
i.logs.previous();
- self.redraw.update();
+ self.rerender.update_draw();
}
}
@@ -664,7 +679,7 @@ impl AppData {
pub fn log_end(&mut self) {
if let Some(i) = self.get_mut_selected_container() {
i.logs.end();
- self.redraw.update();
+ self.rerender.update_draw();
}
}
@@ -672,17 +687,17 @@ impl AppData {
pub fn log_start(&mut self) {
if let Some(i) = self.get_mut_selected_container() {
i.logs.start();
- self.redraw.update();
+ self.rerender.update_draw();
}
}
/// Get mutable Vec of current containers logs
- pub fn get_logs(&self, height: u16, padding: usize) -> Vec> {
+ pub fn get_logs(&self, size: Size, padding: usize) -> Vec> {
self.containers
.state
.selected()
.and_then(|i| self.containers.items.get(i))
- .map_or(vec![], |i| i.logs.to_vec(height.into(), padding))
+ .map_or(vec![], |i| i.logs.get_visible_logs(size, padding))
}
/// Get mutable Option of the currently selected container Logs state
@@ -713,14 +728,14 @@ impl AppData {
/// Remove single app_state error
pub fn remove_error(&mut self) {
self.error = None;
- self.redraw.update();
+ self.rerender.update_draw();
}
/// Insert single app_state error
pub fn set_error(&mut self, error: AppError, gui_state: &Arc>, status: Status) {
gui_state.lock().status_push(status);
self.error = Some(error);
- self.redraw.update();
+ self.rerender.update_draw();
}
/// Check if the selected container is a dockerised version of oxker
@@ -810,7 +825,7 @@ impl AppData {
container.mem_limit.update(mem_limit);
}
if self.is_selected_container(id) {
- self.redraw.update();
+ self.rerender.update_draw();
}
self.sort_containers();
}
@@ -848,7 +863,7 @@ impl AppData {
if self.containers.items.get(index).is_some() {
self.containers.items.remove(index);
if self.is_selected_container(id) {
- self.redraw.update();
+ self.rerender.update_draw();
}
}
}
@@ -881,7 +896,12 @@ impl AppData {
.as_ref()
.map_or(String::new(), std::clone::Clone::clone),
);
- let state = State::from((i.state.as_ref().map_or("dead", |z| z), &status));
+ let state = State::from((
+ i.state
+ .as_ref()
+ .map_or(&bollard::secret::ContainerSummaryStateEnum::DEAD, |z| z),
+ &status,
+ ));
let image = i
.image
.as_ref()
@@ -965,7 +985,7 @@ impl AppData {
} else {
log_sanitizer::remove_ansi(&i)
};
- container.logs.insert(ListItem::new(lines), log_tz);
+ container.logs.insert(Text::from(lines), log_tz);
}
// Set the logs selected row for each container
@@ -977,7 +997,7 @@ impl AppData {
}
}
if self.is_selected_container(id) {
- self.redraw.update();
+ self.rerender.update_draw();
}
}
}
@@ -1945,14 +1965,19 @@ mod tests {
let logs = (1..=3).map(|i| format!("{i} {i}")).collect::>();
app_data.update_log_by_id(logs, &ids[0]);
- // app_data.log_start();
let result = app_data.get_log_state();
assert!(result.is_some());
assert_eq!(result.as_ref().unwrap().selected(), Some(2));
assert_eq!(result.unwrap().offset(), 0);
- let result = app_data.get_logs(4, 1);
+ let result = app_data.get_logs(
+ Size {
+ width: 20,
+ height: 4,
+ },
+ 1,
+ );
assert_eq!(result.len(), 3);
let result = app_data.get_log_title();
@@ -2340,44 +2365,68 @@ mod tests {
app_data.update_log_by_id(logs, &ids[0]);
- let result = app_data.get_logs(10, 10);
+ let result = app_data.get_logs(
+ Size {
+ width: 20,
+ height: 10,
+ },
+ 10,
+ );
for (index, item) in result.iter().enumerate() {
if index < 979 {
- assert_eq!(item, &ListItem::new(""));
+ assert_eq!(item, &Text::from(""));
} else {
- assert_eq!(item, &ListItem::new(format!("{index}")));
+ assert_eq!(item, &Text::from(format!("{index}")));
}
}
- let result = app_data.get_logs(100, 20);
+ let result = app_data.get_logs(
+ Size {
+ width: 20,
+ height: 100,
+ },
+ 20,
+ );
for (index, item) in result.iter().enumerate() {
if index < 879 {
- assert_eq!(item, &ListItem::new(""));
+ assert_eq!(item, &Text::from(""));
} else {
- assert_eq!(item, &ListItem::new(format!("{index}")));
+ assert_eq!(item, &Text::from(format!("{index}")));
}
}
app_data.log_start();
- let result = app_data.get_logs(10, 10);
+
+ let result = app_data.get_logs(
+ Size {
+ width: 20,
+ height: 10,
+ },
+ 10,
+ );
for (index, item) in result.iter().enumerate() {
if index > 20 {
- assert_eq!(item, &ListItem::new(""));
+ assert_eq!(item, &Text::from(""));
} else {
- assert_eq!(item, &ListItem::new(format!("{index}")));
+ assert_eq!(item, &Text::from(format!("{index}")));
}
}
for _ in 0..=500 {
app_data.log_next();
}
-
- let result = app_data.get_logs(10, 10);
+ let result = app_data.get_logs(
+ Size {
+ width: 20,
+ height: 10,
+ },
+ 10,
+ );
for (index, item) in result.iter().enumerate() {
if (481..=521).contains(&index) {
- assert_eq!(item, &ListItem::new(format!("{index}")));
+ assert_eq!(item, &Text::from(format!("{index}")));
} else {
- assert_eq!(item, &ListItem::new(""));
+ assert_eq!(item, &Text::from(""));
}
}
}
diff --git a/src/config/config.toml b/src/config/config.toml
index 457064a..182e7c5 100644
--- a/src/config/config.toml
+++ b/src/config/config.toml
@@ -56,6 +56,9 @@ show_logs = true
# 4) backspace, tab, backtab, delete, end, esc, home, insert, pagedown, pageup, left, right, up, down
# Each definition can have two keys associated with it
+
+# WARNING "scroll_many" only accepts control, alt, shift, with no secondary option
+
# If any key clashes are found, oxker will revert to it's default keymap
[keymap]
@@ -73,18 +76,28 @@ filter_mode = ["/", "F1"]
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 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
+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"]
+# Horizontal scroll of the logs
+log_scroll_forward = ["right"]
+log_scroll_back = ["left"]
# Select next panel
select_next_panel = ["tab"]
# Select previous panel
@@ -110,6 +123,8 @@ 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"]
#################
# Custom Colors #
diff --git a/src/config/keymap_parser.rs b/src/config/keymap_parser.rs
index 9847800..3f62e44 100644
--- a/src/config/keymap_parser.rs
+++ b/src/config/keymap_parser.rs
@@ -1,6 +1,6 @@
use std::collections::HashSet;
-use crossterm::event::KeyCode;
+use crossterm::event::{KeyCode, KeyModifiers};
/// The macro accepts a list of struct names with key names
/// Returns a struct where every key name is an Option, with the correct derived attributes
@@ -12,6 +12,7 @@ macro_rules! optional_config_struct {
$(
$key_name: Option>,
)*
+ pub scroll_many: Option>,
}
)*
};
@@ -24,9 +25,10 @@ macro_rules! config_struct {
$(
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct $struct_name {
- $(
+ $(
pub $key_name: (KeyCode, Option),
)*
+ pub scroll_many: KeyModifiers,
}
)*
};
@@ -35,6 +37,7 @@ macro_rules! config_struct {
optional_config_struct!(
ConfigKeymap,
clear,
+ force_redraw,
delete_deny,
delete_confirm,
exec,
@@ -42,13 +45,19 @@ optional_config_struct!(
log_section_height_increase,
log_section_height_decrease,
log_section_toggle,
+ log_scroll_forward,
+ log_scroll_back,
quit,
save_logs,
+ // TODO remove in next release
scroll_down_many,
+ // TODO rename in next release
scroll_down_one,
scroll_end,
scroll_start,
+ // TODO remove in next release
scroll_up_many,
+ // TODO rename in next release
scroll_up_one,
select_next_panel,
select_previous_panel,
@@ -73,16 +82,23 @@ config_struct!(
delete_confirm,
exec,
filter_mode,
+ force_redraw,
log_section_height_increase,
log_section_height_decrease,
log_section_toggle,
+ log_scroll_forward,
+ log_scroll_back,
quit,
save_logs,
+ // TODO remove in next release
scroll_down_many,
+ // TODO rename in next release
scroll_down_one,
scroll_end,
scroll_start,
+ // TODO remove in next release
scroll_up_many,
+ // TODO rename in next release
scroll_up_one,
select_next_panel,
select_previous_panel,
@@ -108,16 +124,24 @@ impl Keymap {
delete_deny: (KeyCode::Char('n'), None),
exec: (KeyCode::Char('e'), None),
filter_mode: (KeyCode::Char('/'), Some(KeyCode::F(1))),
+ force_redraw: (KeyCode::Char('f'), 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_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'))),
select_next_panel: (KeyCode::Tab, None),
select_previous_panel: (KeyCode::BackTab, None),
@@ -189,6 +213,7 @@ impl From