mirror of
https://github.com/ratatui-org/ratatui
synced 2025-02-16 14:08:44 +00:00
Merge branch 'main' into jm/fix-canvas-rounding
This commit is contained in:
commit
c75b2802e0
12 changed files with 256 additions and 80 deletions
4
.github/workflows/ci.yml
vendored
4
.github/workflows/ci.yml
vendored
|
@ -75,7 +75,7 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: DavidAnson/markdownlint-cli2-action@v17
|
- uses: DavidAnson/markdownlint-cli2-action@v18
|
||||||
with:
|
with:
|
||||||
globs: |
|
globs: |
|
||||||
'**/*.md'
|
'**/*.md'
|
||||||
|
@ -94,7 +94,7 @@ jobs:
|
||||||
- uses: taiki-e/install-action@cargo-llvm-cov
|
- uses: taiki-e/install-action@cargo-llvm-cov
|
||||||
- uses: Swatinem/rust-cache@v2
|
- uses: Swatinem/rust-cache@v2
|
||||||
- run: cargo xtask coverage
|
- run: cargo xtask coverage
|
||||||
- uses: codecov/codecov-action@v4
|
- uses: codecov/codecov-action@v5
|
||||||
with:
|
with:
|
||||||
token: ${{ secrets.CODECOV_TOKEN }}
|
token: ${{ secrets.CODECOV_TOKEN }}
|
||||||
fail_ci_if_error: true
|
fail_ci_if_error: true
|
||||||
|
|
91
Cargo.lock
generated
91
Cargo.lock
generated
|
@ -367,8 +367,10 @@ checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"android-tzdata",
|
"android-tzdata",
|
||||||
"iana-time-zone",
|
"iana-time-zone",
|
||||||
|
"js-sys",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
"serde",
|
"serde",
|
||||||
|
"wasm-bindgen",
|
||||||
"windows-targets",
|
"windows-targets",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -401,9 +403,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap"
|
name = "clap"
|
||||||
version = "4.5.20"
|
version = "4.5.21"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8"
|
checksum = "fb3b4b9e5a7c7514dfa52869339ee98b3156b0bfb4e8a77c4ff4babb64b1604f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap_builder",
|
"clap_builder",
|
||||||
"clap_derive",
|
"clap_derive",
|
||||||
|
@ -422,9 +424,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap-verbosity-flag"
|
name = "clap-verbosity-flag"
|
||||||
version = "2.2.2"
|
version = "2.2.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e099138e1807662ff75e2cebe4ae2287add879245574489f9b1588eb5e5564ed"
|
checksum = "34c77f67047557f62582784fd7482884697731b2932c7d37ced54bce2312e1e2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap",
|
"clap",
|
||||||
"log",
|
"log",
|
||||||
|
@ -432,9 +434,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap_builder"
|
name = "clap_builder"
|
||||||
version = "4.5.20"
|
version = "4.5.21"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54"
|
checksum = "b17a95aa67cc7b5ebd32aa5370189aa0d79069ef1c64ce893bd30fb24bff20ec"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anstream",
|
"anstream",
|
||||||
"anstyle",
|
"anstyle",
|
||||||
|
@ -664,6 +666,41 @@ dependencies = [
|
||||||
"phf",
|
"phf",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "darling"
|
||||||
|
version = "0.20.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989"
|
||||||
|
dependencies = [
|
||||||
|
"darling_core",
|
||||||
|
"darling_macro",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "darling_core"
|
||||||
|
version = "0.20.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5"
|
||||||
|
dependencies = [
|
||||||
|
"fnv",
|
||||||
|
"ident_case",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"strsim 0.11.1",
|
||||||
|
"syn 2.0.85",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "darling_macro"
|
||||||
|
version = "0.20.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806"
|
||||||
|
dependencies = [
|
||||||
|
"darling_core",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.85",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deltae"
|
name = "deltae"
|
||||||
version = "0.3.2"
|
version = "0.3.2"
|
||||||
|
@ -1175,6 +1212,12 @@ dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ident_case"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "idna"
|
name = "idna"
|
||||||
version = "0.5.0"
|
version = "0.5.0"
|
||||||
|
@ -1209,10 +1252,14 @@ checksum = "b248f5224d1d606005e02c97f5aa4e88eeb230488bcc03bc9ca4d7991399f2b5"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "instability"
|
name = "instability"
|
||||||
version = "0.3.2"
|
version = "0.3.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b23a0c8dfe501baac4adf6ebbfa6eddf8f0c07f56b058cc1288017e32397846c"
|
checksum = "b829f37dead9dc39df40c2d3376c179fdfd2ac771f53f55d3c30dc096a3c0c6e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"darling",
|
||||||
|
"indoc",
|
||||||
|
"pretty_assertions",
|
||||||
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn 2.0.85",
|
"syn 2.0.85",
|
||||||
]
|
]
|
||||||
|
@ -1561,9 +1608,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "octocrab"
|
name = "octocrab"
|
||||||
version = "0.41.2"
|
version = "0.42.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e2dfd11f6efbd39491d71a3864496f0b6f45e2d01b73b26c55d631c4e0dafaef"
|
checksum = "5235d5839910001bef2c3df99a88688c7c781e5b1fd5fe40c5d8fa8bd786ac5a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arc-swap",
|
"arc-swap",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
|
@ -1596,6 +1643,7 @@ dependencies = [
|
||||||
"tower-http",
|
"tower-http",
|
||||||
"tracing",
|
"tracing",
|
||||||
"url",
|
"url",
|
||||||
|
"web-time",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1909,9 +1957,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.88"
|
version = "1.0.89"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7c3a7fc5db1e57d5a779a352c8cdb57b29aa4c40cc69c3a68a7fedc815fbf2f9"
|
checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
@ -2492,18 +2540,18 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.214"
|
version = "1.0.215"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f55c3193aca71c12ad7890f1785d2b73e1b9f63a0bbc353c08ef26fe03fc56b5"
|
checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.214"
|
version = "1.0.215"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766"
|
checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
@ -3357,6 +3405,17 @@ dependencies = [
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "web-time"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb"
|
||||||
|
dependencies = [
|
||||||
|
"js-sys",
|
||||||
|
"serde",
|
||||||
|
"wasm-bindgen",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wezterm-bidi"
|
name = "wezterm-bidi"
|
||||||
version = "0.2.3"
|
version = "0.2.3"
|
||||||
|
|
|
@ -27,14 +27,14 @@ rust-version = "1.74.0"
|
||||||
bitflags = "2.6.0"
|
bitflags = "2.6.0"
|
||||||
document-features = "0.2.7"
|
document-features = "0.2.7"
|
||||||
indoc = "2.0.5"
|
indoc = "2.0.5"
|
||||||
instability = "0.3.1"
|
instability = "0.3.3"
|
||||||
itertools = "0.13.0"
|
itertools = "0.13.0"
|
||||||
pretty_assertions = "1.4.1"
|
pretty_assertions = "1.4.1"
|
||||||
ratatui = { path = "ratatui" }
|
ratatui = { path = "ratatui" }
|
||||||
ratatui-core = { path = "ratatui-core" }
|
ratatui-core = { path = "ratatui-core" }
|
||||||
ratatui-widgets = { path = "ratatui-widgets" }
|
ratatui-widgets = { path = "ratatui-widgets" }
|
||||||
rstest = "0.23.0"
|
rstest = "0.23.0"
|
||||||
serde = { version = "1.0.214", features = ["derive"] }
|
serde = { version = "1.0.215", features = ["derive"] }
|
||||||
strum = { version = "0.26.3", features = ["derive"] }
|
strum = { version = "0.26.3", features = ["derive"] }
|
||||||
unicode-segmentation = "1.12.0"
|
unicode-segmentation = "1.12.0"
|
||||||
# See <https://github.com/ratatui/ratatui/issues/1271> for information about why we pin unicode-width
|
# See <https://github.com/ratatui/ratatui/issues/1271> for information about why we pin unicode-width
|
||||||
|
|
52
bacon.toml
52
bacon.toml
|
@ -8,26 +8,17 @@
|
||||||
default_job = "check"
|
default_job = "check"
|
||||||
|
|
||||||
[jobs.check]
|
[jobs.check]
|
||||||
command = ["cargo", "check", "--all-features", "--color", "always"]
|
command = ["cargo", "check", "--all-features"]
|
||||||
need_stdout = false
|
need_stdout = false
|
||||||
|
|
||||||
[jobs.check-all]
|
[jobs.check-all]
|
||||||
command = [
|
command = ["cargo", "check", "--all-targets", "--all-features"]
|
||||||
"cargo",
|
|
||||||
"check",
|
|
||||||
"--all-targets",
|
|
||||||
"--all-features",
|
|
||||||
"--color",
|
|
||||||
"always",
|
|
||||||
]
|
|
||||||
need_stdout = false
|
need_stdout = false
|
||||||
|
|
||||||
[jobs.check-crossterm]
|
[jobs.check-crossterm]
|
||||||
command = [
|
command = [
|
||||||
"cargo",
|
"cargo",
|
||||||
"check",
|
"check",
|
||||||
"--color",
|
|
||||||
"always",
|
|
||||||
"--all-targets",
|
"--all-targets",
|
||||||
"--no-default-features",
|
"--no-default-features",
|
||||||
"--features",
|
"--features",
|
||||||
|
@ -39,8 +30,6 @@ need_stdout = false
|
||||||
command = [
|
command = [
|
||||||
"cargo",
|
"cargo",
|
||||||
"check",
|
"check",
|
||||||
"--color",
|
|
||||||
"always",
|
|
||||||
"--all-targets",
|
"--all-targets",
|
||||||
"--no-default-features",
|
"--no-default-features",
|
||||||
"--features",
|
"--features",
|
||||||
|
@ -52,8 +41,6 @@ need_stdout = false
|
||||||
command = [
|
command = [
|
||||||
"cargo",
|
"cargo",
|
||||||
"check",
|
"check",
|
||||||
"--color",
|
|
||||||
"always",
|
|
||||||
"--all-targets",
|
"--all-targets",
|
||||||
"--no-default-features",
|
"--no-default-features",
|
||||||
"--features",
|
"--features",
|
||||||
|
@ -62,34 +49,15 @@ command = [
|
||||||
need_stdout = false
|
need_stdout = false
|
||||||
|
|
||||||
[jobs.clippy]
|
[jobs.clippy]
|
||||||
command = ["cargo", "clippy", "--all-targets", "--color", "always"]
|
command = ["cargo", "clippy", "--all-targets"]
|
||||||
need_stdout = false
|
need_stdout = false
|
||||||
|
|
||||||
[jobs.test]
|
[jobs.test]
|
||||||
command = [
|
command = ["cargo", "test", "--all-features"]
|
||||||
"cargo",
|
|
||||||
"test",
|
|
||||||
"--all-features",
|
|
||||||
"--color",
|
|
||||||
"always",
|
|
||||||
"--",
|
|
||||||
"--color",
|
|
||||||
"always", # see https://github.com/Canop/bacon/issues/124
|
|
||||||
]
|
|
||||||
need_stdout = true
|
need_stdout = true
|
||||||
|
|
||||||
[jobs.test-unit]
|
[jobs.test-unit]
|
||||||
command = [
|
command = ["cargo", "test", "--lib", "--all-features"]
|
||||||
"cargo",
|
|
||||||
"test",
|
|
||||||
"--lib",
|
|
||||||
"--all-features",
|
|
||||||
"--color",
|
|
||||||
"always",
|
|
||||||
"--",
|
|
||||||
"--color",
|
|
||||||
"always", # see https://github.com/Canop/bacon/issues/124
|
|
||||||
]
|
|
||||||
need_stdout = true
|
need_stdout = true
|
||||||
|
|
||||||
[jobs.doc]
|
[jobs.doc]
|
||||||
|
@ -100,8 +68,6 @@ command = [
|
||||||
"-Zunstable-options",
|
"-Zunstable-options",
|
||||||
"-Zrustdoc-scrape-examples",
|
"-Zrustdoc-scrape-examples",
|
||||||
"--all-features",
|
"--all-features",
|
||||||
"--color",
|
|
||||||
"always",
|
|
||||||
"--no-deps",
|
"--no-deps",
|
||||||
]
|
]
|
||||||
env.RUSTDOCFLAGS = "--cfg docsrs"
|
env.RUSTDOCFLAGS = "--cfg docsrs"
|
||||||
|
@ -117,8 +83,6 @@ command = [
|
||||||
"-Zunstable-options",
|
"-Zunstable-options",
|
||||||
"-Zrustdoc-scrape-examples",
|
"-Zrustdoc-scrape-examples",
|
||||||
"--all-features",
|
"--all-features",
|
||||||
"--color",
|
|
||||||
"always",
|
|
||||||
"--no-deps",
|
"--no-deps",
|
||||||
"--open",
|
"--open",
|
||||||
]
|
]
|
||||||
|
@ -134,8 +98,6 @@ command = [
|
||||||
"--output-path",
|
"--output-path",
|
||||||
"target/lcov.info",
|
"target/lcov.info",
|
||||||
"--all-features",
|
"--all-features",
|
||||||
"--color",
|
|
||||||
"always",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[jobs.coverage-unit-tests-only]
|
[jobs.coverage-unit-tests-only]
|
||||||
|
@ -147,8 +109,6 @@ command = [
|
||||||
"target/lcov.info",
|
"target/lcov.info",
|
||||||
"--lib",
|
"--lib",
|
||||||
"--all-features",
|
"--all-features",
|
||||||
"--color",
|
|
||||||
"always",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[jobs.hack]
|
[jobs.hack]
|
||||||
|
@ -160,8 +120,6 @@ command = [
|
||||||
"--each-feature",
|
"--each-feature",
|
||||||
# "--all-targets",
|
# "--all-targets",
|
||||||
"--workspace",
|
"--workspace",
|
||||||
"--color",
|
|
||||||
"always",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
# You may define here keybindings that would be specific to
|
# You may define here keybindings that would be specific to
|
||||||
|
|
|
@ -1,3 +1,10 @@
|
||||||
|
// show the feature flags in the generated documentation
|
||||||
|
#![cfg_attr(docsrs, feature(doc_cfg))]
|
||||||
|
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
|
||||||
|
#![doc(
|
||||||
|
html_logo_url = "https://raw.githubusercontent.com/ratatui/ratatui/main/assets/logo.png",
|
||||||
|
html_favicon_url = "https://raw.githubusercontent.com/ratatui/ratatui/main/assets/favicon.ico"
|
||||||
|
)]
|
||||||
//! **ratatui-core** is the core library of the [ratatui] project,
|
//! **ratatui-core** is the core library of the [ratatui] project,
|
||||||
//! providing the essential building blocks for creating rich terminal user interfaces in Rust.
|
//! providing the essential building blocks for creating rich terminal user interfaces in Rust.
|
||||||
//!
|
//!
|
||||||
|
|
|
@ -121,7 +121,7 @@ pub trait StatefulWidget {
|
||||||
/// If you don't need this then you probably want to implement [`Widget`] instead.
|
/// If you don't need this then you probably want to implement [`Widget`] instead.
|
||||||
///
|
///
|
||||||
/// [`Widget`]: super::Widget
|
/// [`Widget`]: super::Widget
|
||||||
type State;
|
type State: ?Sized;
|
||||||
/// Draws the current state of the widget in the given buffer. That is the only method required
|
/// Draws the current state of the widget in the given buffer. That is the only method required
|
||||||
/// to implement a custom stateful widget.
|
/// to implement a custom stateful widget.
|
||||||
fn render(self, area: Rect, buf: &mut Buffer, state: &mut Self::State);
|
fn render(self, area: Rect, buf: &mut Buffer, state: &mut Self::State);
|
||||||
|
@ -159,4 +159,23 @@ mod tests {
|
||||||
widget.render(buf.area, &mut buf, &mut state);
|
widget.render(buf.area, &mut buf, &mut state);
|
||||||
assert_eq!(buf, Buffer::with_lines(["Hello world "]));
|
assert_eq!(buf, Buffer::with_lines(["Hello world "]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct Bytes;
|
||||||
|
|
||||||
|
/// A widget with an unsized state type.
|
||||||
|
impl StatefulWidget for Bytes {
|
||||||
|
type State = [u8];
|
||||||
|
fn render(self, area: Rect, buf: &mut Buffer, state: &mut Self::State) {
|
||||||
|
let slice = std::str::from_utf8(state).unwrap();
|
||||||
|
Line::from(format!("Bytes: {slice}")).render(area, buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn render_unsized_state_type(mut buf: Buffer) {
|
||||||
|
let widget = Bytes;
|
||||||
|
let state = b"hello";
|
||||||
|
widget.render(buf.area, &mut buf, &mut state.clone());
|
||||||
|
assert_eq!(buf, Buffer::with_lines(["Bytes: hello "]));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,10 @@
|
||||||
|
// show the feature flags in the generated documentation
|
||||||
|
#![cfg_attr(docsrs, feature(doc_cfg))]
|
||||||
|
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
|
||||||
|
#![doc(
|
||||||
|
html_logo_url = "https://raw.githubusercontent.com/ratatui/ratatui/main/assets/logo.png",
|
||||||
|
html_favicon_url = "https://raw.githubusercontent.com/ratatui/ratatui/main/assets/favicon.ico"
|
||||||
|
)]
|
||||||
#![warn(missing_docs)]
|
#![warn(missing_docs)]
|
||||||
//! **ratatui-widgets** contains all the widgets that were previously part of the [Ratatui] crate.
|
//! **ratatui-widgets** contains all the widgets that were previously part of the [Ratatui] crate.
|
||||||
//! It is meant to be used in conjunction with `ratatui`, which provides the core functionality
|
//! It is meant to be used in conjunction with `ratatui`, which provides the core functionality
|
||||||
|
|
|
@ -43,7 +43,7 @@ fakeit = "1.1"
|
||||||
font8x8 = "0.3.1"
|
font8x8 = "0.3.1"
|
||||||
futures = "0.3.30"
|
futures = "0.3.30"
|
||||||
indoc = "2"
|
indoc = "2"
|
||||||
octocrab = "0.41.0"
|
octocrab = "0.42.0"
|
||||||
pretty_assertions = "1.4.0"
|
pretty_assertions = "1.4.0"
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
rand_chacha = "0.3.1"
|
rand_chacha = "0.3.1"
|
||||||
|
|
|
@ -1,3 +1,11 @@
|
||||||
|
// show the feature flags in the generated documentation
|
||||||
|
#![cfg_attr(docsrs, feature(doc_cfg))]
|
||||||
|
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
|
||||||
|
#![doc(
|
||||||
|
html_logo_url = "https://raw.githubusercontent.com/ratatui/ratatui/main/assets/logo.png",
|
||||||
|
html_favicon_url = "https://raw.githubusercontent.com/ratatui/ratatui/main/assets/favicon.ico"
|
||||||
|
)]
|
||||||
|
#![warn(missing_docs)]
|
||||||
//! ![Demo](https://github.com/ratatui/ratatui/blob/87ae72dbc756067c97f6400d3e2a58eeb383776e/examples/demo2-destroy.gif?raw=true)
|
//! ![Demo](https://github.com/ratatui/ratatui/blob/87ae72dbc756067c97f6400d3e2a58eeb383776e/examples/demo2-destroy.gif?raw=true)
|
||||||
//!
|
//!
|
||||||
//! <div align="center">
|
//! <div align="center">
|
||||||
|
@ -318,13 +326,6 @@
|
||||||
//! [Forum]: https://forum.ratatui.rs
|
//! [Forum]: https://forum.ratatui.rs
|
||||||
//! [Sponsors Badge]: https://img.shields.io/github/sponsors/ratatui?logo=github&style=flat-square&color=1370D3
|
//! [Sponsors Badge]: https://img.shields.io/github/sponsors/ratatui?logo=github&style=flat-square&color=1370D3
|
||||||
|
|
||||||
// show the feature flags in the generated documentation
|
|
||||||
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
|
|
||||||
#![doc(
|
|
||||||
html_logo_url = "https://raw.githubusercontent.com/ratatui/ratatui/main/assets/logo.png",
|
|
||||||
html_favicon_url = "https://raw.githubusercontent.com/ratatui/ratatui/main/assets/favicon.ico"
|
|
||||||
)]
|
|
||||||
|
|
||||||
/// re-export the `crossterm` crate so that users don't have to add it as a dependency
|
/// re-export the `crossterm` crate so that users don't have to add it as a dependency
|
||||||
#[cfg(feature = "crossterm")]
|
#[cfg(feature = "crossterm")]
|
||||||
pub use crossterm;
|
pub use crossterm;
|
||||||
|
|
|
@ -61,7 +61,7 @@ pub trait StatefulWidgetRef {
|
||||||
/// If you don't need this then you probably want to implement [`WidgetRef`] instead.
|
/// If you don't need this then you probably want to implement [`WidgetRef`] instead.
|
||||||
///
|
///
|
||||||
/// [`WidgetRef`]: super::WidgetRef
|
/// [`WidgetRef`]: super::WidgetRef
|
||||||
type State;
|
type State: ?Sized;
|
||||||
/// Draws the current state of the widget in the given buffer. That is the only method required
|
/// Draws the current state of the widget in the given buffer. That is the only method required
|
||||||
/// to implement a custom stateful widget.
|
/// to implement a custom stateful widget.
|
||||||
fn render_ref(&self, area: Rect, buf: &mut Buffer, state: &mut Self::State);
|
fn render_ref(&self, area: Rect, buf: &mut Buffer, state: &mut Self::State);
|
||||||
|
@ -70,7 +70,7 @@ pub trait StatefulWidgetRef {
|
||||||
/// Blanket implementation of `StatefulWidgetRef` for `&W` where `W` implements `StatefulWidget`.
|
/// Blanket implementation of `StatefulWidgetRef` for `&W` where `W` implements `StatefulWidget`.
|
||||||
///
|
///
|
||||||
/// This allows you to render a stateful widget by reference.
|
/// This allows you to render a stateful widget by reference.
|
||||||
impl<W, State> StatefulWidgetRef for &W
|
impl<W, State: ?Sized> StatefulWidgetRef for &W
|
||||||
where
|
where
|
||||||
for<'a> &'a W: StatefulWidget<State = State>,
|
for<'a> &'a W: StatefulWidget<State = State>,
|
||||||
{
|
{
|
||||||
|
@ -119,4 +119,38 @@ mod tests {
|
||||||
widget.render_ref(buf.area, &mut buf, &mut state);
|
widget.render_ref(buf.area, &mut buf, &mut state);
|
||||||
assert_eq!(buf, Buffer::with_lines(["Hello world "]));
|
assert_eq!(buf, Buffer::with_lines(["Hello world "]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn render_stateful_widget_ref_with_unsized_state(mut buf: Buffer) {
|
||||||
|
struct Bytes;
|
||||||
|
|
||||||
|
impl StatefulWidgetRef for Bytes {
|
||||||
|
type State = [u8];
|
||||||
|
fn render_ref(&self, area: Rect, buf: &mut Buffer, state: &mut Self::State) {
|
||||||
|
let slice = std::str::from_utf8(state).unwrap();
|
||||||
|
Line::from(format!("Bytes: {slice}")).render(area, buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let widget = Bytes;
|
||||||
|
let state = b"hello";
|
||||||
|
widget.render_ref(buf.area, &mut buf, &mut state.clone());
|
||||||
|
assert_eq!(buf, Buffer::with_lines(["Bytes: hello "]));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn render_stateful_widget_with_unsized_state(mut buf: Buffer) {
|
||||||
|
struct Bytes;
|
||||||
|
impl StatefulWidget for &Bytes {
|
||||||
|
type State = [u8];
|
||||||
|
fn render(self, area: Rect, buf: &mut Buffer, state: &mut Self::State) {
|
||||||
|
let slice = std::str::from_utf8(state).unwrap();
|
||||||
|
Line::from(format!("Bytes: {slice}")).render(area, buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let widget = &Bytes;
|
||||||
|
let mut state = b"hello".to_owned();
|
||||||
|
let state = state.as_mut_slice();
|
||||||
|
widget.render_ref(buf.area, &mut buf, state);
|
||||||
|
assert_eq!(buf, Buffer::with_lines(["Bytes: hello "]));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
91
ratatui/tests/stateful_widget_ref_dyn.rs
Normal file
91
ratatui/tests/stateful_widget_ref_dyn.rs
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
#![cfg(feature = "unstable-widget-ref")]
|
||||||
|
|
||||||
|
use std::{
|
||||||
|
any::{type_name, Any},
|
||||||
|
cell::RefCell,
|
||||||
|
};
|
||||||
|
|
||||||
|
use pretty_assertions::assert_eq;
|
||||||
|
use ratatui::widgets::StatefulWidgetRef;
|
||||||
|
use ratatui_core::{buffer::Buffer, layout::Rect, text::Line, widgets::Widget};
|
||||||
|
|
||||||
|
trait AnyWindow: StatefulWidgetRef<State = dyn Any> {
|
||||||
|
fn title(&self) -> &str {
|
||||||
|
type_name::<Self>()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Window1;
|
||||||
|
|
||||||
|
struct Window1State {
|
||||||
|
pub value: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AnyWindow for Window1 {}
|
||||||
|
|
||||||
|
impl StatefulWidgetRef for Window1 {
|
||||||
|
type State = dyn Any;
|
||||||
|
|
||||||
|
fn render_ref(&self, area: Rect, buf: &mut Buffer, state: &mut Self::State) {
|
||||||
|
let state = state.downcast_mut::<Window1State>().expect("window1 state");
|
||||||
|
Line::from(format!("{}, u32: {}", self.title(), state.value)).render(area, buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Window2;
|
||||||
|
|
||||||
|
struct Window2State {
|
||||||
|
pub value: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AnyWindow for Window2 {}
|
||||||
|
|
||||||
|
impl StatefulWidgetRef for Window2 {
|
||||||
|
type State = dyn Any;
|
||||||
|
|
||||||
|
fn render_ref(&self, area: Rect, buf: &mut Buffer, state: &mut Self::State) {
|
||||||
|
let state = state.downcast_mut::<Window2State>().expect("window2 state");
|
||||||
|
Line::from(format!("{}, String: {}", self.title(), state.value)).render(area, buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type BoxedWindow = Box<dyn AnyWindow>;
|
||||||
|
type BoxedState = Box<RefCell<dyn Any>>;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn render_dyn_widgets() {
|
||||||
|
let windows: Vec<(BoxedWindow, BoxedState)> = vec![
|
||||||
|
(
|
||||||
|
Box::new(Window1),
|
||||||
|
Box::new(RefCell::new(Window1State { value: 32 })),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
Box::new(Window2),
|
||||||
|
Box::new(RefCell::new(Window2State {
|
||||||
|
value: "Some".to_string(),
|
||||||
|
})),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
Box::new(Window1),
|
||||||
|
Box::new(RefCell::new(Window1State { value: 42 })),
|
||||||
|
),
|
||||||
|
];
|
||||||
|
|
||||||
|
let mut buf = Buffer::empty(Rect::new(0, 0, 50, 3));
|
||||||
|
|
||||||
|
let mut area = Rect::new(0, 0, 50, 1);
|
||||||
|
for (w, s) in &windows {
|
||||||
|
let mut s = s.borrow_mut();
|
||||||
|
w.render_ref(area, &mut buf, &mut *s);
|
||||||
|
area.y += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
buf,
|
||||||
|
Buffer::with_lines([
|
||||||
|
"stateful_widget_ref_dyn::Window1, u32: 32 ",
|
||||||
|
"stateful_widget_ref_dyn::Window2, String: Some ",
|
||||||
|
"stateful_widget_ref_dyn::Window1, u32: 42 ",
|
||||||
|
])
|
||||||
|
);
|
||||||
|
}
|
|
@ -6,9 +6,9 @@ license.workspace = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
cargo_metadata = "0.18.1"
|
cargo_metadata = "0.18.1"
|
||||||
clap = { version = "4.5.20", features = ["derive"] }
|
clap = { version = "4.5.21", features = ["derive"] }
|
||||||
clap-cargo = { version = "0.14.1", features = ["cargo_metadata"] }
|
clap-cargo = { version = "0.14.1", features = ["cargo_metadata"] }
|
||||||
clap-verbosity-flag = "2.2.2"
|
clap-verbosity-flag = "2.2.3"
|
||||||
color-eyre = "0.6.3"
|
color-eyre = "0.6.3"
|
||||||
duct = "0.13.7"
|
duct = "0.13.7"
|
||||||
tracing = "0.1.40"
|
tracing = "0.1.40"
|
||||||
|
|
Loading…
Add table
Reference in a new issue