v0.28.0
0.28.0 - 2024-08-07
"If you are what you eat, then I only want to eat the good stuff." β Remy
We are excited to announce the new version of ratatui
- a Rust library that's all about cooking up TUIs π
In this version, we have upgraded to Crossterm 0.28.0, introducing enhanced functionality and performance improvements.
New features include GraphType::Bar, lines in bar charts, and enhanced scroll/navigation methods.
We have also refined the terminal module and added brand new methods for cursor positions and text operations.
β¨ Release highlights: https://ratatui.rs/highlights/v028/
Features
-
8d4a102 (barchart) Allow axes to accept Lines by @joshka in #1273 [breaking]
Fixes:#1272
-
a23ecd9 (buffer) Add Buffer::cell, cell_mut and index implementations by @joshka in #1084
Code which previously called
buf.get(x, y)
orbuf.get_mut(x, y)
should now use index operators, or be transitioned tobuff.cell()
or
buf.cell_mut()
for safe access that avoids panics by returning
Option<&Cell>
andOption<&mut Cell>
.The new methods accept
Into<Position>
instead ofx
andy
coordinates, which makes them more ergonomic to use.let mut buffer = Buffer::empty(Rect::new(0, 0, 10, 10)); let cell = buf[(0, 0)]; let cell = buf[Position::new(0, 0)]; let symbol = buf.cell((0, 0)).map(|cell| cell.symbol()); let symbol = buf.cell(Position::new(0, 0)).map(|cell| cell.symbol()); buf[(0, 0)].set_symbol("π"); buf[Position::new(0, 0)].set_symbol("π"); buf.cell_mut((0, 0)).map(|cell| cell.set_symbol("π")); buf.cell_mut(Position::new(0, 0)).map(|cell| cell.set_symbol("π"));
The existing
get()
andget_mut()
methods are marked as deprecated.
These are fairly widely used and we will leave these methods around on
the buffer for a longer time than our normal deprecation approach (2
major release)Addresses part of: #1011
-
afe1534 (chart) Accept
IntoIterator
for axis labels by @EdJoPaTo in #1283 [breaking]BREAKING CHANGES: #1273 is already breaking and this only advances the
already breaking part -
5b51018 (chart) Add GraphType::Bar by @joshka in #1205
-
f97e07c (frame) Replace Frame::size() with Frame::area() by @EdJoPaTo in #1293
Area is the more correct term for the result of this method.
The Frame::size() method is marked as deprecated and will be
removed around Ratatui version 0.30 or later.Fixes:#1254 (comment)
-
5b89bd0 (layout) Add Size::ZERO and Position::ORIGIN constants by @EdJoPaTo in #1253
-
b2aa843 (layout) Enable serde for Margin, Position, Rect, Size by @EdJoPaTo in #1255
-
36d49e5 (table) Select first, last, etc to table state by @robertpsoane in #1198
Add select_previous, select_next, select_first & select_last to
TableStateUsed equivalent API as in ListState
-
3bb374d (terminal) Add Terminal::try_draw() method by @joshka in #1209
This makes it easier to write fallible rendering methods that can use
the?
operatorterminal.try_draw(|frame| { some_method_that_can_fail()?; another_faillible_method()?; Ok(()) })?;
-
3725262 (text) Add
Add
andAddAssign
implementations forLine
,Span
, andText
by @joshka in #1236This enables:
let line = Span::raw("Red").red() + Span::raw("blue").blue(); let line = Line::raw("Red").red() + Span::raw("blue").blue(); let line = Line::raw("Red").red() + Line::raw("Blue").blue(); let text = Line::raw("Red").red() + Line::raw("Blue").blue(); let text = Text::raw("Red").red() + Line::raw("Blue").blue(); let mut line = Line::raw("Red").red(); line += Span::raw("Blue").blue(); let mut text = Text::raw("Red").red(); text += Line::raw("Blue").blue(); line.extend(vec![Span::raw("1"), Span::raw("2"), Span::raw("3")]);
-
c34fb77 (text) Remove unnecessary lifetime from ToText trait by @joshka in #1234 [breaking]
BREAKING CHANGE:The ToText trait no longer has a lifetime parameter.
This change simplifies the trait and makes it easier implement. -
c68ee6c (uncategorized) Add
get/set_cursor_position()
methods to Terminal and Backend by @EdJoPaTo in #1284 [breaking]The new methods return/accept
Into<Position>
which can be either a Position or a (u16, u16) tuple.backend.set_cursor_position(Position { x: 0, y: 20 })?; let position = backend.get_cursor_position()?; terminal.set_cursor_position((0, 20))?; let position = terminal.set_cursor_position()?;
-
b70cd03 (uncategorized) Add ListState / TableState scroll_down_by() / scroll_up_by() methods by @josueBarretogit in #1267
Implement new methods
scroll_down_by(u16)
andscroll_up_by(u16)
for
bothListstate
andTablestate
.Closes:#1207
Bug Fixes
-
864cd9f (testbackend) Prevent area mismatch by @EdJoPaTo in #1252
Removes the height and width fields from TestBackend, which can get
out of sync with the Buffer, which currently clamps to 255,255.This changes the
TestBackend
serde representation. It should be
possible to read older data, but data generated after this change
can't be read by older versions. -
7e1bab0 (buffer) Dont render control characters by @EdJoPaTo in #1226
-
c08b522 (chart) Allow removing all the axis labels by @EdJoPaTo in #1282
axis.labels(vec![])
removes all the labels correctly.This makes calling axis.labels with an empty Vec the equivalent
of not calling axis.labels. It's likely that this is never used, but it
prevents weird cases by removing the mix-up ofOption::None
andVec::is_empty
, and simplifies the implementation code. -
03f3124 (paragraph) Line_width, and line_count include block borders by @airblast-dev in #1235
The
line_width
, andline_count
methods forParagraph
would not
take into account theBlock
if one was set. This will now correctly
calculate the values including theBlock
's width/height.Fixes:#1233
-
3ca920e (span) Prevent panic on rendering out of y bounds by @EdJoPaTo in #1257
-
84cb164 (terminal) Make terminal module private by @joshka in #1260 [breaking]
This is a simplification of the public API that is helpful for new users
that are not familiar with how rust re-exports work, and helps avoid
clashes with other modules in the backends that are named terminal.BREAKING CHANGE:The
terminal
module is now private and can not be
used directly. The types under this module are exported from the root of
the crate.- use ratatui::terminal::{CompletedFrame, Frame, Terminal, TerminalOptions, ViewPort}; + use ratatui::{CompletedFrame, Frame, Terminal, TerminalOptions, ViewPort};
Fixes:#1210
-
29c8c84 (uncategorized) Ignore newlines in Span's Display impl by @SUPERCILEX in #1270
-
cd93547 (uncategorized) Remove unnecessary synchronization in layout cache by @SUPERCILEX in #1245
Layout::init_cache no longer returns bool and takes a NonZeroUsize instead of usize
The cache is a thread-local, so doesn't make much sense to require
synchronized initialization. -
b344f95 (uncategorized) Only apply style to first line when rendering a
Line
by @joshka in #1247A
Line
widget should only apply its style to the first line when
rendering and not the entire area. This is because theLine
widget
should only render a single line of text. This commit fixes the issue by
clamping the area to a single line before rendering the text. -
7ddfbc0 (uncategorized) Unnecessary allocations when creating Lines by @SUPERCILEX in #1237
-
84f3341 (uncategorized) Clippy lints from rust 1.80.0 by @joshka in #1238
Refactor
-
bb68bc6 (backend) Return
Size
fromBackend::size
instead ofRect
by @EdJoPaTo in #1254 [breaking]The
Backend::size
method returns aSize
instead of aRect
.
There is no need for the position here as it was always 0,0. -
e81663b (list) Split up list.rs into smaller modules by @joshka in #1204
-
e707ff1 (uncategorized) Internally use Position struct by @EdJoPaTo in #1256
-
32a0b26 (uncategorized) Simplify WordWrapper implementation by @tranzystorekk in #1193
Documentation
-
6ce447c (block) Add docs about style inheritance by @joshka in #1190
Fixes:#1129
-
55e0880 (block) Update block documentation by @leohscl in #1206
Update block documentation with constructor methods and setter methods
in the main doc comment Added an example for using it to surround
widgetsFixes:#914
-
f2fa1ae (breaking-changes) Add missing code block by @orhun in #1291
-
f687af7 (breaking-changes) Mention removed lifetime of ToText trait by @orhun in #1292
-
d468463 (breaking-changes) Fix the PR link by @orhun in #1294
-
1b9bdd4 (contributing) Fix minor issues by @EdJoPaTo in #1300
-
5f7a7fb (examples) Update barcharts gifs by @joshka in #1306
-
fe4eeab (examples) Simplify the barchart example by @joshka in #1079
The
barchart
example has been split into two examples:barchart
and
barchart-grouped
. Thebarchart
example now shows a simple barchart
with random data, while thebarchart-grouped
example shows a grouped
barchart with fake revenue data.This simplifies the examples a bit so they don't cover too much at once.
- Simplify the rendering functions
- Fix several clippy lints that were marked as allowed
-
6e7b4e4 (examples) Add async example by @joshka in #1248
This example demonstrates how to use Ratatui with widgets that fetch
data asynchronously. It uses theoctocrab
crate to fetch a list of
pull requests from the GitHub API. You will need an environment
variable namedGITHUB_TOKEN
with a valid GitHub personal access
token. The token does not need any special permissions. -
935a718 (examples) Add missing examples to README by @kibibyt3 in #1225
Resolves:#1014
-
50e5674 (examples) Fix: fix typos in tape files by @kibibyt3 in #1224
-
810da72 (examples) Fix hyperlink example tape by @kibibyt3 in #1222
-
5eeb1cc (github) Create CODE_OF_CONDUCT.md by @joshka in #1279
-
bb71e5f (readme) Remove MSRV by @EdJoPaTo in #1266
This notice was useful when the
Cargo.toml
had no standardized field
for this. Now it's easier to look it up in theCargo.toml
and it's
also a single point of truth. Updating the README was overlooked for
quite some time so it's better to just omit it rather than having
something wrong that will be forgotten again in the future. -
2fd5ae6 (widgets) Document stability of WidgetRef by @joshka in #1288
Addresses some confusion about when to implement
WidgetRef
vsimpl Widget for &W
. Notes the stability rationale and links to an issue that
helps explain the context of where we're at in working this out. -
716c931 (uncategorized) Document crossterm breaking change by @joshka in #1281
-
f775030 (uncategorized) Update main lib.rs / README examples by @joshka in #1280
-
8433d09 (uncategorized) Update demo image by @joshka in #1276
Follow up to #1203
Performance
-
663486f (list) Avoid extra allocations when rendering
List
by @airblast-dev in #1244When rendering a
List
, eachListItem
would be cloned. Removing the
clone, and replacingWidget::render
withWidgetRef::render_ref
saves
us allocations caused by the clone of theText<'_>
stored inside of
ListItem
.Based on the results of running the "list" benchmark locally;
Performance is improved by %1-3 for allrender
benchmarks forList
. -
4753b72 (reflow) Eliminate most WordWrapper allocations by @SUPERCILEX in #1239
On large paragraphs (~1MB), this saves hundreds of thousands of
allocations.TL;DR:reuse as much memory as possible across
next_line
calls.
Instead of allocating new buffers each time, allocate the buffers once
and clear them before reuse. -
be3eb75 (table) Avoid extra allocations when rendering
Table
by @airblast-dev in #1242When rendering a
Table
theText
stored inside of aCell
gets
cloned before rendering. This removes the clone and usesWidgetRef
instead, saving us from allocating aVec<Line<'_>>
insideText
. Also
avoids an allocation when rendering the highlight symbol if it contains
an owned value. -
f04bf85 (uncategorized) Add buffer benchmarks by @joshka in #1303
-
e6d2e04 (uncategorized) Move benchmarks into a single benchmark harness by @joshka in #1302
Consolidates the benchmarks into a single executable rather than having
to create a new cargo.toml setting per and makes it easier to rearrange
these when adding new benchmarks.
Styling
-
a80a8a6 (format) Lint markdown by @joshka in #1131
- chore: Fix line endings for changelog
- chore: cleanup markdown lints
- ci: add Markdown linter
- build: add markdown lint to the makefile
Testing
Miscellaneous Tasks
-
82b70fd (ci) Integrate cargo-semver-checks by @orhun in #1166
cargo-semver-checks
:
Lint your crate API changes for semver violations. -
c245c13 (ci) Onboard bencher for tracking benchmarks by @orhun in #1174
https://bencher.dev/console/projects/ratatui-org
Closes:#1092
-
efef0d0 (ci) Change label from
breaking change
toType: Breaking Change
by @kdheepak in #1243This PR changes the label that is auto attached to a PR with a breaking
change per the conventional commits specification. -
41a9100 (github) Use the GitHub organization team as codeowners by @EdJoPaTo in #1081
Use GitHub organization team in CODEOWNERS and create MAINTAINERS.md
-
3e7458f (github) Add forums and faqs to the issue template by @joshka in #1201
-
45fcab7 (uncategorized) Add rect::rows benchmark by @joshka in #1301
-
edc2af9 (uncategorized) Replace big_text with hardcoded logo by @joshka in #1203
big_text.rs was a copy of the code from tui-big-text and was getting
gradually out of sync with the original crate. It was also rendering
something a bit different than the Ratatui logo. This commit replaces
the big_text.rs file with a much smaller string representation of the
Ratatui logo. -
c2d3850 (uncategorized) Use LF line endings for CHANGELOG.md instead of CRLF by @joshka in #1269
-
a9fe428 (uncategorized) Update cargo-deny config by @EdJoPaTo in #1265
Update
cargo-deny
config (noticed in
#1263 (review)) -
ffc4300 (uncategorized) Remove executable flag for rs files by @EdJoPaTo in #1262
-
7bab9f0 (uncategorized) Add more CompactString::const_new instead of new by @joshka in #1230
-
ccf83e6 (uncategorized) Update labels in issue templates by @joshka in #1212
Build
Continuous Integration
-
476ac87 (uncategorized) Split up lint job by @EdJoPaTo in #1264
This helps with identifying what failed right from the title. Also steps
after a failing one are now always executed.Also shortens the steps a bit by removing obvious names.
New Contributors
- @SUPERCILEX made their first contribution in #1239
- @josueBarretogit made their first contribution in #1267
- @airblast-dev made their first contribution in #1242
- @kibibyt3 made their first contribution in #1225
- @EmiOnGit made their first contribution in #1217
- @leohscl made their first contribution in #1206
- @robertpsoane made their first contribution in #1198
Full Changelog: v0.27.0...0.28.0