Releases: ratatui/ratatui
Release list
ratatui-widgets-v0.3.2
We are excited to announce the new version of ratatui - a Rust library that's all about cooking up TUIs 👨🍳🐀
✨ Release highlights: https://ratatui.rs/highlights/v0302/
Features
-
90639c1 (uncategorized) Add Termina backend by
@joshkain #2561Summary
- add the
ratatui-terminabackend crate using the publishedtermina
crate - expose the backend through the
terminafeature and Ratatui
prelude/backend re-exports - add a small Termina event-loop example and wire the backend into CI,
xtask, README generation, and docs
Refs #1784
Validation
cargo +nightly fmtcargo check -p ratatui-termina --all-features --all-targetscargo check -p ratatui --no-default-features --features terminacargo check -p xtaskcargo check -p release-headercargo xtask check-backend terminacargo xtask test-backend terminacargo xtask rdme --checkmarkdownlint-cli2 ARCHITECTURE.md ratatui-termina/README.md .github/ISSUE_TEMPLATE/bug_report.md
- add the
Bug Fixes
-
fce3c80 (widgets) Require thread-safe shadow effects by
@joshkain #2584Summary
- require custom shadow effects to preserve the auto traits expected by
Block-backed widgets - document the CellEffect auto-trait contract
- add a public widget regression test for the affected ratatui::widgets
re-exports
Fixes #2583
- require custom shadow effects to preserve the auto traits expected by
-
e306ce6 (buffer) Create updates for "uncovered" cells by
@benjajajain #2587When a wide cell from the previous buffer is replaced by a short/normal
cell, the trailing cell does not get an update if its content does not
change. But if the wide cell has a background (or other) style, the
terminal did render the trailing cell with that style.Force trailing cells to update if background, underline, or modifiers
are different than the wide cell. We can ignore foreground.Fixes #2585 (see that for the detailed visual reports)
-
81e667f (scrollbar) Keep a large thumb within the track at the end by
@satyakwokin #2594Closes #2582.
Problem
When the content is shorter than the viewport, the thumb is large
relative to the track. With the position at the end,part_lengths
clampedthumb_starttotrack_length - 1whilethumb_lengthwas
clamped independently to[1, track_length], sothumb_start + thumb_lengthcould exceedtrack_length.bar_symbolslays outbegin + track_start + thumb + track_end + end
and zips it against the cells of the area. When the thumb overruns the
track,track_endsaturates to0but the thumb still emits more cells
than the track can hold, so the trailingendsymbol is pushed past the
end of the area. The last visible cell ends up being a thumb (█) where
the end arrow (▼) should be.Concretely, for the issue's repro (
VerticalRight,content_length = 9,position = 8, height24): track is22,thumb_length = 17,
thumb_start = 6, and6 + 17 = 23 > 22.This is a regression from v0.30.0, where
thumb_lengthwas derived as
thumb_end - thumb_startand therefore always fit within the track.Fix
Clamp
thumb_starttotrack_length - thumb_length(instead of
track_length - 1) so the thumb always fits within the track and the
end symbol is preserved.Test
Two regression tests, both fail on
mainand pass with the fix:thumb_stays_within_track_for_large_thumb_at_endchecks
part_lengthsdirectly with the issue's parameters — asserts
thumb_start + thumb_length <= track_lengthand that the parts sum to
the track length.render_scrollbar_keeps_end_symbol_for_large_thumbrenders the #2582
case (both arrows, large thumb at the end) and asserts the end symbol is
drawn rather than overwritten by a thumb cell.
All existing scrollbar tests still pass.
Miscellaneous Tasks
-
c75d778 (ci) Add cargo-udeps dependency check by
@joshkain #2599Adds cargo xtask udeps and runs it from CI as a required job.
This complements cargo-machete rather than replacing it. cargo-machete
is a fast static source scan, which is why it missed the package-level
unused deps fixed in #2598 when the same dependency names were still
referenced by example crates. cargo-udeps compiles the workspace and
checks rustc dep-info, so it can catch unused dependency declarations
for the package being checked.To make the new job pass, this also removes the remaining true-positive
unused dev-deps and records explicit cargo-udeps ignores for current
false positives / intentional cases: ratatui-core critical-section,
ratatui-crossterm's duplicate crossterm version feature shape, and
ratatui-termwiz's doc-example-only ratatui dev-dependency.I searched existing issues and PRs for udeps / cargo-udeps / "cargo
udeps". I did not find prior ratatui discussion about adopting
cargo-udeps; the only hits were Dependabot PR bodies for
taiki-e/install-action release notes mentioning cargo-udeps version
updates, for example #1971, #2095, #2194, and #2522.Validation:- cargo xtask udeps
- cargo xtask format --check
-
4a63d41 (uncategorized) Remove unused dependencies by
@KikiKianin #2598Audit removes these dependencies that are not used:
ratatui/Cargo.toml — Removed from [dev-dependencies]:
- futures
- rand_chacha
- tokio
- tracing
- tracing-appender
- tracing-subscriber
ratatui-core/Cargo.toml — Moved from [dependencies] →
[dev-dependencies]:- indoc
Continuous Integration
-
36854ef (uncategorized) Add auto-merge required gate by
@joshkain #2596Summary
This makes GitHub auto-merge usable for Ratatui PRs once maintainers are
happy with the change but CI is still running.The workflow change adds a single aggregate
requiredjob to the main
CI workflow. The repository now has auto-merge
enabled
and anensure checks pass
ruleset
that requires thatrequiredstatus context onmain.Why
Without a required status context, GitHub's auto-merge button is not
useful for the maintainer flow we want. The goal is to let a maintainer
review a PR, decide it is ready, click auto-merge, and move on without
coming back later just to check whether the remaining jobs finished.This does not relax the merge policy. GitHub's own auto-merge behavior
is to merge only after all required reviews and required status checks
are satisfied. This change gives GitHub a stable required status to wait
on automatically.Precedent
I have been using this same auto-merge pattern in
ratatui/tui-widgets, where
it has worked well for the intended maintainer flow: once a PR looks
ready, I can enable auto-merge and let GitHub merge it after the
remaining checks and review requirements are satisfied.How it works
The new
requiredjob depends on the main CI jobs in
.github/workflows/ci.ymland always runs after them. It fails if any
required dependency fails, is cancelled, or is skipped.The repository ruleset requires only this aggregate
requiredcontext
instead of requiring every individual matrix job separately. That gives
GitHub one stable status to wait on while preserving the existing CI
coverage.Things to know
- Auto-merge is opt-in per PR. Maintainers still choose when to click
it. - It does not skip review requirements, status checks, labels, or any
other protection rule. - A PR with auto-merge enabled can still show as blocked while checks or
required reviews are pending. That is expected. - If something needs to merge normally, maintainers can still use the
regular merge path or an allowed ruleset bypass. This is a convenience
path, not a hard blocker. - Existing open PRs may need a rebase or synchronize event after this
lands so they pick up the newrequiredworkflow job. - If a new required CI job is added later, it should be added to the
required.needslist or it will not be repr...
- Auto-merge is opt-in per PR. Maintainers still choose when to click
ratatui-v0.30.2
We are excited to announce the new version of ratatui - a Rust library that's all about cooking up TUIs 👨🍳🐀
✨ Release highlights: https://ratatui.rs/highlights/v0302/
Features
-
90639c1 (uncategorized) Add Termina backend by
@joshkain #2561Summary
- add the
ratatui-terminabackend crate using the publishedtermina
crate - expose the backend through the
terminafeature and Ratatui
prelude/backend re-exports - add a small Termina event-loop example and wire the backend into CI,
xtask, README generation, and docs
Refs #1784
Validation
cargo +nightly fmtcargo check -p ratatui-termina --all-features --all-targetscargo check -p ratatui --no-default-features --features terminacargo check -p xtaskcargo check -p release-headercargo xtask check-backend terminacargo xtask test-backend terminacargo xtask rdme --checkmarkdownlint-cli2 ARCHITECTURE.md ratatui-termina/README.md .github/ISSUE_TEMPLATE/bug_report.md
- add the
Bug Fixes
-
fce3c80 (widgets) Require thread-safe shadow effects by
@joshkain #2584Summary
- require custom shadow effects to preserve the auto traits expected by
Block-backed widgets - document the CellEffect auto-trait contract
- add a public widget regression test for the affected ratatui::widgets
re-exports
Fixes #2583
- require custom shadow effects to preserve the auto traits expected by
-
e306ce6 (buffer) Create updates for "uncovered" cells by
@benjajajain #2587When a wide cell from the previous buffer is replaced by a short/normal
cell, the trailing cell does not get an update if its content does not
change. But if the wide cell has a background (or other) style, the
terminal did render the trailing cell with that style.Force trailing cells to update if background, underline, or modifiers
are different than the wide cell. We can ignore foreground.Fixes #2585 (see that for the detailed visual reports)
-
81e667f (scrollbar) Keep a large thumb within the track at the end by
@satyakwokin #2594Closes #2582.
Problem
When the content is shorter than the viewport, the thumb is large
relative to the track. With the position at the end,part_lengths
clampedthumb_starttotrack_length - 1whilethumb_lengthwas
clamped independently to[1, track_length], sothumb_start + thumb_lengthcould exceedtrack_length.bar_symbolslays outbegin + track_start + thumb + track_end + end
and zips it against the cells of the area. When the thumb overruns the
track,track_endsaturates to0but the thumb still emits more cells
than the track can hold, so the trailingendsymbol is pushed past the
end of the area. The last visible cell ends up being a thumb (█) where
the end arrow (▼) should be.Concretely, for the issue's repro (
VerticalRight,content_length = 9,position = 8, height24): track is22,thumb_length = 17,
thumb_start = 6, and6 + 17 = 23 > 22.This is a regression from v0.30.0, where
thumb_lengthwas derived as
thumb_end - thumb_startand therefore always fit within the track.Fix
Clamp
thumb_starttotrack_length - thumb_length(instead of
track_length - 1) so the thumb always fits within the track and the
end symbol is preserved.Test
Two regression tests, both fail on
mainand pass with the fix:thumb_stays_within_track_for_large_thumb_at_endchecks
part_lengthsdirectly with the issue's parameters — asserts
thumb_start + thumb_length <= track_lengthand that the parts sum to
the track length.render_scrollbar_keeps_end_symbol_for_large_thumbrenders the #2582
case (both arrows, large thumb at the end) and asserts the end symbol is
drawn rather than overwritten by a thumb cell.
All existing scrollbar tests still pass.
Miscellaneous Tasks
-
c75d778 (ci) Add cargo-udeps dependency check by
@joshkain #2599Adds cargo xtask udeps and runs it from CI as a required job.
This complements cargo-machete rather than replacing it. cargo-machete
is a fast static source scan, which is why it missed the package-level
unused deps fixed in #2598 when the same dependency names were still
referenced by example crates. cargo-udeps compiles the workspace and
checks rustc dep-info, so it can catch unused dependency declarations
for the package being checked.To make the new job pass, this also removes the remaining true-positive
unused dev-deps and records explicit cargo-udeps ignores for current
false positives / intentional cases: ratatui-core critical-section,
ratatui-crossterm's duplicate crossterm version feature shape, and
ratatui-termwiz's doc-example-only ratatui dev-dependency.I searched existing issues and PRs for udeps / cargo-udeps / "cargo
udeps". I did not find prior ratatui discussion about adopting
cargo-udeps; the only hits were Dependabot PR bodies for
taiki-e/install-action release notes mentioning cargo-udeps version
updates, for example #1971, #2095, #2194, and #2522.Validation:- cargo xtask udeps
- cargo xtask format --check
-
4a63d41 (uncategorized) Remove unused dependencies by
@KikiKianin #2598Audit removes these dependencies that are not used:
ratatui/Cargo.toml — Removed from [dev-dependencies]:
- futures
- rand_chacha
- tokio
- tracing
- tracing-appender
- tracing-subscriber
ratatui-core/Cargo.toml — Moved from [dependencies] →
[dev-dependencies]:- indoc
Continuous Integration
-
36854ef (uncategorized) Add auto-merge required gate by
@joshkain #2596Summary
This makes GitHub auto-merge usable for Ratatui PRs once maintainers are
happy with the change but CI is still running.The workflow change adds a single aggregate
requiredjob to the main
CI workflow. The repository now has auto-merge
enabled
and anensure checks pass
ruleset
that requires thatrequiredstatus context onmain.Why
Without a required status context, GitHub's auto-merge button is not
useful for the maintainer flow we want. The goal is to let a maintainer
review a PR, decide it is ready, click auto-merge, and move on without
coming back later just to check whether the remaining jobs finished.This does not relax the merge policy. GitHub's own auto-merge behavior
is to merge only after all required reviews and required status checks
are satisfied. This change gives GitHub a stable required status to wait
on automatically.Precedent
I have been using this same auto-merge pattern in
ratatui/tui-widgets, where
it has worked well for the intended maintainer flow: once a PR looks
ready, I can enable auto-merge and let GitHub merge it after the
remaining checks and review requirements are satisfied.How it works
The new
requiredjob depends on the main CI jobs in
.github/workflows/ci.ymland always runs after them. It fails if any
required dependency fails, is cancelled, or is skipped.The repository ruleset requires only this aggregate
requiredcontext
instead of requiring every individual matrix job separately. That gives
GitHub one stable status to wait on while preserving the existing CI
coverage.Things to know
- Auto-merge is opt-in per PR. Maintainers still choose when to click
it. - It does not skip review requirements, status checks, labels, or any
other protection rule. - A PR with auto-merge enabled can still show as blocked while checks or
required reviews are pending. That is expected. - If something needs to merge normally, maintainers can still use the
regular merge path or an allowed ruleset bypass. This is a convenience
path, not a hard blocker. - Existing open PRs may need a rebase or synchronize event after this
lands so they pick up the newrequiredworkflow job. - If a new required CI job is added later, it should be added to the
required.needslist or it will not be repr...
- Auto-merge is opt-in per PR. Maintainers still choose when to click
ratatui-termwiz-v0.1.2
We are excited to announce the new version of ratatui - a Rust library that's all about cooking up TUIs 👨🍳🐀
✨ Release highlights: https://ratatui.rs/highlights/v0302/
Features
-
90639c1 (uncategorized) Add Termina backend by
@joshkain #2561Summary
- add the
ratatui-terminabackend crate using the publishedtermina
crate - expose the backend through the
terminafeature and Ratatui
prelude/backend re-exports - add a small Termina event-loop example and wire the backend into CI,
xtask, README generation, and docs
Refs #1784
Validation
cargo +nightly fmtcargo check -p ratatui-termina --all-features --all-targetscargo check -p ratatui --no-default-features --features terminacargo check -p xtaskcargo check -p release-headercargo xtask check-backend terminacargo xtask test-backend terminacargo xtask rdme --checkmarkdownlint-cli2 ARCHITECTURE.md ratatui-termina/README.md .github/ISSUE_TEMPLATE/bug_report.md
- add the
Bug Fixes
-
fce3c80 (widgets) Require thread-safe shadow effects by
@joshkain #2584Summary
- require custom shadow effects to preserve the auto traits expected by
Block-backed widgets - document the CellEffect auto-trait contract
- add a public widget regression test for the affected ratatui::widgets
re-exports
Fixes #2583
- require custom shadow effects to preserve the auto traits expected by
-
e306ce6 (buffer) Create updates for "uncovered" cells by
@benjajajain #2587When a wide cell from the previous buffer is replaced by a short/normal
cell, the trailing cell does not get an update if its content does not
change. But if the wide cell has a background (or other) style, the
terminal did render the trailing cell with that style.Force trailing cells to update if background, underline, or modifiers
are different than the wide cell. We can ignore foreground.Fixes #2585 (see that for the detailed visual reports)
-
81e667f (scrollbar) Keep a large thumb within the track at the end by
@satyakwokin #2594Closes #2582.
Problem
When the content is shorter than the viewport, the thumb is large
relative to the track. With the position at the end,part_lengths
clampedthumb_starttotrack_length - 1whilethumb_lengthwas
clamped independently to[1, track_length], sothumb_start + thumb_lengthcould exceedtrack_length.bar_symbolslays outbegin + track_start + thumb + track_end + end
and zips it against the cells of the area. When the thumb overruns the
track,track_endsaturates to0but the thumb still emits more cells
than the track can hold, so the trailingendsymbol is pushed past the
end of the area. The last visible cell ends up being a thumb (█) where
the end arrow (▼) should be.Concretely, for the issue's repro (
VerticalRight,content_length = 9,position = 8, height24): track is22,thumb_length = 17,
thumb_start = 6, and6 + 17 = 23 > 22.This is a regression from v0.30.0, where
thumb_lengthwas derived as
thumb_end - thumb_startand therefore always fit within the track.Fix
Clamp
thumb_starttotrack_length - thumb_length(instead of
track_length - 1) so the thumb always fits within the track and the
end symbol is preserved.Test
Two regression tests, both fail on
mainand pass with the fix:thumb_stays_within_track_for_large_thumb_at_endchecks
part_lengthsdirectly with the issue's parameters — asserts
thumb_start + thumb_length <= track_lengthand that the parts sum to
the track length.render_scrollbar_keeps_end_symbol_for_large_thumbrenders the #2582
case (both arrows, large thumb at the end) and asserts the end symbol is
drawn rather than overwritten by a thumb cell.
All existing scrollbar tests still pass.
Miscellaneous Tasks
-
c75d778 (ci) Add cargo-udeps dependency check by
@joshkain #2599Adds cargo xtask udeps and runs it from CI as a required job.
This complements cargo-machete rather than replacing it. cargo-machete
is a fast static source scan, which is why it missed the package-level
unused deps fixed in #2598 when the same dependency names were still
referenced by example crates. cargo-udeps compiles the workspace and
checks rustc dep-info, so it can catch unused dependency declarations
for the package being checked.To make the new job pass, this also removes the remaining true-positive
unused dev-deps and records explicit cargo-udeps ignores for current
false positives / intentional cases: ratatui-core critical-section,
ratatui-crossterm's duplicate crossterm version feature shape, and
ratatui-termwiz's doc-example-only ratatui dev-dependency.I searched existing issues and PRs for udeps / cargo-udeps / "cargo
udeps". I did not find prior ratatui discussion about adopting
cargo-udeps; the only hits were Dependabot PR bodies for
taiki-e/install-action release notes mentioning cargo-udeps version
updates, for example #1971, #2095, #2194, and #2522.Validation:- cargo xtask udeps
- cargo xtask format --check
-
4a63d41 (uncategorized) Remove unused dependencies by
@KikiKianin #2598Audit removes these dependencies that are not used:
ratatui/Cargo.toml — Removed from [dev-dependencies]:
- futures
- rand_chacha
- tokio
- tracing
- tracing-appender
- tracing-subscriber
ratatui-core/Cargo.toml — Moved from [dependencies] →
[dev-dependencies]:- indoc
Continuous Integration
-
36854ef (uncategorized) Add auto-merge required gate by
@joshkain #2596Summary
This makes GitHub auto-merge usable for Ratatui PRs once maintainers are
happy with the change but CI is still running.The workflow change adds a single aggregate
requiredjob to the main
CI workflow. The repository now has auto-merge
enabled
and anensure checks pass
ruleset
that requires thatrequiredstatus context onmain.Why
Without a required status context, GitHub's auto-merge button is not
useful for the maintainer flow we want. The goal is to let a maintainer
review a PR, decide it is ready, click auto-merge, and move on without
coming back later just to check whether the remaining jobs finished.This does not relax the merge policy. GitHub's own auto-merge behavior
is to merge only after all required reviews and required status checks
are satisfied. This change gives GitHub a stable required status to wait
on automatically.Precedent
I have been using this same auto-merge pattern in
ratatui/tui-widgets, where
it has worked well for the intended maintainer flow: once a PR looks
ready, I can enable auto-merge and let GitHub merge it after the
remaining checks and review requirements are satisfied.How it works
The new
requiredjob depends on the main CI jobs in
.github/workflows/ci.ymland always runs after them. It fails if any
required dependency fails, is cancelled, or is skipped.The repository ruleset requires only this aggregate
requiredcontext
instead of requiring every individual matrix job separately. That gives
GitHub one stable status to wait on while preserving the existing CI
coverage.Things to know
- Auto-merge is opt-in per PR. Maintainers still choose when to click
it. - It does not skip review requirements, status checks, labels, or any
other protection rule. - A PR with auto-merge enabled can still show as blocked while checks or
required reviews are pending. That is expected. - If something needs to merge normally, maintainers can still use the
regular merge path or an allowed ruleset bypass. This is a convenience
path, not a hard blocker. - Existing open PRs may need a rebase or synchronize event after this
lands so they pick up the newrequiredworkflow job. - If a new required CI job is added later, it should be added to the
required.needslist or it will not be repr...
- Auto-merge is opt-in per PR. Maintainers still choose when to click
ratatui-termion-v0.1.2
We are excited to announce the new version of ratatui - a Rust library that's all about cooking up TUIs 👨🍳🐀
✨ Release highlights: https://ratatui.rs/highlights/v0302/
Features
-
90639c1 (uncategorized) Add Termina backend by
@joshkain #2561Summary
- add the
ratatui-terminabackend crate using the publishedtermina
crate - expose the backend through the
terminafeature and Ratatui
prelude/backend re-exports - add a small Termina event-loop example and wire the backend into CI,
xtask, README generation, and docs
Refs #1784
Validation
cargo +nightly fmtcargo check -p ratatui-termina --all-features --all-targetscargo check -p ratatui --no-default-features --features terminacargo check -p xtaskcargo check -p release-headercargo xtask check-backend terminacargo xtask test-backend terminacargo xtask rdme --checkmarkdownlint-cli2 ARCHITECTURE.md ratatui-termina/README.md .github/ISSUE_TEMPLATE/bug_report.md
- add the
Bug Fixes
-
fce3c80 (widgets) Require thread-safe shadow effects by
@joshkain #2584Summary
- require custom shadow effects to preserve the auto traits expected by
Block-backed widgets - document the CellEffect auto-trait contract
- add a public widget regression test for the affected ratatui::widgets
re-exports
Fixes #2583
- require custom shadow effects to preserve the auto traits expected by
-
e306ce6 (buffer) Create updates for "uncovered" cells by
@benjajajain #2587When a wide cell from the previous buffer is replaced by a short/normal
cell, the trailing cell does not get an update if its content does not
change. But if the wide cell has a background (or other) style, the
terminal did render the trailing cell with that style.Force trailing cells to update if background, underline, or modifiers
are different than the wide cell. We can ignore foreground.Fixes #2585 (see that for the detailed visual reports)
-
81e667f (scrollbar) Keep a large thumb within the track at the end by
@satyakwokin #2594Closes #2582.
Problem
When the content is shorter than the viewport, the thumb is large
relative to the track. With the position at the end,part_lengths
clampedthumb_starttotrack_length - 1whilethumb_lengthwas
clamped independently to[1, track_length], sothumb_start + thumb_lengthcould exceedtrack_length.bar_symbolslays outbegin + track_start + thumb + track_end + end
and zips it against the cells of the area. When the thumb overruns the
track,track_endsaturates to0but the thumb still emits more cells
than the track can hold, so the trailingendsymbol is pushed past the
end of the area. The last visible cell ends up being a thumb (█) where
the end arrow (▼) should be.Concretely, for the issue's repro (
VerticalRight,content_length = 9,position = 8, height24): track is22,thumb_length = 17,
thumb_start = 6, and6 + 17 = 23 > 22.This is a regression from v0.30.0, where
thumb_lengthwas derived as
thumb_end - thumb_startand therefore always fit within the track.Fix
Clamp
thumb_starttotrack_length - thumb_length(instead of
track_length - 1) so the thumb always fits within the track and the
end symbol is preserved.Test
Two regression tests, both fail on
mainand pass with the fix:thumb_stays_within_track_for_large_thumb_at_endchecks
part_lengthsdirectly with the issue's parameters — asserts
thumb_start + thumb_length <= track_lengthand that the parts sum to
the track length.render_scrollbar_keeps_end_symbol_for_large_thumbrenders the #2582
case (both arrows, large thumb at the end) and asserts the end symbol is
drawn rather than overwritten by a thumb cell.
All existing scrollbar tests still pass.
Miscellaneous Tasks
-
c75d778 (ci) Add cargo-udeps dependency check by
@joshkain #2599Adds cargo xtask udeps and runs it from CI as a required job.
This complements cargo-machete rather than replacing it. cargo-machete
is a fast static source scan, which is why it missed the package-level
unused deps fixed in #2598 when the same dependency names were still
referenced by example crates. cargo-udeps compiles the workspace and
checks rustc dep-info, so it can catch unused dependency declarations
for the package being checked.To make the new job pass, this also removes the remaining true-positive
unused dev-deps and records explicit cargo-udeps ignores for current
false positives / intentional cases: ratatui-core critical-section,
ratatui-crossterm's duplicate crossterm version feature shape, and
ratatui-termwiz's doc-example-only ratatui dev-dependency.I searched existing issues and PRs for udeps / cargo-udeps / "cargo
udeps". I did not find prior ratatui discussion about adopting
cargo-udeps; the only hits were Dependabot PR bodies for
taiki-e/install-action release notes mentioning cargo-udeps version
updates, for example #1971, #2095, #2194, and #2522.Validation:- cargo xtask udeps
- cargo xtask format --check
-
4a63d41 (uncategorized) Remove unused dependencies by
@KikiKianin #2598Audit removes these dependencies that are not used:
ratatui/Cargo.toml — Removed from [dev-dependencies]:
- futures
- rand_chacha
- tokio
- tracing
- tracing-appender
- tracing-subscriber
ratatui-core/Cargo.toml — Moved from [dependencies] →
[dev-dependencies]:- indoc
Continuous Integration
-
36854ef (uncategorized) Add auto-merge required gate by
@joshkain #2596Summary
This makes GitHub auto-merge usable for Ratatui PRs once maintainers are
happy with the change but CI is still running.The workflow change adds a single aggregate
requiredjob to the main
CI workflow. The repository now has auto-merge
enabled
and anensure checks pass
ruleset
that requires thatrequiredstatus context onmain.Why
Without a required status context, GitHub's auto-merge button is not
useful for the maintainer flow we want. The goal is to let a maintainer
review a PR, decide it is ready, click auto-merge, and move on without
coming back later just to check whether the remaining jobs finished.This does not relax the merge policy. GitHub's own auto-merge behavior
is to merge only after all required reviews and required status checks
are satisfied. This change gives GitHub a stable required status to wait
on automatically.Precedent
I have been using this same auto-merge pattern in
ratatui/tui-widgets, where
it has worked well for the intended maintainer flow: once a PR looks
ready, I can enable auto-merge and let GitHub merge it after the
remaining checks and review requirements are satisfied.How it works
The new
requiredjob depends on the main CI jobs in
.github/workflows/ci.ymland always runs after them. It fails if any
required dependency fails, is cancelled, or is skipped.The repository ruleset requires only this aggregate
requiredcontext
instead of requiring every individual matrix job separately. That gives
GitHub one stable status to wait on while preserving the existing CI
coverage.Things to know
- Auto-merge is opt-in per PR. Maintainers still choose when to click
it. - It does not skip review requirements, status checks, labels, or any
other protection rule. - A PR with auto-merge enabled can still show as blocked while checks or
required reviews are pending. That is expected. - If something needs to merge normally, maintainers can still use the
regular merge path or an allowed ruleset bypass. This is a convenience
path, not a hard blocker. - Existing open PRs may need a rebase or synchronize event after this
lands so they pick up the newrequiredworkflow job. - If a new required CI job is added later, it should be added to the
required.needslist or it will not be repr...
- Auto-merge is opt-in per PR. Maintainers still choose when to click
ratatui-macros-v0.7.2
We are excited to announce the new version of ratatui - a Rust library that's all about cooking up TUIs 👨🍳🐀
✨ Release highlights: https://ratatui.rs/highlights/v0302/
Features
-
90639c1 (uncategorized) Add Termina backend by
@joshkain #2561Summary
- add the
ratatui-terminabackend crate using the publishedtermina
crate - expose the backend through the
terminafeature and Ratatui
prelude/backend re-exports - add a small Termina event-loop example and wire the backend into CI,
xtask, README generation, and docs
Refs #1784
Validation
cargo +nightly fmtcargo check -p ratatui-termina --all-features --all-targetscargo check -p ratatui --no-default-features --features terminacargo check -p xtaskcargo check -p release-headercargo xtask check-backend terminacargo xtask test-backend terminacargo xtask rdme --checkmarkdownlint-cli2 ARCHITECTURE.md ratatui-termina/README.md .github/ISSUE_TEMPLATE/bug_report.md
- add the
Bug Fixes
-
fce3c80 (widgets) Require thread-safe shadow effects by
@joshkain #2584Summary
- require custom shadow effects to preserve the auto traits expected by
Block-backed widgets - document the CellEffect auto-trait contract
- add a public widget regression test for the affected ratatui::widgets
re-exports
Fixes #2583
- require custom shadow effects to preserve the auto traits expected by
-
e306ce6 (buffer) Create updates for "uncovered" cells by
@benjajajain #2587When a wide cell from the previous buffer is replaced by a short/normal
cell, the trailing cell does not get an update if its content does not
change. But if the wide cell has a background (or other) style, the
terminal did render the trailing cell with that style.Force trailing cells to update if background, underline, or modifiers
are different than the wide cell. We can ignore foreground.Fixes #2585 (see that for the detailed visual reports)
-
81e667f (scrollbar) Keep a large thumb within the track at the end by
@satyakwokin #2594Closes #2582.
Problem
When the content is shorter than the viewport, the thumb is large
relative to the track. With the position at the end,part_lengths
clampedthumb_starttotrack_length - 1whilethumb_lengthwas
clamped independently to[1, track_length], sothumb_start + thumb_lengthcould exceedtrack_length.bar_symbolslays outbegin + track_start + thumb + track_end + end
and zips it against the cells of the area. When the thumb overruns the
track,track_endsaturates to0but the thumb still emits more cells
than the track can hold, so the trailingendsymbol is pushed past the
end of the area. The last visible cell ends up being a thumb (█) where
the end arrow (▼) should be.Concretely, for the issue's repro (
VerticalRight,content_length = 9,position = 8, height24): track is22,thumb_length = 17,
thumb_start = 6, and6 + 17 = 23 > 22.This is a regression from v0.30.0, where
thumb_lengthwas derived as
thumb_end - thumb_startand therefore always fit within the track.Fix
Clamp
thumb_starttotrack_length - thumb_length(instead of
track_length - 1) so the thumb always fits within the track and the
end symbol is preserved.Test
Two regression tests, both fail on
mainand pass with the fix:thumb_stays_within_track_for_large_thumb_at_endchecks
part_lengthsdirectly with the issue's parameters — asserts
thumb_start + thumb_length <= track_lengthand that the parts sum to
the track length.render_scrollbar_keeps_end_symbol_for_large_thumbrenders the #2582
case (both arrows, large thumb at the end) and asserts the end symbol is
drawn rather than overwritten by a thumb cell.
All existing scrollbar tests still pass.
Miscellaneous Tasks
-
c75d778 (ci) Add cargo-udeps dependency check by
@joshkain #2599Adds cargo xtask udeps and runs it from CI as a required job.
This complements cargo-machete rather than replacing it. cargo-machete
is a fast static source scan, which is why it missed the package-level
unused deps fixed in #2598 when the same dependency names were still
referenced by example crates. cargo-udeps compiles the workspace and
checks rustc dep-info, so it can catch unused dependency declarations
for the package being checked.To make the new job pass, this also removes the remaining true-positive
unused dev-deps and records explicit cargo-udeps ignores for current
false positives / intentional cases: ratatui-core critical-section,
ratatui-crossterm's duplicate crossterm version feature shape, and
ratatui-termwiz's doc-example-only ratatui dev-dependency.I searched existing issues and PRs for udeps / cargo-udeps / "cargo
udeps". I did not find prior ratatui discussion about adopting
cargo-udeps; the only hits were Dependabot PR bodies for
taiki-e/install-action release notes mentioning cargo-udeps version
updates, for example #1971, #2095, #2194, and #2522.Validation:- cargo xtask udeps
- cargo xtask format --check
-
4a63d41 (uncategorized) Remove unused dependencies by
@KikiKianin #2598Audit removes these dependencies that are not used:
ratatui/Cargo.toml — Removed from [dev-dependencies]:
- futures
- rand_chacha
- tokio
- tracing
- tracing-appender
- tracing-subscriber
ratatui-core/Cargo.toml — Moved from [dependencies] →
[dev-dependencies]:- indoc
Continuous Integration
-
36854ef (uncategorized) Add auto-merge required gate by
@joshkain #2596Summary
This makes GitHub auto-merge usable for Ratatui PRs once maintainers are
happy with the change but CI is still running.The workflow change adds a single aggregate
requiredjob to the main
CI workflow. The repository now has auto-merge
enabled
and anensure checks pass
ruleset
that requires thatrequiredstatus context onmain.Why
Without a required status context, GitHub's auto-merge button is not
useful for the maintainer flow we want. The goal is to let a maintainer
review a PR, decide it is ready, click auto-merge, and move on without
coming back later just to check whether the remaining jobs finished.This does not relax the merge policy. GitHub's own auto-merge behavior
is to merge only after all required reviews and required status checks
are satisfied. This change gives GitHub a stable required status to wait
on automatically.Precedent
I have been using this same auto-merge pattern in
ratatui/tui-widgets, where
it has worked well for the intended maintainer flow: once a PR looks
ready, I can enable auto-merge and let GitHub merge it after the
remaining checks and review requirements are satisfied.How it works
The new
requiredjob depends on the main CI jobs in
.github/workflows/ci.ymland always runs after them. It fails if any
required dependency fails, is cancelled, or is skipped.The repository ruleset requires only this aggregate
requiredcontext
instead of requiring every individual matrix job separately. That gives
GitHub one stable status to wait on while preserving the existing CI
coverage.Things to know
- Auto-merge is opt-in per PR. Maintainers still choose when to click
it. - It does not skip review requirements, status checks, labels, or any
other protection rule. - A PR with auto-merge enabled can still show as blocked while checks or
required reviews are pending. That is expected. - If something needs to merge normally, maintainers can still use the
regular merge path or an allowed ruleset bypass. This is a convenience
path, not a hard blocker. - Existing open PRs may need a rebase or synchronize event after this
lands so they pick up the newrequiredworkflow job. - If a new required CI job is added later, it should be added to the
required.needslist or it will not be repr...
- Auto-merge is opt-in per PR. Maintainers still choose when to click
ratatui-crossterm-v0.1.2
We are excited to announce the new version of ratatui - a Rust library that's all about cooking up TUIs 👨🍳🐀
✨ Release highlights: https://ratatui.rs/highlights/v0302/
Features
-
90639c1 (uncategorized) Add Termina backend by
@joshkain #2561Summary
- add the
ratatui-terminabackend crate using the publishedtermina
crate - expose the backend through the
terminafeature and Ratatui
prelude/backend re-exports - add a small Termina event-loop example and wire the backend into CI,
xtask, README generation, and docs
Refs #1784
Validation
cargo +nightly fmtcargo check -p ratatui-termina --all-features --all-targetscargo check -p ratatui --no-default-features --features terminacargo check -p xtaskcargo check -p release-headercargo xtask check-backend terminacargo xtask test-backend terminacargo xtask rdme --checkmarkdownlint-cli2 ARCHITECTURE.md ratatui-termina/README.md .github/ISSUE_TEMPLATE/bug_report.md
- add the
Bug Fixes
-
fce3c80 (widgets) Require thread-safe shadow effects by
@joshkain #2584Summary
- require custom shadow effects to preserve the auto traits expected by
Block-backed widgets - document the CellEffect auto-trait contract
- add a public widget regression test for the affected ratatui::widgets
re-exports
Fixes #2583
- require custom shadow effects to preserve the auto traits expected by
-
e306ce6 (buffer) Create updates for "uncovered" cells by
@benjajajain #2587When a wide cell from the previous buffer is replaced by a short/normal
cell, the trailing cell does not get an update if its content does not
change. But if the wide cell has a background (or other) style, the
terminal did render the trailing cell with that style.Force trailing cells to update if background, underline, or modifiers
are different than the wide cell. We can ignore foreground.Fixes #2585 (see that for the detailed visual reports)
-
81e667f (scrollbar) Keep a large thumb within the track at the end by
@satyakwokin #2594Closes #2582.
Problem
When the content is shorter than the viewport, the thumb is large
relative to the track. With the position at the end,part_lengths
clampedthumb_starttotrack_length - 1whilethumb_lengthwas
clamped independently to[1, track_length], sothumb_start + thumb_lengthcould exceedtrack_length.bar_symbolslays outbegin + track_start + thumb + track_end + end
and zips it against the cells of the area. When the thumb overruns the
track,track_endsaturates to0but the thumb still emits more cells
than the track can hold, so the trailingendsymbol is pushed past the
end of the area. The last visible cell ends up being a thumb (█) where
the end arrow (▼) should be.Concretely, for the issue's repro (
VerticalRight,content_length = 9,position = 8, height24): track is22,thumb_length = 17,
thumb_start = 6, and6 + 17 = 23 > 22.This is a regression from v0.30.0, where
thumb_lengthwas derived as
thumb_end - thumb_startand therefore always fit within the track.Fix
Clamp
thumb_starttotrack_length - thumb_length(instead of
track_length - 1) so the thumb always fits within the track and the
end symbol is preserved.Test
Two regression tests, both fail on
mainand pass with the fix:thumb_stays_within_track_for_large_thumb_at_endchecks
part_lengthsdirectly with the issue's parameters — asserts
thumb_start + thumb_length <= track_lengthand that the parts sum to
the track length.render_scrollbar_keeps_end_symbol_for_large_thumbrenders the #2582
case (both arrows, large thumb at the end) and asserts the end symbol is
drawn rather than overwritten by a thumb cell.
All existing scrollbar tests still pass.
Miscellaneous Tasks
-
c75d778 (ci) Add cargo-udeps dependency check by
@joshkain #2599Adds cargo xtask udeps and runs it from CI as a required job.
This complements cargo-machete rather than replacing it. cargo-machete
is a fast static source scan, which is why it missed the package-level
unused deps fixed in #2598 when the same dependency names were still
referenced by example crates. cargo-udeps compiles the workspace and
checks rustc dep-info, so it can catch unused dependency declarations
for the package being checked.To make the new job pass, this also removes the remaining true-positive
unused dev-deps and records explicit cargo-udeps ignores for current
false positives / intentional cases: ratatui-core critical-section,
ratatui-crossterm's duplicate crossterm version feature shape, and
ratatui-termwiz's doc-example-only ratatui dev-dependency.I searched existing issues and PRs for udeps / cargo-udeps / "cargo
udeps". I did not find prior ratatui discussion about adopting
cargo-udeps; the only hits were Dependabot PR bodies for
taiki-e/install-action release notes mentioning cargo-udeps version
updates, for example #1971, #2095, #2194, and #2522.Validation:- cargo xtask udeps
- cargo xtask format --check
-
4a63d41 (uncategorized) Remove unused dependencies by
@KikiKianin #2598Audit removes these dependencies that are not used:
ratatui/Cargo.toml — Removed from [dev-dependencies]:
- futures
- rand_chacha
- tokio
- tracing
- tracing-appender
- tracing-subscriber
ratatui-core/Cargo.toml — Moved from [dependencies] →
[dev-dependencies]:- indoc
Continuous Integration
-
36854ef (uncategorized) Add auto-merge required gate by
@joshkain #2596Summary
This makes GitHub auto-merge usable for Ratatui PRs once maintainers are
happy with the change but CI is still running.The workflow change adds a single aggregate
requiredjob to the main
CI workflow. The repository now has auto-merge
enabled
and anensure checks pass
ruleset
that requires thatrequiredstatus context onmain.Why
Without a required status context, GitHub's auto-merge button is not
useful for the maintainer flow we want. The goal is to let a maintainer
review a PR, decide it is ready, click auto-merge, and move on without
coming back later just to check whether the remaining jobs finished.This does not relax the merge policy. GitHub's own auto-merge behavior
is to merge only after all required reviews and required status checks
are satisfied. This change gives GitHub a stable required status to wait
on automatically.Precedent
I have been using this same auto-merge pattern in
ratatui/tui-widgets, where
it has worked well for the intended maintainer flow: once a PR looks
ready, I can enable auto-merge and let GitHub merge it after the
remaining checks and review requirements are satisfied.How it works
The new
requiredjob depends on the main CI jobs in
.github/workflows/ci.ymland always runs after them. It fails if any
required dependency fails, is cancelled, or is skipped.The repository ruleset requires only this aggregate
requiredcontext
instead of requiring every individual matrix job separately. That gives
GitHub one stable status to wait on while preserving the existing CI
coverage.Things to know
- Auto-merge is opt-in per PR. Maintainers still choose when to click
it. - It does not skip review requirements, status checks, labels, or any
other protection rule. - A PR with auto-merge enabled can still show as blocked while checks or
required reviews are pending. That is expected. - If something needs to merge normally, maintainers can still use the
regular merge path or an allowed ruleset bypass. This is a convenience
path, not a hard blocker. - Existing open PRs may need a rebase or synchronize event after this
lands so they pick up the newrequiredworkflow job. - If a new required CI job is added later, it should be added to the
required.needslist or it will not be repr...
- Auto-merge is opt-in per PR. Maintainers still choose when to click
ratatui-core-v0.1.2
We are excited to announce the new version of ratatui - a Rust library that's all about cooking up TUIs 👨🍳🐀
✨ Release highlights: https://ratatui.rs/highlights/v0302/
Features
-
90639c1 (uncategorized) Add Termina backend by
@joshkain #2561Summary
- add the
ratatui-terminabackend crate using the publishedtermina
crate - expose the backend through the
terminafeature and Ratatui
prelude/backend re-exports - add a small Termina event-loop example and wire the backend into CI,
xtask, README generation, and docs
Refs #1784
Validation
cargo +nightly fmtcargo check -p ratatui-termina --all-features --all-targetscargo check -p ratatui --no-default-features --features terminacargo check -p xtaskcargo check -p release-headercargo xtask check-backend terminacargo xtask test-backend terminacargo xtask rdme --checkmarkdownlint-cli2 ARCHITECTURE.md ratatui-termina/README.md .github/ISSUE_TEMPLATE/bug_report.md
- add the
Bug Fixes
-
fce3c80 (widgets) Require thread-safe shadow effects by
@joshkain #2584Summary
- require custom shadow effects to preserve the auto traits expected by
Block-backed widgets - document the CellEffect auto-trait contract
- add a public widget regression test for the affected ratatui::widgets
re-exports
Fixes #2583
- require custom shadow effects to preserve the auto traits expected by
-
e306ce6 (buffer) Create updates for "uncovered" cells by
@benjajajain #2587When a wide cell from the previous buffer is replaced by a short/normal
cell, the trailing cell does not get an update if its content does not
change. But if the wide cell has a background (or other) style, the
terminal did render the trailing cell with that style.Force trailing cells to update if background, underline, or modifiers
are different than the wide cell. We can ignore foreground.Fixes #2585 (see that for the detailed visual reports)
-
81e667f (scrollbar) Keep a large thumb within the track at the end by
@satyakwokin #2594Closes #2582.
Problem
When the content is shorter than the viewport, the thumb is large
relative to the track. With the position at the end,part_lengths
clampedthumb_starttotrack_length - 1whilethumb_lengthwas
clamped independently to[1, track_length], sothumb_start + thumb_lengthcould exceedtrack_length.bar_symbolslays outbegin + track_start + thumb + track_end + end
and zips it against the cells of the area. When the thumb overruns the
track,track_endsaturates to0but the thumb still emits more cells
than the track can hold, so the trailingendsymbol is pushed past the
end of the area. The last visible cell ends up being a thumb (█) where
the end arrow (▼) should be.Concretely, for the issue's repro (
VerticalRight,content_length = 9,position = 8, height24): track is22,thumb_length = 17,
thumb_start = 6, and6 + 17 = 23 > 22.This is a regression from v0.30.0, where
thumb_lengthwas derived as
thumb_end - thumb_startand therefore always fit within the track.Fix
Clamp
thumb_starttotrack_length - thumb_length(instead of
track_length - 1) so the thumb always fits within the track and the
end symbol is preserved.Test
Two regression tests, both fail on
mainand pass with the fix:thumb_stays_within_track_for_large_thumb_at_endchecks
part_lengthsdirectly with the issue's parameters — asserts
thumb_start + thumb_length <= track_lengthand that the parts sum to
the track length.render_scrollbar_keeps_end_symbol_for_large_thumbrenders the #2582
case (both arrows, large thumb at the end) and asserts the end symbol is
drawn rather than overwritten by a thumb cell.
All existing scrollbar tests still pass.
Miscellaneous Tasks
-
c75d778 (ci) Add cargo-udeps dependency check by
@joshkain #2599Adds cargo xtask udeps and runs it from CI as a required job.
This complements cargo-machete rather than replacing it. cargo-machete
is a fast static source scan, which is why it missed the package-level
unused deps fixed in #2598 when the same dependency names were still
referenced by example crates. cargo-udeps compiles the workspace and
checks rustc dep-info, so it can catch unused dependency declarations
for the package being checked.To make the new job pass, this also removes the remaining true-positive
unused dev-deps and records explicit cargo-udeps ignores for current
false positives / intentional cases: ratatui-core critical-section,
ratatui-crossterm's duplicate crossterm version feature shape, and
ratatui-termwiz's doc-example-only ratatui dev-dependency.I searched existing issues and PRs for udeps / cargo-udeps / "cargo
udeps". I did not find prior ratatui discussion about adopting
cargo-udeps; the only hits were Dependabot PR bodies for
taiki-e/install-action release notes mentioning cargo-udeps version
updates, for example #1971, #2095, #2194, and #2522.Validation:- cargo xtask udeps
- cargo xtask format --check
-
4a63d41 (uncategorized) Remove unused dependencies by
@KikiKianin #2598Audit removes these dependencies that are not used:
ratatui/Cargo.toml — Removed from [dev-dependencies]:
- futures
- rand_chacha
- tokio
- tracing
- tracing-appender
- tracing-subscriber
ratatui-core/Cargo.toml — Moved from [dependencies] →
[dev-dependencies]:- indoc
Continuous Integration
-
36854ef (uncategorized) Add auto-merge required gate by
@joshkain #2596Summary
This makes GitHub auto-merge usable for Ratatui PRs once maintainers are
happy with the change but CI is still running.The workflow change adds a single aggregate
requiredjob to the main
CI workflow. The repository now has auto-merge
enabled
and anensure checks pass
ruleset
that requires thatrequiredstatus context onmain.Why
Without a required status context, GitHub's auto-merge button is not
useful for the maintainer flow we want. The goal is to let a maintainer
review a PR, decide it is ready, click auto-merge, and move on without
coming back later just to check whether the remaining jobs finished.This does not relax the merge policy. GitHub's own auto-merge behavior
is to merge only after all required reviews and required status checks
are satisfied. This change gives GitHub a stable required status to wait
on automatically.Precedent
I have been using this same auto-merge pattern in
ratatui/tui-widgets, where
it has worked well for the intended maintainer flow: once a PR looks
ready, I can enable auto-merge and let GitHub merge it after the
remaining checks and review requirements are satisfied.How it works
The new
requiredjob depends on the main CI jobs in
.github/workflows/ci.ymland always runs after them. It fails if any
required dependency fails, is cancelled, or is skipped.The repository ruleset requires only this aggregate
requiredcontext
instead of requiring every individual matrix job separately. That gives
GitHub one stable status to wait on while preserving the existing CI
coverage.Things to know
- Auto-merge is opt-in per PR. Maintainers still choose when to click
it. - It does not skip review requirements, status checks, labels, or any
other protection rule. - A PR with auto-merge enabled can still show as blocked while checks or
required reviews are pending. That is expected. - If something needs to merge normally, maintainers can still use the
regular merge path or an allowed ruleset bypass. This is a convenience
path, not a hard blocker. - Existing open PRs may need a rebase or synchronize event after this
lands so they pick up the newrequiredworkflow job. - If a new required CI job is added later, it should be added to the
required.needslist or it will not be repr...
- Auto-merge is opt-in per PR. Maintainers still choose when to click
ratatui-widgets-v0.3.1
"Rats, we're rats; we're the rats." – Rat Movie
We are excited to announce the new version of ratatui - a Rust library that's all about cooking up TUIs 👨🍳🐀
✨ Release highlights: https://ratatui.rs/highlights/v0301/
Features
-
74d6a84 (block) Support shadows by orhun in #2481
Introduce
Block::shadow(...)with a newShadowtype that supports:- presets:
overlay,block,light_shade,medium_shade,
dark_shade - custom symbols via
Shadow::symbol(...) - custom effects via
Shadow::custom(...)
use ratatui::layout::Offset; use ratatui::style::Stylize; use ratatui::widgets::{Block, Shadow}; let popup = Block::bordered().title("Popup").shadow( Shadow::dark_shade() .black() .on_white() .offset(Offset::new(2, 1)), );
Results in:
┌Popup─────┐ │content │▒ └──────────┘▒ ▒▒▒▒▒▒▒▒▒▒▒fixes #1892
- presets:
-
4d30420 (buffer) Add
CellDiffOption::AlwaysUpdateto force cell updates by sxyazi in #2480When this option is used, the cells are updated even when content is identical.
Follow-up for #1605
Trying to resolve #1116
-
39c32c6 (buffer) Add cell diff options by benjajaja in #1605
Problem:Escape sequences always cause a cell to count as "multiwidth",
even when it doesn't render wider than one cell, or not as wide as the
escape sequence would be computed as.Solution:Convert
skip:boolto enum. Add enum optionForceWidthto
force a cell width for diffing.When using the option, this also fixes some bug where diffing is not
idempotent and causes a diff operation for(symbol.len() - 1)times.There are three new specific test cases:
- Rendering hyperlinks by squeezing the escape sequence into the first
cell and forcing the width to the unicode width of the text part.
This is much easier to implement for a Link widget, as it would only
need to get the unicode-width once and not iterate over graphemes
like Spans must do. - Rendering hyperlinks by squeezing the opening sequence into the first
cell with the first grapheme and forcing the width to that of the
first grapheme. Then rendering each grapheme as usual. Then squeezing
the closing sequence into the last cell with the last grapheme and
forcing the width to that of the last grapheme.
This is harder to implement for a Link widget, as it would have to
iterate over graphemes with their width like Spans do. - Kitty image sequence with utf-8 placeholders, similar to 2 but with
known constant grapheme widths.
Link widget that leverages this
It would be cooler if we could just add something like
.link(url)to
Spans, because it would much simpler to insert some link and leverage
all the Line/Text/Paragraph wrapping and whatnot. With a custom widget
you need to take care of theAreawhere you'd want to render it, so
it's not that clean. But we could iterate on this later, if even
possible. - Rendering hyperlinks by squeezing the escape sequence into the first
-
6faaddb (core) Implement from slice for line and text by NoOPeEKS in #2371
This PR adds the following implementations of the From trait for Line
and Text structs:- Implements From<&[T]> where T is Into<Span> for Line, allowing using
of slices to construct Lines. - Implements From<&[T]> where T is Into<Line> for Text, allowing using
of slices of various types to construct Texts.
closes #2279
- Implements From<&[T]> where T is Into<Span> for Line, allowing using
-
5fc6ab8 (core) Support layout-cache in no_std environments by junkdog in #2399
this enables "layout-cache" for no_std builds; it's meant for embedded
environments, where the layout engine otherwise consumes all CPU,
capping the framerate at around ~10fps. the same app can refresh 300-500
times per second with layout cache enabled.i had to add
layout-cache = ["dep:critical-section"]to all builds -
it's pretty tiny and shouldn't leave a trace in std-builds. the
alternative is to add an extra layer of features for layout-cache with
std and no_std, but it pollutes the feature space.
-
ee4b7a9 (crossterm) Add the missing hidden modifier by sxyazi in #2413
Fixes sxyazi/yazi#3724, see
sxyazi/yazi#3724 (comment) for a
reproducer.This PR adds the missing
Modifier::HIDDENstyle and introduces a
queue_modifier_diffto testModifierDiff::queue().It also fixes a bug where
CrosstermAttribute::Boldand
CrosstermAttribute::Dimwould be emitted twice when resetting
intensity. For example:#[case(Modifier::DIM, Modifier::BOLD, &[CrosstermAttribute::NormalIntensity, CrosstermAttribute::Bold])]would become:
#[case(Modifier::DIM, Modifier::BOLD, &[CrosstermAttribute::NormalIntensity, CrosstermAttribute::Bold, CrosstermAttribute::Bold])]
-
9d9239a (examples) Add volatility-surface 3D visualization by floor-licker in #2322
A design demonstration of a 3D volatility surface rendering using
Braille canvas with interactive rotation and zoom controls. I built this
for myself for an app I'm currently building but just wanted to share it
with the community as well to inspire more 3D perspective terminal
widgets in the future.Final Demo
Description
Adds a new example demonstrating 3D visualization techniques in the
terminal. There aren't many examples showing how to represent 3D objects
in 2D terminal space so my goal is just to demonstrate more advanced
Canvas and Braille rendering techniques for 3D graphics. The example
visualizes an implied volatility surface which is a common financial
visualization using interactive rotation and zoom controls. You can run
the interactive demo for yourself withcargo run -p volatility-surfacedemo.mov
<img width="659" height="432" alt="image"
Technical Highlights
- Demonstrates how to implement perspective projection in a terminal
- Shows advanced use of
Canvaswidget withMarker::Braille - Example of smooth animation patterns and state management
- Self-contained with synthetic data generation (no external APIs)
-
ae975c7 (examples) Allow overlap spacing in explorer by joshka in #2316
Store spacing as i16 so negative values map to Spacing::Overlap, and
show overlap in the axis label. -
1e0ab0c (ratatui-crossterm) Add IntoCrossterm for Style by 0xferrous in #2323
-
101a63e (render) Add function for applying buffer by musjj in #2566
Add a public API for applying and flushing the terminal buffer.
A minimal usage will look something like this:
use ratatui::Terminal; use ratatui::backend::CrosstermBackend; use ratatui::buffer::Buffer; use ratatui::widgets::Widget; let backend = CrosstermBackend::new(io::stdout()); let mut terminal = Terminal::new(backend)?; terminal.autoresize()?; let mut custom_buffer = Buffer::default(); custom_buffer.resize(terminal.get_frame().area()); custom_buffer.reset(); "Hello World!".render(custom_buffer.area, &mut custom_buffer); terminal.current_buffer_mut().merge(&custom_buffer); terminal.apply_buffer()?;
My primary motivation for this PR is to improve the ECS ergonomics in
bevy_ratatui. But this
should be useful for anyone who wants to commit incremental writes to
the buffer without having to do everything in one monolithic...
ratatui-v0.30.1
"Rats, we're rats; we're the rats." – Rat Movie
We are excited to announce the new version of ratatui - a Rust library that's all about cooking up TUIs 👨🍳🐀
✨ Release highlights: https://ratatui.rs/highlights/v0301/
Features
-
74d6a84 (block) Support shadows by orhun in #2481
Introduce
Block::shadow(...)with a newShadowtype that supports:- presets:
overlay,block,light_shade,medium_shade,
dark_shade - custom symbols via
Shadow::symbol(...) - custom effects via
Shadow::custom(...)
use ratatui::layout::Offset; use ratatui::style::Stylize; use ratatui::widgets::{Block, Shadow}; let popup = Block::bordered().title("Popup").shadow( Shadow::dark_shade() .black() .on_white() .offset(Offset::new(2, 1)), );
Results in:
┌Popup─────┐ │content │▒ └──────────┘▒ ▒▒▒▒▒▒▒▒▒▒▒fixes #1892
- presets:
-
4d30420 (buffer) Add
CellDiffOption::AlwaysUpdateto force cell updates by sxyazi in #2480When this option is used, the cells are updated even when content is identical.
Follow-up for #1605
Trying to resolve #1116
-
39c32c6 (buffer) Add cell diff options by benjajaja in #1605
Problem:Escape sequences always cause a cell to count as "multiwidth",
even when it doesn't render wider than one cell, or not as wide as the
escape sequence would be computed as.Solution:Convert
skip:boolto enum. Add enum optionForceWidthto
force a cell width for diffing.When using the option, this also fixes some bug where diffing is not
idempotent and causes a diff operation for(symbol.len() - 1)times.There are three new specific test cases:
- Rendering hyperlinks by squeezing the escape sequence into the first
cell and forcing the width to the unicode width of the text part.
This is much easier to implement for a Link widget, as it would only
need to get the unicode-width once and not iterate over graphemes
like Spans must do. - Rendering hyperlinks by squeezing the opening sequence into the first
cell with the first grapheme and forcing the width to that of the
first grapheme. Then rendering each grapheme as usual. Then squeezing
the closing sequence into the last cell with the last grapheme and
forcing the width to that of the last grapheme.
This is harder to implement for a Link widget, as it would have to
iterate over graphemes with their width like Spans do. - Kitty image sequence with utf-8 placeholders, similar to 2 but with
known constant grapheme widths.
Link widget that leverages this
It would be cooler if we could just add something like
.link(url)to
Spans, because it would much simpler to insert some link and leverage
all the Line/Text/Paragraph wrapping and whatnot. With a custom widget
you need to take care of theAreawhere you'd want to render it, so
it's not that clean. But we could iterate on this later, if even
possible. - Rendering hyperlinks by squeezing the escape sequence into the first
-
6faaddb (core) Implement from slice for line and text by NoOPeEKS in #2371
This PR adds the following implementations of the From trait for Line
and Text structs:- Implements From<&[T]> where T is Into<Span> for Line, allowing using
of slices to construct Lines. - Implements From<&[T]> where T is Into<Line> for Text, allowing using
of slices of various types to construct Texts.
closes #2279
- Implements From<&[T]> where T is Into<Span> for Line, allowing using
-
5fc6ab8 (core) Support layout-cache in no_std environments by junkdog in #2399
this enables "layout-cache" for no_std builds; it's meant for embedded
environments, where the layout engine otherwise consumes all CPU,
capping the framerate at around ~10fps. the same app can refresh 300-500
times per second with layout cache enabled.i had to add
layout-cache = ["dep:critical-section"]to all builds -
it's pretty tiny and shouldn't leave a trace in std-builds. the
alternative is to add an extra layer of features for layout-cache with
std and no_std, but it pollutes the feature space.
-
ee4b7a9 (crossterm) Add the missing hidden modifier by sxyazi in #2413
Fixes sxyazi/yazi#3724, see
sxyazi/yazi#3724 (comment) for a
reproducer.This PR adds the missing
Modifier::HIDDENstyle and introduces a
queue_modifier_diffto testModifierDiff::queue().It also fixes a bug where
CrosstermAttribute::Boldand
CrosstermAttribute::Dimwould be emitted twice when resetting
intensity. For example:#[case(Modifier::DIM, Modifier::BOLD, &[CrosstermAttribute::NormalIntensity, CrosstermAttribute::Bold])]would become:
#[case(Modifier::DIM, Modifier::BOLD, &[CrosstermAttribute::NormalIntensity, CrosstermAttribute::Bold, CrosstermAttribute::Bold])]
-
9d9239a (examples) Add volatility-surface 3D visualization by floor-licker in #2322
A design demonstration of a 3D volatility surface rendering using
Braille canvas with interactive rotation and zoom controls. I built this
for myself for an app I'm currently building but just wanted to share it
with the community as well to inspire more 3D perspective terminal
widgets in the future.Final Demo
Description
Adds a new example demonstrating 3D visualization techniques in the
terminal. There aren't many examples showing how to represent 3D objects
in 2D terminal space so my goal is just to demonstrate more advanced
Canvas and Braille rendering techniques for 3D graphics. The example
visualizes an implied volatility surface which is a common financial
visualization using interactive rotation and zoom controls. You can run
the interactive demo for yourself withcargo run -p volatility-surfacedemo.mov
<img width="659" height="432" alt="image"
Technical Highlights
- Demonstrates how to implement perspective projection in a terminal
- Shows advanced use of
Canvaswidget withMarker::Braille - Example of smooth animation patterns and state management
- Self-contained with synthetic data generation (no external APIs)
-
ae975c7 (examples) Allow overlap spacing in explorer by joshka in #2316
Store spacing as i16 so negative values map to Spacing::Overlap, and
show overlap in the axis label. -
1e0ab0c (ratatui-crossterm) Add IntoCrossterm for Style by 0xferrous in #2323
-
101a63e (render) Add function for applying buffer by musjj in #2566
Add a public API for applying and flushing the terminal buffer.
A minimal usage will look something like this:
use ratatui::Terminal; use ratatui::backend::CrosstermBackend; use ratatui::buffer::Buffer; use ratatui::widgets::Widget; let backend = CrosstermBackend::new(io::stdout()); let mut terminal = Terminal::new(backend)?; terminal.autoresize()?; let mut custom_buffer = Buffer::default(); custom_buffer.resize(terminal.get_frame().area()); custom_buffer.reset(); "Hello World!".render(custom_buffer.area, &mut custom_buffer); terminal.current_buffer_mut().merge(&custom_buffer); terminal.apply_buffer()?;
My primary motivation for this PR is to improve the ECS ergonomics in
bevy_ratatui. But this
should be useful for anyone who wants to commit incremental writes to
the buffer without having to do everything in one monolithic...
ratatui-termwiz-v0.1.1
"Rats, we're rats; we're the rats." – Rat Movie
We are excited to announce the new version of ratatui - a Rust library that's all about cooking up TUIs 👨🍳🐀
✨ Release highlights: https://ratatui.rs/highlights/v0301/
Features
-
74d6a84 (block) Support shadows by orhun in #2481
Introduce
Block::shadow(...)with a newShadowtype that supports:- presets:
overlay,block,light_shade,medium_shade,
dark_shade - custom symbols via
Shadow::symbol(...) - custom effects via
Shadow::custom(...)
use ratatui::layout::Offset; use ratatui::style::Stylize; use ratatui::widgets::{Block, Shadow}; let popup = Block::bordered().title("Popup").shadow( Shadow::dark_shade() .black() .on_white() .offset(Offset::new(2, 1)), );
Results in:
┌Popup─────┐ │content │▒ └──────────┘▒ ▒▒▒▒▒▒▒▒▒▒▒fixes #1892
- presets:
-
4d30420 (buffer) Add
CellDiffOption::AlwaysUpdateto force cell updates by sxyazi in #2480When this option is used, the cells are updated even when content is identical.
Follow-up for #1605
Trying to resolve #1116
-
39c32c6 (buffer) Add cell diff options by benjajaja in #1605
Problem:Escape sequences always cause a cell to count as "multiwidth",
even when it doesn't render wider than one cell, or not as wide as the
escape sequence would be computed as.Solution:Convert
skip:boolto enum. Add enum optionForceWidthto
force a cell width for diffing.When using the option, this also fixes some bug where diffing is not
idempotent and causes a diff operation for(symbol.len() - 1)times.There are three new specific test cases:
- Rendering hyperlinks by squeezing the escape sequence into the first
cell and forcing the width to the unicode width of the text part.
This is much easier to implement for a Link widget, as it would only
need to get the unicode-width once and not iterate over graphemes
like Spans must do. - Rendering hyperlinks by squeezing the opening sequence into the first
cell with the first grapheme and forcing the width to that of the
first grapheme. Then rendering each grapheme as usual. Then squeezing
the closing sequence into the last cell with the last grapheme and
forcing the width to that of the last grapheme.
This is harder to implement for a Link widget, as it would have to
iterate over graphemes with their width like Spans do. - Kitty image sequence with utf-8 placeholders, similar to 2 but with
known constant grapheme widths.
Link widget that leverages this
It would be cooler if we could just add something like
.link(url)to
Spans, because it would much simpler to insert some link and leverage
all the Line/Text/Paragraph wrapping and whatnot. With a custom widget
you need to take care of theAreawhere you'd want to render it, so
it's not that clean. But we could iterate on this later, if even
possible. - Rendering hyperlinks by squeezing the escape sequence into the first
-
6faaddb (core) Implement from slice for line and text by NoOPeEKS in #2371
This PR adds the following implementations of the From trait for Line
and Text structs:- Implements From<&[T]> where T is Into<Span> for Line, allowing using
of slices to construct Lines. - Implements From<&[T]> where T is Into<Line> for Text, allowing using
of slices of various types to construct Texts.
closes #2279
- Implements From<&[T]> where T is Into<Span> for Line, allowing using
-
5fc6ab8 (core) Support layout-cache in no_std environments by junkdog in #2399
this enables "layout-cache" for no_std builds; it's meant for embedded
environments, where the layout engine otherwise consumes all CPU,
capping the framerate at around ~10fps. the same app can refresh 300-500
times per second with layout cache enabled.i had to add
layout-cache = ["dep:critical-section"]to all builds -
it's pretty tiny and shouldn't leave a trace in std-builds. the
alternative is to add an extra layer of features for layout-cache with
std and no_std, but it pollutes the feature space.
-
ee4b7a9 (crossterm) Add the missing hidden modifier by sxyazi in #2413
Fixes sxyazi/yazi#3724, see
sxyazi/yazi#3724 (comment) for a
reproducer.This PR adds the missing
Modifier::HIDDENstyle and introduces a
queue_modifier_diffto testModifierDiff::queue().It also fixes a bug where
CrosstermAttribute::Boldand
CrosstermAttribute::Dimwould be emitted twice when resetting
intensity. For example:#[case(Modifier::DIM, Modifier::BOLD, &[CrosstermAttribute::NormalIntensity, CrosstermAttribute::Bold])]would become:
#[case(Modifier::DIM, Modifier::BOLD, &[CrosstermAttribute::NormalIntensity, CrosstermAttribute::Bold, CrosstermAttribute::Bold])]
-
9d9239a (examples) Add volatility-surface 3D visualization by floor-licker in #2322
A design demonstration of a 3D volatility surface rendering using
Braille canvas with interactive rotation and zoom controls. I built this
for myself for an app I'm currently building but just wanted to share it
with the community as well to inspire more 3D perspective terminal
widgets in the future.Final Demo
Description
Adds a new example demonstrating 3D visualization techniques in the
terminal. There aren't many examples showing how to represent 3D objects
in 2D terminal space so my goal is just to demonstrate more advanced
Canvas and Braille rendering techniques for 3D graphics. The example
visualizes an implied volatility surface which is a common financial
visualization using interactive rotation and zoom controls. You can run
the interactive demo for yourself withcargo run -p volatility-surfacedemo.mov
<img width="659" height="432" alt="image"
Technical Highlights
- Demonstrates how to implement perspective projection in a terminal
- Shows advanced use of
Canvaswidget withMarker::Braille - Example of smooth animation patterns and state management
- Self-contained with synthetic data generation (no external APIs)
-
ae975c7 (examples) Allow overlap spacing in explorer by joshka in #2316
Store spacing as i16 so negative values map to Spacing::Overlap, and
show overlap in the axis label. -
1e0ab0c (ratatui-crossterm) Add IntoCrossterm for Style by 0xferrous in #2323
-
101a63e (render) Add function for applying buffer by musjj in #2566
Add a public API for applying and flushing the terminal buffer.
A minimal usage will look something like this:
use ratatui::Terminal; use ratatui::backend::CrosstermBackend; use ratatui::buffer::Buffer; use ratatui::widgets::Widget; let backend = CrosstermBackend::new(io::stdout()); let mut terminal = Terminal::new(backend)?; terminal.autoresize()?; let mut custom_buffer = Buffer::default(); custom_buffer.resize(terminal.get_frame().area()); custom_buffer.reset(); "Hello World!".render(custom_buffer.area, &mut custom_buffer); terminal.current_buffer_mut().merge(&custom_buffer); terminal.apply_buffer()?;
My primary motivation for this PR is to improve the ECS ergonomics in
bevy_ratatui. But this
should be useful for anyone who wants to commit incremental writes to
the buffer without having to do everything in one monolithic...



