Compare commits
1 Commits
v0.26.3-al
...
rect-offse
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9ea840d87f |
5
.github/CODEOWNERS
vendored
5
.github/CODEOWNERS
vendored
@@ -5,7 +5,4 @@
|
||||
# https://git-scm.com/docs/gitignore#_pattern_format
|
||||
|
||||
# Maintainers
|
||||
* @orhun @joshka @kdheepak @Valentin271 @EdJoPaTo
|
||||
|
||||
# Past maintainers
|
||||
# @mindoodoo @sayanarijit
|
||||
* @orhun @mindoodoo @sayanarijit @joshka @kdheepak @Valentin271 @EdJoPaTo
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
This document contains a list of breaking changes in each version and some notes to help migrate
|
||||
between versions. It is compiled manually from the commit history and changelog. We also tag PRs on
|
||||
GitHub with a [breaking change] label.
|
||||
github with a [breaking change] label.
|
||||
|
||||
[breaking change]: (https://github.com/ratatui-org/ratatui/issues?q=label%3A%22breaking+change%22)
|
||||
|
||||
@@ -37,7 +37,7 @@ This is a quick summary of the sections below:
|
||||
- `Scrollbar`: symbols moved to `symbols` module
|
||||
- MSRV is now 1.67.0
|
||||
- [v0.22.0](#v0220)
|
||||
- `serde` representation of `Borders` and `Modifiers` has changed
|
||||
- serde representation of `Borders` and `Modifiers` has changed
|
||||
- [v0.21.0](#v0210)
|
||||
- MSRV is now 1.65.0
|
||||
- `terminal::ViewPort` is now an enum
|
||||
@@ -49,14 +49,14 @@ This is a quick summary of the sections below:
|
||||
|
||||
## [v0.26.0](https://github.com/ratatui-org/ratatui/releases/tag/v0.26.0)
|
||||
|
||||
### `Flex::Start` is the new default flex mode for `Layout` ([#881])
|
||||
### `Flex::Start` is the new default flex mode for `Layout`
|
||||
|
||||
[#881]: https://github.com/ratatui-org/ratatui/pull/881
|
||||
|
||||
Previously, constraints would stretch to fill all available space, violating constraints if
|
||||
necessary.
|
||||
|
||||
With v0.26.0, `Flex` modes are introduced, and the default is `Flex::Start`, which will align
|
||||
With v0.26.0, `Flex` modes are introduced and the default is `Flex::Start`, which will align
|
||||
areas associated with constraints to be beginning of the area. With v0.26.0, additionally,
|
||||
`Min` constraints grow to fill excess space. These changes will allow users to build layouts
|
||||
more easily.
|
||||
@@ -108,7 +108,7 @@ by removing the call to `.collect()`.
|
||||
[#751]: https://github.com/ratatui-org/ratatui/pull/751
|
||||
|
||||
The default() implementation of Table now sets the column_spacing field to 1 and the segment_size
|
||||
field to `SegmentSize::None`. This will affect the rendering of a small amount of apps.
|
||||
field to SegmentSize::None. This will affect the rendering of a small amount of apps.
|
||||
|
||||
To use the previous default values, call `table.segment_size(Default::default())` and
|
||||
`table.column_spacing(0)`.
|
||||
@@ -222,8 +222,8 @@ widget in the default configuration would not show any indication of the selecte
|
||||
|
||||
[#664]: https://github.com/ratatui-org/ratatui/pull/664
|
||||
|
||||
Previously `Table`s could be constructed without `widths`. In almost all cases this is an error.
|
||||
A new `widths` parameter is now mandatory on `Table::new()`. Existing code of the form:
|
||||
Previously `Table`s could be constructed without widths. In almost all cases this is an error.
|
||||
A new widths parameter is now mandatory on `Table::new()`. Existing code of the form:
|
||||
|
||||
```diff
|
||||
- Table::new(rows).widths(widths)
|
||||
@@ -281,7 +281,7 @@ let layout = layout::new(Direction::Vertical, [Constraint::Min(1), Constraint::M
|
||||
|
||||
## [v0.24.0](https://github.com/ratatui-org/ratatui/releases/tag/v0.24.0)
|
||||
|
||||
### `ScrollbarState` field type changed from `u16` to `usize` ([#456])
|
||||
### ScrollbarState field type changed from `u16` to `usize` ([#456])
|
||||
|
||||
[#456]: https://github.com/ratatui-org/ratatui/pull/456
|
||||
|
||||
@@ -385,12 +385,12 @@ The MSRV of ratatui is now 1.67 due to an MSRV update in a dependency (`time`).
|
||||
|
||||
## [v0.22.0](https://github.com/ratatui-org/ratatui/releases/tag/v0.22.0)
|
||||
|
||||
### `bitflags` updated to 2.3 ([#205])
|
||||
### bitflags updated to 2.3 ([#205])
|
||||
|
||||
[#205]: https://github.com/ratatui-org/ratatui/issues/205
|
||||
|
||||
The `serde` representation of `bitflags` has changed. Any existing serialized types that have Borders or
|
||||
Modifiers will need to be re-serialized. This is documented in the [`bitflags`
|
||||
The serde representation of bitflags has changed. Any existing serialized types that have Borders or
|
||||
Modifiers will need to be re-serialized. This is documented in the [bitflags
|
||||
changelog](https://github.com/bitflags/bitflags/blob/main/CHANGELOG.md#200-rc2)..
|
||||
|
||||
## [v0.21.0](https://github.com/ratatui-org/ratatui/releases/tag/v0.21.0)
|
||||
@@ -422,9 +422,9 @@ let terminal = Terminal::with_options(backend, TerminalOptions {
|
||||
|
||||
[#168]: https://github.com/ratatui-org/ratatui/issues/168
|
||||
|
||||
A new type `Masked` was introduced that implements `From<Text<'a>>`. This causes any code that
|
||||
A new type `Masked` was introduced that implements `From<Text<'a>>`. This causes any code that did
|
||||
previously did not need to use type annotations to fail to compile. To fix this, annotate or call
|
||||
`to_string()` / `to_owned()` / `as_str()` on the value. E.g.:
|
||||
to_string() / to_owned() / as_str() on the value. E.g.:
|
||||
|
||||
```diff
|
||||
- let paragraph = Paragraph::new("".as_ref());
|
||||
|
||||
458
CHANGELOG.md
458
CHANGELOG.md
@@ -2,457 +2,7 @@
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
## [0.26.2](https://github.com/ratatui-org/ratatui/releases/tag/v0.26.2) - 2024-04-15
|
||||
|
||||
This is a patch release that fixes bugs and adds enhancements, including new iterator constructors, List scroll padding, and various rendering improvements. ✨
|
||||
|
||||
✨ **Release highlights**: <https://ratatui.rs/highlights/v0262/>
|
||||
|
||||
### Features
|
||||
|
||||
- [11b452d](https://github.com/ratatui-org/ratatui/commit/11b452d56fe590188ee7a53fa2dde95513b1a4c7)
|
||||
*(layout)* Mark various functions as const by @EdJoPaTo in [#951](https://github.com/ratatui-org/ratatui/pull/951)
|
||||
|
||||
- [1cff511](https://github.com/ratatui-org/ratatui/commit/1cff51193466f5a94d202b6233d56889eccf6d7b)
|
||||
*(line)* Impl Styled for Line by @joshka in [#968](https://github.com/ratatui-org/ratatui/pull/968)
|
||||
|
||||
````text
|
||||
This adds `FromIterator` impls for `Line` and `Text` that allow creating
|
||||
`Line` and `Text` instances from iterators of `Span` and `Line`
|
||||
instances, respectively.
|
||||
|
||||
```rust
|
||||
let line = Line::from_iter(vec!["Hello".blue(), " world!".green()]);
|
||||
let line: Line = iter::once("Hello".blue())
|
||||
.chain(iter::once(" world!".green()))
|
||||
.collect();
|
||||
let text = Text::from_iter(vec!["The first line", "The second line"]);
|
||||
let text: Text = iter::once("The first line")
|
||||
.chain(iter::once("The second line"))
|
||||
.collect();
|
||||
```
|
||||
````
|
||||
|
||||
- [654949b](https://github.com/ratatui-org/ratatui/commit/654949bb00b4522130642f9ad50ab4d9095d921b)
|
||||
*(list)* Add Scroll Padding to Lists by @CameronBarnes in [#958](https://github.com/ratatui-org/ratatui/pull/958)
|
||||
|
||||
````text
|
||||
Introduces scroll padding, which allows the api user to request that a certain number of ListItems be kept visible above and below the currently selected item while scrolling.
|
||||
|
||||
```rust
|
||||
let list = List::new(items).scroll_padding(1);
|
||||
```
|
||||
````
|
||||
|
||||
Fixes:https://github.com/ratatui-org/ratatui/pull/955
|
||||
|
||||
- [26af650](https://github.com/ratatui-org/ratatui/commit/26af65043ee9f165459dec228d12eaeed9997d92)
|
||||
*(text)* Add push methods for text and line by @joshka in [#998](https://github.com/ratatui-org/ratatui/pull/998)
|
||||
|
||||
````text
|
||||
Adds the following methods to the `Text` and `Line` structs:
|
||||
- Text::push_line
|
||||
- Text::push_span
|
||||
- Line::push_span
|
||||
|
||||
This allows for adding lines and spans to a text object without having
|
||||
to call methods on the fields directly, which is useful for incremental
|
||||
construction of text objects.
|
||||
````
|
||||
|
||||
- [b5bdde0](https://github.com/ratatui-org/ratatui/commit/b5bdde079e0e1eda98b9b1bbbba011b770e5b167)
|
||||
*(text)* Add `FromIterator` impls for `Line` and `Text` by @joshka in [#967](https://github.com/ratatui-org/ratatui/pull/967)
|
||||
|
||||
````text
|
||||
This adds `FromIterator` impls for `Line` and `Text` that allow creating
|
||||
`Line` and `Text` instances from iterators of `Span` and `Line`
|
||||
instances, respectively.
|
||||
|
||||
```rust
|
||||
let line = Line::from_iter(vec!["Hello".blue(), " world!".green()]);
|
||||
let line: Line = iter::once("Hello".blue())
|
||||
.chain(iter::once(" world!".green()))
|
||||
.collect();
|
||||
let text = Text::from_iter(vec!["The first line", "The second line"]);
|
||||
let text: Text = iter::once("The first line")
|
||||
.chain(iter::once("The second line"))
|
||||
.collect();
|
||||
```
|
||||
````
|
||||
|
||||
- [12f67e8](https://github.com/ratatui-org/ratatui/commit/12f67e810fad0f907546408192a2380b590ff7bd)
|
||||
*(uncategorized)* Impl Widget for `&str` and `String` by @kdheepak in [#952](https://github.com/ratatui-org/ratatui/pull/952)
|
||||
|
||||
````text
|
||||
Currently, `f.render_widget("hello world".bold(), area)` works but
|
||||
`f.render_widget("hello world", area)` doesn't. This PR changes that my
|
||||
implementing `Widget` for `&str` and `String`. This makes it easier to
|
||||
render strings with no styles as widgets.
|
||||
|
||||
Example usage:
|
||||
|
||||
```rust
|
||||
terminal.draw(|f| f.render_widget("Hello World!", f.size()))?;
|
||||
```
|
||||
|
||||
---------
|
||||
````
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
- [0207160](https://github.com/ratatui-org/ratatui/commit/02071607848c51250b4663722c52e19c8ce1c5e2)
|
||||
*(line)* Line truncation respects alignment by @TadoTheMiner in [#987](https://github.com/ratatui-org/ratatui/pull/987)
|
||||
|
||||
````text
|
||||
When rendering a `Line`, the line will be truncated:
|
||||
- on the right for left aligned lines
|
||||
- on the left for right aligned lines
|
||||
- on bot sides for centered lines
|
||||
|
||||
E.g. "Hello World" will be rendered as "Hello", "World", "lo wo" for
|
||||
left, right, centered lines respectively.
|
||||
````
|
||||
|
||||
Fixes:https://github.com/ratatui-org/ratatui/issues/932
|
||||
|
||||
- [c56f49b](https://github.com/ratatui-org/ratatui/commit/c56f49b9fb1c7f1c8c97749119e85f81882ca9a9)
|
||||
*(list)* Saturating_sub to fix highlight_symbol overflow by @mrjackwills in [#949](https://github.com/ratatui-org/ratatui/pull/949)
|
||||
|
||||
````text
|
||||
An overflow (pedantically an underflow) can occur if the
|
||||
highlight_symbol is a multi-byte char, and area is reduced to a size
|
||||
less than that char length.
|
||||
````
|
||||
|
||||
- [b7778e5](https://github.com/ratatui-org/ratatui/commit/b7778e5cd15d0d4b28f7bbb8b3c62950748e333a)
|
||||
*(paragraph)* Unit test typo by @joshka in [#1022](https://github.com/ratatui-org/ratatui/pull/1022)
|
||||
|
||||
- [943c043](https://github.com/ratatui-org/ratatui/commit/943c0431d968a82b23a2f31527f32e57f86f8a7c)
|
||||
*(scrollbar)* Dont render on 0 length track by @EdJoPaTo in [#964](https://github.com/ratatui-org/ratatui/pull/964)
|
||||
|
||||
````text
|
||||
Fixes a panic when `track_length - 1` is used. (clamp panics on `-1.0`
|
||||
being smaller than `0.0`)
|
||||
````
|
||||
|
||||
- [742a5ea](https://github.com/ratatui-org/ratatui/commit/742a5ead066bec14047f6ab7ffa3ac8307eea715)
|
||||
*(text)* Fix panic when rendering out of bounds by @joshka in [#997](https://github.com/ratatui-org/ratatui/pull/997)
|
||||
|
||||
````text
|
||||
Previously it was possible to cause a panic when rendering to an area
|
||||
outside of the buffer bounds. Instead this now correctly renders nothing
|
||||
to the buffer.
|
||||
````
|
||||
|
||||
- [f6c4e44](https://github.com/ratatui-org/ratatui/commit/f6c4e447e65fe10f4fc7fcc9e9c4312acad41096)
|
||||
*(uncategorized)* Ensure that paragraph correctly renders styled text by @joshka in [#992](https://github.com/ratatui-org/ratatui/pull/992)
|
||||
|
||||
````text
|
||||
Paragraph was ignoring the new `Text::style` field added in 0.26.0
|
||||
````
|
||||
|
||||
Fixes:https://github.com/ratatui-org/ratatui/issues/990
|
||||
|
||||
- [35e971f](https://github.com/ratatui-org/ratatui/commit/35e971f7ebb0deadc613b561b15511abd48bdb54)
|
||||
*(uncategorized)* Scrollbar thumb not visible on long lists by @ThomasMiz in [#959](https://github.com/ratatui-org/ratatui/pull/959)
|
||||
|
||||
````text
|
||||
When displaying somewhat-long lists, the `Scrollbar` widget sometimes did not display a thumb character, and only the track will be visible.
|
||||
````
|
||||
|
||||
### Refactor
|
||||
|
||||
- [6fd5f63](https://github.com/ratatui-org/ratatui/commit/6fd5f631bbd58156d9fcae196040bb0248097819)
|
||||
*(lint)* Prefer idiomatic for loops by @EdJoPaTo
|
||||
|
||||
- [37b957c](https://github.com/ratatui-org/ratatui/commit/37b957c7e167a7ecda07b8a60cee5de71efcc55e)
|
||||
*(lints)* Add lints to scrollbar by @EdJoPaTo
|
||||
|
||||
- [c12bcfe](https://github.com/ratatui-org/ratatui/commit/c12bcfefa26529610886040bd96f2b6762436b15)
|
||||
*(non-src)* Apply pedantic lints by @EdJoPaTo in [#976](https://github.com/ratatui-org/ratatui/pull/976)
|
||||
|
||||
````text
|
||||
Fixes many not yet enabled lints (mostly pedantic) on everything that is
|
||||
not the lib (examples, benches, tests). Therefore, this is not containing
|
||||
anything that can be a breaking change.
|
||||
|
||||
Lints are not enabled as that should be the job of #974. I created this
|
||||
as a separate PR as its mostly independent and would only clutter up the
|
||||
diff of #974 even more.
|
||||
|
||||
Also see
|
||||
https://github.com/ratatui-org/ratatui/pull/974#discussion_r1506458743
|
||||
|
||||
---------
|
||||
````
|
||||
|
||||
- [8719608](https://github.com/ratatui-org/ratatui/commit/8719608bdaf32ba92bdfdd60569cf73f7070a618)
|
||||
*(span)* Rename to_aligned_line into into_aligned_line by @EdJoPaTo in [#993](https://github.com/ratatui-org/ratatui/pull/993)
|
||||
|
||||
````text
|
||||
With the Rust method naming conventions these methods are into methods
|
||||
consuming the Span. Therefore, it's more consistent to use `into_`
|
||||
instead of `to_`.
|
||||
|
||||
```rust
|
||||
Span::to_centered_line
|
||||
Span::to_left_aligned_line
|
||||
Span::to_right_aligned_line
|
||||
```
|
||||
|
||||
Are marked deprecated and replaced with the following
|
||||
|
||||
```rust
|
||||
Span::into_centered_line
|
||||
Span::into_left_aligned_line
|
||||
Span::into_right_aligned_line
|
||||
```
|
||||
````
|
||||
|
||||
- [b831c56](https://github.com/ratatui-org/ratatui/commit/b831c5688c6f1fbfa6ae2bcd70d803a54fcf0196)
|
||||
*(widget-ref)* Clippy::needless_pass_by_value by @EdJoPaTo
|
||||
|
||||
- [359204c](https://github.com/ratatui-org/ratatui/commit/359204c9298cc26ea21807d886d596de0329bacc)
|
||||
*(uncategorized)* Simplify to io::Result by @EdJoPaTo in [#1016](https://github.com/ratatui-org/ratatui/pull/1016)
|
||||
|
||||
````text
|
||||
Simplifies the code, logic stays exactly the same.
|
||||
````
|
||||
|
||||
- [8e68db9](https://github.com/ratatui-org/ratatui/commit/8e68db9e2f57fcbf7cb5140006bbbd4dd80bf907)
|
||||
*(uncategorized)* Remove pointless default on internal structs by @EdJoPaTo in [#980](https://github.com/ratatui-org/ratatui/pull/980)
|
||||
|
||||
See #978
|
||||
|
||||
Also remove other derives. They are unused and just slow down
|
||||
compilation.
|
||||
|
||||
- [3be189e](https://github.com/ratatui-org/ratatui/commit/3be189e3c6ebd418d13138ff32bc4a749dc840cf)
|
||||
*(uncategorized)* Clippy::thread_local_initializer_can_be_made_const by @EdJoPaTo
|
||||
|
||||
````text
|
||||
enabled by default on nightly
|
||||
````
|
||||
|
||||
- [5c4efac](https://github.com/ratatui-org/ratatui/commit/5c4efacd1d70bb295d90ffaa73853dc206c187fb)
|
||||
*(uncategorized)* Clippy::map_err_ignore by @EdJoPaTo
|
||||
|
||||
- [bbb6d65](https://github.com/ratatui-org/ratatui/commit/bbb6d65e063df9a74ab6487b2216183c1fdd7230)
|
||||
*(uncategorized)* Clippy::else_if_without_else by @EdJoPaTo
|
||||
|
||||
- [fdb14dc](https://github.com/ratatui-org/ratatui/commit/fdb14dc7cd69788e2ed20709e767f7631b11ffa2)
|
||||
*(uncategorized)* Clippy::redundant_type_annotations by @EdJoPaTo
|
||||
|
||||
- [9b3b23a](https://github.com/ratatui-org/ratatui/commit/9b3b23ac14518a1ef23065d4a5da0fb047b18213)
|
||||
*(uncategorized)* Remove literal suffix by @EdJoPaTo
|
||||
|
||||
````text
|
||||
its not needed and can just be assumed
|
||||
````
|
||||
|
||||
related:clippy::(un)separated_literal_suffix
|
||||
|
||||
- [58b6e0b](https://github.com/ratatui-org/ratatui/commit/58b6e0be0f4db3d90005e130e4b84cd865179785)
|
||||
*(uncategorized)* Clippy::should_panic_without_expect by @EdJoPaTo
|
||||
|
||||
- [c870a41](https://github.com/ratatui-org/ratatui/commit/c870a41057ac0c14c2e72e762b37689dc32e7b23)
|
||||
*(uncategorized)* Clippy::many_single_char_names by @EdJoPaTo
|
||||
|
||||
- [a6036ad](https://github.com/ratatui-org/ratatui/commit/a6036ad78911653407f607f5efa556a055d3dce9)
|
||||
*(uncategorized)* Clippy::similar_names by @EdJoPaTo
|
||||
|
||||
- [060d26b](https://github.com/ratatui-org/ratatui/commit/060d26b6dc6e1027dbf46ae98b0ebba83701f941)
|
||||
*(uncategorized)* Clippy::match_same_arms by @EdJoPaTo
|
||||
|
||||
- [fcbea9e](https://github.com/ratatui-org/ratatui/commit/fcbea9ee68591344a29a7b2e83f1c8c878857aeb)
|
||||
*(uncategorized)* Clippy::uninlined_format_args by @EdJoPaTo
|
||||
|
||||
- [14b24e7](https://github.com/ratatui-org/ratatui/commit/14b24e75858af48f39d5880e7f6c9adeac1b1da9)
|
||||
*(uncategorized)* Clippy::if_not_else by @EdJoPaTo
|
||||
|
||||
- [5ed1f43](https://github.com/ratatui-org/ratatui/commit/5ed1f43c627053f25d9ee711677ebec6cb8fcd85)
|
||||
*(uncategorized)* Clippy::redundant_closure_for_method_calls by @EdJoPaTo
|
||||
|
||||
- [c8c7924](https://github.com/ratatui-org/ratatui/commit/c8c7924e0ca84351f5ed5c54e79611ce16d4dc37)
|
||||
*(uncategorized)* Clippy::too_many_lines by @EdJoPaTo
|
||||
|
||||
- [e3afe7c](https://github.com/ratatui-org/ratatui/commit/e3afe7c8a14c1cffd7de50782a7acf0f95f41673)
|
||||
*(uncategorized)* Clippy::unreadable_literal by @EdJoPaTo
|
||||
|
||||
- [a1f54de](https://github.com/ratatui-org/ratatui/commit/a1f54de7d60fa6c57be29bf8f02a675e58b7b9c2)
|
||||
*(uncategorized)* Clippy::bool_to_int_with_if by @EdJoPaTo
|
||||
|
||||
- [b8ea190](https://github.com/ratatui-org/ratatui/commit/b8ea190bf2cde8c18e2ac8276d2eb57d219db263)
|
||||
*(uncategorized)* Clippy::cast_lossless by @EdJoPaTo
|
||||
|
||||
- [0de5238](https://github.com/ratatui-org/ratatui/commit/0de5238ed3613f2d663f5e9628ca7b2aa205ed02)
|
||||
*(uncategorized)* Dead_code by @EdJoPaTo
|
||||
|
||||
````text
|
||||
enabled by default, only detected by nightly yet
|
||||
````
|
||||
|
||||
- [df5dddf](https://github.com/ratatui-org/ratatui/commit/df5dddfbc9c679d15a5a90ea79bb1f8946d5cb9c)
|
||||
*(uncategorized)* Unused_imports by @EdJoPaTo
|
||||
|
||||
````text
|
||||
enabled by default, only detected on nightly yet
|
||||
````
|
||||
|
||||
- [f1398ae](https://github.com/ratatui-org/ratatui/commit/f1398ae6cb1abd32106923d64844b482c7ba6f82)
|
||||
*(uncategorized)* Clippy::useless_vec by @EdJoPaTo
|
||||
|
||||
````text
|
||||
Lint enabled by default but only nightly finds this yet
|
||||
````
|
||||
|
||||
- [525848f](https://github.com/ratatui-org/ratatui/commit/525848ff4e066526d402fecf1d5b9c63cff1f22a)
|
||||
*(uncategorized)* Manually apply clippy::use_self for impl with lifetimes by @EdJoPaTo
|
||||
|
||||
- [660c718](https://github.com/ratatui-org/ratatui/commit/660c7183c7a10dc453d80dfb651d9534536960b9)
|
||||
*(uncategorized)* Clippy::empty_line_after_doc_comments by @EdJoPaTo
|
||||
|
||||
- [ab951fa](https://github.com/ratatui-org/ratatui/commit/ab951fae8166c9321728ba942b48552dfe4d9c55)
|
||||
*(uncategorized)* Clippy::return_self_not_must_use by @EdJoPaTo
|
||||
|
||||
- [3cd4369](https://github.com/ratatui-org/ratatui/commit/3cd436917649a93b4b80d0c4a0343284e0585522)
|
||||
*(uncategorized)* Clippy::doc_markdown by @EdJoPaTo
|
||||
|
||||
- [9bc014d](https://github.com/ratatui-org/ratatui/commit/9bc014d7f16efdb70fcd6b6b786fe74eac7b9bdf)
|
||||
*(uncategorized)* Clippy::items_after_statements by @EdJoPaTo
|
||||
|
||||
- [36a0cd5](https://github.com/ratatui-org/ratatui/commit/36a0cd56e5645533a1d6c2720536fa10a56b0d40)
|
||||
*(uncategorized)* Clippy::deref_by_slicing by @EdJoPaTo
|
||||
|
||||
- [f7f6692](https://github.com/ratatui-org/ratatui/commit/f7f66928a8833532a3bc97292665640285e7aafa)
|
||||
*(uncategorized)* Clippy::equatable_if_let by @EdJoPaTo
|
||||
|
||||
- [01418eb](https://github.com/ratatui-org/ratatui/commit/01418eb7c2e1874cb4070828c485d81ea171b18d)
|
||||
*(uncategorized)* Clippy::default_trait_access by @EdJoPaTo
|
||||
|
||||
- [8536760](https://github.com/ratatui-org/ratatui/commit/8536760e7802a498f7c6d9fe8fb4c7920a1c6e71)
|
||||
*(uncategorized)* Clippy::inefficient_to_string by @EdJoPaTo
|
||||
|
||||
- [a558b19](https://github.com/ratatui-org/ratatui/commit/a558b19c9a7b90a1ed3f309301f49f0b483e02ec)
|
||||
*(uncategorized)* Clippy::implicit_clone by @EdJoPaTo
|
||||
|
||||
- [5b00e3a](https://github.com/ratatui-org/ratatui/commit/5b00e3aae98cb5c20c10bec944948a75ac83f956)
|
||||
*(uncategorized)* Clippy::use_self by @EdJoPaTo
|
||||
|
||||
- [27680c0](https://github.com/ratatui-org/ratatui/commit/27680c05ce1670f026ad23c446ada321c1c755f0)
|
||||
*(uncategorized)* Clippy::semicolon_if_nothing_returned by @EdJoPaTo
|
||||
|
||||
### Documentation
|
||||
|
||||
- [14461c3](https://github.com/ratatui-org/ratatui/commit/14461c3a3554c95905ebca433fc3d4dae1e1acda)
|
||||
*(breaking-changes)* Typos and markdownlint by @EdJoPaTo in [#1009](https://github.com/ratatui-org/ratatui/pull/1009)
|
||||
|
||||
- [d0067c8](https://github.com/ratatui-org/ratatui/commit/d0067c8815d5244d319934d58a9366c8ad36b3e5)
|
||||
*(license)* Update copyright years by @orhun in [#962](https://github.com/ratatui-org/ratatui/pull/962)
|
||||
|
||||
- [88bfb5a](https://github.com/ratatui-org/ratatui/commit/88bfb5a43027cf3410ad560772c5bfdbaa3d58b7)
|
||||
*(text)* Update Text and Line docs by @joshka in [#969](https://github.com/ratatui-org/ratatui/pull/969)
|
||||
|
||||
- [3b002fd](https://github.com/ratatui-org/ratatui/commit/3b002fdcab964ce3f65f55dc8053d9678ae247a3)
|
||||
*(uncategorized)* Update incompatible code warning in examples readme by @joshka in [#1013](https://github.com/ratatui-org/ratatui/pull/1013)
|
||||
|
||||
### Performance
|
||||
|
||||
- [e02f476](https://github.com/ratatui-org/ratatui/commit/e02f4768ce2ee30473200fe98e2687e42acb9c33)
|
||||
*(borders)* Allow border!() in const by @EdJoPaTo in [#977](https://github.com/ratatui-org/ratatui/pull/977)
|
||||
|
||||
````text
|
||||
This allows more compiler optimizations when the macro is used.
|
||||
````
|
||||
|
||||
- [541f0f9](https://github.com/ratatui-org/ratatui/commit/541f0f99538762a07d68a71b2989ecc6ff6f71ef)
|
||||
*(cell)* Use const CompactString::new_inline by @EdJoPaTo in [#979](https://github.com/ratatui-org/ratatui/pull/979)
|
||||
|
||||
````text
|
||||
Some minor find when messing around trying to `const` all the things.
|
||||
|
||||
While `reset()` and `default()` can not be `const` it's still a benefit
|
||||
when their contents are.
|
||||
````
|
||||
|
||||
- [65e7923](https://github.com/ratatui-org/ratatui/commit/65e792375396c3160d76964ef0dfc4fb1e53be41)
|
||||
*(scrollbar)* Const creation by @EdJoPaTo in [#963](https://github.com/ratatui-org/ratatui/pull/963)
|
||||
|
||||
````text
|
||||
A bunch of `const fn` allow for more performance and `Default` now uses the `const` new implementations.
|
||||
````
|
||||
|
||||
- [8195f52](https://github.com/ratatui-org/ratatui/commit/8195f526cb4b321f337dcbe9e689cc7f6eb84065)
|
||||
*(uncategorized)* Clippy::needless_pass_by_value by @EdJoPaTo
|
||||
|
||||
- [183c07e](https://github.com/ratatui-org/ratatui/commit/183c07ef436cbb8fb0bec418042b44b4fedd836f)
|
||||
*(uncategorized)* Clippy::trivially_copy_pass_by_ref by @EdJoPaTo
|
||||
|
||||
- [a13867f](https://github.com/ratatui-org/ratatui/commit/a13867ffceb2f8f57f4540049754c2f916fd3efc)
|
||||
*(uncategorized)* Clippy::cloned_instead_of_copied by @EdJoPaTo
|
||||
|
||||
- [3834374](https://github.com/ratatui-org/ratatui/commit/3834374652b46c5ddbfedcf8dea2086fd762f884)
|
||||
*(uncategorized)* Clippy::missing_const_for_fn by @EdJoPaTo
|
||||
|
||||
### Miscellaneous Tasks
|
||||
|
||||
- [125ee92](https://github.com/ratatui-org/ratatui/commit/125ee929ee9009b97a270e2e105a3f1167ab13d7)
|
||||
*(docs)* Fix: fix typos in crate documentation by @orhun in [#1002](https://github.com/ratatui-org/ratatui/pull/1002)
|
||||
|
||||
- [38c17e0](https://github.com/ratatui-org/ratatui/commit/38c17e091cf3f4de2d196ecdd6a40129019eafc4)
|
||||
*(editorconfig)* Set and apply some defaults by @EdJoPaTo
|
||||
|
||||
- [07da90a](https://github.com/ratatui-org/ratatui/commit/07da90a7182035b24f870bcbf0a0ffaad75eb48b)
|
||||
*(funding)* Add eth address for receiving funds from drips.network by @BenJam in [#994](https://github.com/ratatui-org/ratatui/pull/994)
|
||||
|
||||
- [078e97e](https://github.com/ratatui-org/ratatui/commit/078e97e4ff65c02afa7c884914ecd38a6e959b58)
|
||||
*(github)* Add EdJoPaTo as a maintainer by @orhun in [#986](https://github.com/ratatui-org/ratatui/pull/986)
|
||||
|
||||
- [b0314c5](https://github.com/ratatui-org/ratatui/commit/b0314c5731b32f51f5b6ca71a5194c6d7f265972)
|
||||
*(uncategorized)* Remove conventional commit check for PR by @Valentin271 in [#950](https://github.com/ratatui-org/ratatui/pull/950)
|
||||
|
||||
````text
|
||||
This removes conventional commit check for PRs.
|
||||
|
||||
Since we use the PR title and description this is useless. It fails a
|
||||
lot of time and we ignore it.
|
||||
|
||||
IMPORTANT NOTE: This does **not** mean Ratatui abandons conventional
|
||||
commits. This only relates to commits in PRs.
|
||||
````
|
||||
|
||||
### Build
|
||||
|
||||
- [6e6ba27](https://github.com/ratatui-org/ratatui/commit/6e6ba27a122560bcf47b0efd20b7095f1bfd8714)
|
||||
*(lint)* Warn on pedantic and allow the rest by @EdJoPaTo
|
||||
|
||||
- [c4ce7e8](https://github.com/ratatui-org/ratatui/commit/c4ce7e8ff6f00875e1ead5b68052f0db737bd44d)
|
||||
*(uncategorized)* Enable more satisfied lints by @EdJoPaTo
|
||||
|
||||
````text
|
||||
These lints dont generate warnings and therefore dont need refactoring.
|
||||
I think they are useful in the future.
|
||||
````
|
||||
|
||||
- [a4e84a6](https://github.com/ratatui-org/ratatui/commit/a4e84a6a7f6f5b80903799028f30e2a4438f2807)
|
||||
*(uncategorized)* Increase msrv to 1.74.0 by @EdJoPaTo [**breaking**]
|
||||
|
||||
````text
|
||||
configure lints in Cargo.toml requires 1.74.0
|
||||
````
|
||||
|
||||
BREAKING CHANGE:rust 1.74 is required now
|
||||
|
||||
### New Contributors
|
||||
|
||||
* @TadoTheMiner made their first contribution in [#987](https://github.com/ratatui-org/ratatui/pull/987)
|
||||
* @BenJam made their first contribution in [#994](https://github.com/ratatui-org/ratatui/pull/994)
|
||||
* @CameronBarnes made their first contribution in [#958](https://github.com/ratatui-org/ratatui/pull/958)
|
||||
* @ThomasMiz made their first contribution in [#959](https://github.com/ratatui-org/ratatui/pull/959)
|
||||
|
||||
**Full Changelog**: https://github.com/ratatui-org/ratatui/compare/v0.26.1...0.26.2
|
||||
|
||||
## [0.26.1](https://github.com/ratatui-org/ratatui/releases/tag/v0.26.1) - 2024-02-12
|
||||
## [0.26.1](https://github.com/ratatui-org/ratatui/releases/tag/0.26.1) - 2024-02-12
|
||||
|
||||
This is a patch release that fixes bugs and adds enhancements, including new iterators, title options for blocks, and various rendering improvements. ✨
|
||||
|
||||
@@ -611,7 +161,7 @@ Here is the list of contributors who have contributed to `ratatui` for the first
|
||||
* @mo8it
|
||||
* @m4rch3n1ng
|
||||
|
||||
## [0.26.0](https://github.com/ratatui-org/ratatui/releases/tag/v0.26.0) - 2024-02-02
|
||||
## [0.26.0](https://github.com/ratatui-org/ratatui/releases/tag/0.26.0) - 2024-02-02
|
||||
|
||||
We are excited to announce the new version of `ratatui` - a Rust library that's all about cooking up TUIs 🐭
|
||||
|
||||
@@ -2268,7 +1818,7 @@ Shout out to our new sponsors!
|
||||
* @atuinsh
|
||||
* @JeftavanderHorst!
|
||||
|
||||
## [0.25.0](https://github.com/ratatui-org/ratatui/releases/tag/v0.25.0) - 2023-12-18
|
||||
## [0.25.0](https://github.com/ratatui-org/ratatui/releases/tag/0.25.0) - 2023-12-18
|
||||
|
||||
We are thrilled to announce the new version of `ratatui` - a Rust library that's all about cooking up TUIs 🐭
|
||||
|
||||
@@ -2753,7 +2303,7 @@ Here is the list of contributors who have contributed to `ratatui` for the first
|
||||
* @YeungKC
|
||||
* @lyuha
|
||||
|
||||
## [0.24.0](https://github.com/ratatui-org/ratatui/releases/tag/v0.24.0) - 2023-10-23
|
||||
## [0.24.0](https://github.com/ratatui-org/ratatui/releases/tag/0.24.0) - 2023-10-23
|
||||
|
||||
We are excited to announce the new version of `ratatui` - a Rust library that's all about cooking up TUIs 🐭
|
||||
|
||||
|
||||
12
Cargo.toml
12
Cargo.toml
@@ -1,13 +1,11 @@
|
||||
[package]
|
||||
name = "ratatui"
|
||||
version = "0.26.2" # crate version
|
||||
version = "0.26.1" # crate version
|
||||
authors = ["Florian Dehau <work@fdehau.com>", "The Ratatui Developers"]
|
||||
description = "A library that's all about cooking up terminal user interfaces"
|
||||
documentation = "https://docs.rs/ratatui/latest/ratatui/"
|
||||
repository = "https://github.com/ratatui-org/ratatui"
|
||||
homepage = "https://ratatui.rs"
|
||||
keywords = ["tui", "terminal", "dashboard"]
|
||||
categories = ["command-line-interface"]
|
||||
repository = "https://github.com/ratatui-org/ratatui"
|
||||
readme = "README.md"
|
||||
license = "MIT"
|
||||
exclude = [
|
||||
@@ -41,7 +39,7 @@ unicode-segmentation = "1.10"
|
||||
unicode-width = "0.1"
|
||||
document-features = { version = "0.2.7", optional = true }
|
||||
lru = "0.12.0"
|
||||
stability = "0.2.0"
|
||||
stability = "0.1.1"
|
||||
compact_str = "0.7.1"
|
||||
|
||||
[dev-dependencies]
|
||||
@@ -60,14 +58,12 @@ palette = "0.7.3"
|
||||
pretty_assertions = "1.4.0"
|
||||
rand = "0.8.5"
|
||||
rand_chacha = "0.3.1"
|
||||
rstest = "0.19.0"
|
||||
rstest = "0.18.2"
|
||||
serde_json = "1.0.109"
|
||||
|
||||
[lints.rust]
|
||||
unsafe_code = "forbid"
|
||||
|
||||
[lints.clippy]
|
||||
cargo = { level = "warn", priority = -1 }
|
||||
pedantic = { level = "warn", priority = -1 }
|
||||
cast_possible_truncation = "allow"
|
||||
cast_possible_wrap = "allow"
|
||||
|
||||
23
README.md
23
README.md
@@ -162,7 +162,7 @@ fn handle_events() -> io::Result<bool> {
|
||||
fn ui(frame: &mut Frame) {
|
||||
frame.render_widget(
|
||||
Paragraph::new("Hello World!")
|
||||
.block(Block::bordered().title("Greeting")),
|
||||
.block(Block::default().title("Greeting").borders(Borders::ALL)),
|
||||
frame.size(),
|
||||
);
|
||||
}
|
||||
@@ -207,11 +207,11 @@ fn ui(frame: &mut Frame) {
|
||||
)
|
||||
.split(main_layout[1]);
|
||||
frame.render_widget(
|
||||
Block::bordered().title("Left"),
|
||||
Block::default().borders(Borders::ALL).title("Left"),
|
||||
inner_layout[0],
|
||||
);
|
||||
frame.render_widget(
|
||||
Block::bordered().title("Right"),
|
||||
Block::default().borders(Borders::ALL).title("Right"),
|
||||
inner_layout[1],
|
||||
);
|
||||
}
|
||||
@@ -327,23 +327,24 @@ Running this example produces the following output:
|
||||
[Termwiz]: https://crates.io/crates/termwiz
|
||||
[tui-rs]: https://crates.io/crates/tui
|
||||
[GitHub Sponsors]: https://github.com/sponsors/ratatui-org
|
||||
[Crate Badge]: https://img.shields.io/crates/v/ratatui?logo=rust&style=flat-square&logoColor=E05D44&color=E05D44
|
||||
[License Badge]: https://img.shields.io/crates/l/ratatui?style=flat-square&color=1370D3
|
||||
[CI Badge]: https://img.shields.io/github/actions/workflow/status/ratatui-org/ratatui/ci.yml?style=flat-square&logo=github
|
||||
[Crate Badge]: https://img.shields.io/crates/v/ratatui?logo=rust&style=flat-square
|
||||
[License Badge]: https://img.shields.io/crates/l/ratatui?style=flat-square
|
||||
[CI Badge]:
|
||||
https://img.shields.io/github/actions/workflow/status/ratatui-org/ratatui/ci.yml?style=flat-square&logo=github
|
||||
[CI Workflow]: https://github.com/ratatui-org/ratatui/actions/workflows/ci.yml
|
||||
[Codecov Badge]:
|
||||
https://img.shields.io/codecov/c/github/ratatui-org/ratatui?logo=codecov&style=flat-square&token=BAQ8SOKEST&color=C43AC3&logoColor=C43AC3
|
||||
https://img.shields.io/codecov/c/github/ratatui-org/ratatui?logo=codecov&style=flat-square&token=BAQ8SOKEST
|
||||
[Codecov]: https://app.codecov.io/gh/ratatui-org/ratatui
|
||||
[Deps.rs Badge]: https://deps.rs/repo/github/ratatui-org/ratatui/status.svg?style=flat-square
|
||||
[Deps.rs]: https://deps.rs/repo/github/ratatui-org/ratatui
|
||||
[Discord Badge]:
|
||||
https://img.shields.io/discord/1070692720437383208?label=discord&logo=discord&style=flat-square&color=1370D3&logoColor=1370D3
|
||||
https://img.shields.io/discord/1070692720437383208?label=discord&logo=discord&style=flat-square
|
||||
[Discord Server]: https://discord.gg/pMCEU9hNEj
|
||||
[Docs Badge]: https://img.shields.io/docsrs/ratatui?logo=rust&style=flat-square&logoColor=E05D44
|
||||
[Docs Badge]: https://img.shields.io/docsrs/ratatui?logo=rust&style=flat-square
|
||||
[Matrix Badge]:
|
||||
https://img.shields.io/matrix/ratatui-general%3Amatrix.org?style=flat-square&logo=matrix&label=Matrix&color=C43AC3
|
||||
https://img.shields.io/matrix/ratatui-general%3Amatrix.org?style=flat-square&logo=matrix&label=Matrix
|
||||
[Matrix]: https://matrix.to/#/#ratatui:matrix.org
|
||||
[Sponsors Badge]: https://img.shields.io/github/sponsors/ratatui-org?logo=github&style=flat-square&color=1370D3
|
||||
[Sponsors Badge]: https://img.shields.io/github/sponsors/ratatui-org?logo=github&style=flat-square
|
||||
|
||||
<!-- cargo-rdme end -->
|
||||
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
use criterion::{criterion_group, criterion_main, BatchSize, Bencher, Criterion};
|
||||
use criterion::{criterion_group, criterion_main, BatchSize, Bencher, BenchmarkId, Criterion};
|
||||
use ratatui::{
|
||||
buffer::Buffer,
|
||||
layout::{Alignment, Rect},
|
||||
layout::Rect,
|
||||
prelude::Alignment,
|
||||
widgets::{
|
||||
block::{Position, Title},
|
||||
Block, Padding, Widget,
|
||||
Block, Borders, Padding, Widget,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -12,31 +13,32 @@ use ratatui::{
|
||||
fn block(c: &mut Criterion) {
|
||||
let mut group = c.benchmark_group("block");
|
||||
|
||||
for (width, height) in [
|
||||
(100, 50), // vertically split screen
|
||||
(200, 50), // 1080p fullscreen with medium font
|
||||
(256, 256), // Max sized area
|
||||
for buffer_size in [
|
||||
Rect::new(0, 0, 100, 50), // vertically split screen
|
||||
Rect::new(0, 0, 200, 50), // 1080p fullscreen with medium font
|
||||
Rect::new(0, 0, 256, 256), // Max sized area
|
||||
] {
|
||||
let buffer_size = Rect::new(0, 0, width, height);
|
||||
let buffer_area = buffer_size.area();
|
||||
|
||||
// Render an empty block
|
||||
group.bench_with_input(
|
||||
format!("render_empty/{width}x{height}"),
|
||||
BenchmarkId::new("render_empty", buffer_area),
|
||||
&Block::new(),
|
||||
|b, block| render(b, block, buffer_size),
|
||||
);
|
||||
|
||||
// Render with all features
|
||||
group.bench_with_input(
|
||||
format!("render_all_feature/{width}x{height}"),
|
||||
&Block::bordered()
|
||||
.padding(Padding::new(5, 5, 2, 2))
|
||||
BenchmarkId::new("render_all_feature", buffer_area),
|
||||
&Block::new()
|
||||
.borders(Borders::ALL)
|
||||
.title("test title")
|
||||
.title(
|
||||
Title::from("bottom left title")
|
||||
.alignment(Alignment::Right)
|
||||
.position(Position::Bottom),
|
||||
),
|
||||
)
|
||||
.padding(Padding::new(5, 5, 2, 2)),
|
||||
|b, block| render(b, block, buffer_size),
|
||||
);
|
||||
}
|
||||
|
||||
35
cliff.toml
35
cliff.toml
@@ -1,9 +1,4 @@
|
||||
# git-cliff ~ configuration file
|
||||
# https://git-cliff.org/docs/configuration
|
||||
|
||||
[remote.github]
|
||||
owner = "ratatui-org"
|
||||
repo = "ratatui"
|
||||
# configuration for https://github.com/orhun/git-cliff
|
||||
|
||||
[changelog]
|
||||
# changelog header
|
||||
@@ -27,9 +22,7 @@ body = """
|
||||
|
||||
{% macro commit(commit) -%}
|
||||
- [{{ commit.id | truncate(length=7, end="") }}]({{ "https://github.com/ratatui-org/ratatui/commit/" ~ commit.id }})
|
||||
*({{commit.scope | default(value = "uncategorized") | lower }})* {{ commit.message | upper_first | trim }}\
|
||||
{% if commit.github.username %} by @{{ commit.github.username }}{%- endif -%}\
|
||||
{% if commit.github.pr_number %} in [#{{ commit.github.pr_number }}]({{ self::remote_url() }}/pull/{{ commit.github.pr_number }}){%- endif %}\
|
||||
*({{commit.scope | default(value = "uncategorized") | lower }})* {{ commit.message | upper_first }}
|
||||
{%- if commit.breaking %} [**breaking**]{% endif %}
|
||||
{%- if commit.body %}
|
||||
|
||||
@@ -56,28 +49,6 @@ body = """
|
||||
{%- endif -%}
|
||||
{%- endfor -%}
|
||||
{%- endfor %}
|
||||
|
||||
{% if github.contributors | filter(attribute="is_first_time", value=true) | length != 0 %}
|
||||
### New Contributors
|
||||
{%- endif %}\
|
||||
{% for contributor in github.contributors | filter(attribute="is_first_time", value=true) %}
|
||||
* @{{ contributor.username }} made their first contribution
|
||||
{%- if contributor.pr_number %} in \
|
||||
[#{{ contributor.pr_number }}]({{ self::remote_url() }}/pull/{{ contributor.pr_number }}) \
|
||||
{%- endif %}
|
||||
{%- endfor -%}
|
||||
|
||||
{% if version %}
|
||||
{% if previous.version %}
|
||||
**Full Changelog**: {{ self::remote_url() }}/compare/{{ previous.version }}...{{ version }}
|
||||
{% endif %}
|
||||
{% else -%}
|
||||
{% raw %}\n{% endraw %}
|
||||
{% endif %}
|
||||
|
||||
{%- macro remote_url() -%}
|
||||
https://github.com/{{ remote.github.owner }}/{{ remote.github.repo }}\
|
||||
{% endmacro %}
|
||||
"""
|
||||
|
||||
|
||||
@@ -97,7 +68,7 @@ filter_unconventional = true
|
||||
split_commits = false
|
||||
# regex for preprocessing the commit messages
|
||||
commit_preprocessors = [
|
||||
{ pattern = '\((\w+\s)?#([0-9]+)\)', replace = "" },
|
||||
{ pattern = '\((\w+\s)?#([0-9]+)\)', replace = "([#${2}](https://github.com/ratatui-org/ratatui/issues/${2}))" },
|
||||
{ pattern = '(better safe shared layout cache)', replace = "perf(layout): ${1}" },
|
||||
{ pattern = '(Clarify README.md)', replace = "docs(readme): ${1}" },
|
||||
{ pattern = '(Update README.md)', replace = "docs(readme): ${1}" },
|
||||
|
||||
15
clippy.toml
15
clippy.toml
@@ -1,15 +0,0 @@
|
||||
# https://rust-lang.github.io/rust-clippy/master/index.html#/multiple_crate_versions
|
||||
# ratatui -> bitflags v2.3
|
||||
# termwiz -> wezterm-blob-leases -> mac_address -> nix -> bitflags v1.3.2
|
||||
# crossterm -> all the windows- deps https://github.com/ratatui-org/ratatui/pull/1064#issuecomment-2078848980
|
||||
allowed-duplicate-crates = [
|
||||
"bitflags",
|
||||
"windows-targets",
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
]
|
||||
@@ -1,20 +1,20 @@
|
||||
# Examples
|
||||
|
||||
This folder might use unreleased code. View the examples for the latest release instead.
|
||||
This folder contains unreleased code. View the [examples for the latest release
|
||||
(0.25.0)](https://github.com/ratatui-org/ratatui/tree/v0.25.0/examples) instead.
|
||||
|
||||
> [!WARNING]
|
||||
>
|
||||
> There may be backwards incompatible changes in these examples, as they are designed to compile
|
||||
> There are backwards incompatible changes in these examples, as they are designed to compile
|
||||
> against the `main` branch.
|
||||
>
|
||||
> There are a few workaround for this problem:
|
||||
>
|
||||
> - View the examples as they were when the latest version was release by selecting the tag that
|
||||
> matches that version. E.g. <https://github.com/ratatui-org/ratatui/tree/v0.26.1/examples>.
|
||||
> - If you're viewing this file on GitHub, there is a combo box at the top of this page which
|
||||
> allows you to select any previous tagged version.
|
||||
> - To view the code locally, checkout the tag. E.g. `git switch --detach v0.26.1`.
|
||||
> - Use the latest [alpha version of Ratatui] in your app. These are released weekly on Saturdays.
|
||||
> matches that version. E.g. <https://github.com/ratatui-org/ratatui/tree/v0.25.0/examples>. There
|
||||
> is a combo box at the top of this page which allows you to select any previous tagged version.
|
||||
> - To view the code locally, checkout the tag using `git switch --detach v0.25.0`.
|
||||
> - Use the latest [alpha version of Ratatui]. These are released weekly on Saturdays.
|
||||
> - Compile your code against the main branch either locally by adding e.g. `path = "../ratatui"` to
|
||||
> the dependency, or remotely by adding `git = "https://github.com/ratatui-org/ratatui"`
|
||||
>
|
||||
|
||||
@@ -26,7 +26,7 @@ use crossterm::{
|
||||
};
|
||||
use ratatui::{
|
||||
prelude::*,
|
||||
widgets::{Bar, BarChart, BarGroup, Block, Paragraph},
|
||||
widgets::{Bar, BarChart, BarGroup, Block, Borders, Paragraph},
|
||||
};
|
||||
|
||||
struct Company<'a> {
|
||||
@@ -159,7 +159,7 @@ fn ui(frame: &mut Frame, app: &App) {
|
||||
let [left, right] = horizontal.areas(bottom);
|
||||
|
||||
let barchart = BarChart::default()
|
||||
.block(Block::bordered().title("Data1"))
|
||||
.block(Block::default().title("Data1").borders(Borders::ALL))
|
||||
.data(&app.data)
|
||||
.bar_width(9)
|
||||
.bar_style(Style::default().fg(Color::Yellow))
|
||||
@@ -217,7 +217,7 @@ fn draw_bar_with_group_labels(f: &mut Frame, app: &App, area: Rect) {
|
||||
let groups = create_groups(app, false);
|
||||
|
||||
let mut barchart = BarChart::default()
|
||||
.block(Block::bordered().title("Data1"))
|
||||
.block(Block::default().title("Data1").borders(Borders::ALL))
|
||||
.bar_width(7)
|
||||
.group_gap(3);
|
||||
|
||||
@@ -246,7 +246,7 @@ fn draw_horizontal_bars(f: &mut Frame, app: &App, area: Rect) {
|
||||
let groups = create_groups(app, true);
|
||||
|
||||
let mut barchart = BarChart::default()
|
||||
.block(Block::bordered().title("Data1"))
|
||||
.block(Block::default().title("Data1").borders(Borders::ALL))
|
||||
.bar_width(1)
|
||||
.group_gap(1)
|
||||
.bar_gap(0)
|
||||
@@ -292,7 +292,9 @@ fn draw_legend(f: &mut Frame, area: Rect) {
|
||||
)]),
|
||||
];
|
||||
|
||||
let block = Block::bordered().style(Style::default().fg(Color::White));
|
||||
let block = Block::default()
|
||||
.borders(Borders::ALL)
|
||||
.style(Style::default().fg(Color::White));
|
||||
let paragraph = Paragraph::new(text).block(block);
|
||||
f.render_widget(paragraph, area);
|
||||
}
|
||||
|
||||
@@ -160,20 +160,23 @@ fn render_border_type(
|
||||
frame: &mut Frame,
|
||||
area: Rect,
|
||||
) {
|
||||
let block = Block::bordered()
|
||||
let block = Block::new()
|
||||
.borders(Borders::ALL)
|
||||
.border_type(border_type)
|
||||
.title(format!("BorderType::{border_type:#?}"));
|
||||
frame.render_widget(paragraph.clone().block(block), area);
|
||||
}
|
||||
fn render_styled_borders(paragraph: &Paragraph, frame: &mut Frame, area: Rect) {
|
||||
let block = Block::bordered()
|
||||
let block = Block::new()
|
||||
.borders(Borders::ALL)
|
||||
.border_style(Style::new().blue().on_white().bold().italic())
|
||||
.title("Styled borders");
|
||||
frame.render_widget(paragraph.clone().block(block), area);
|
||||
}
|
||||
|
||||
fn render_styled_block(paragraph: &Paragraph, frame: &mut Frame, area: Rect) {
|
||||
let block = Block::bordered()
|
||||
let block = Block::new()
|
||||
.borders(Borders::ALL)
|
||||
.style(Style::new().blue().on_white().bold().italic())
|
||||
.title("Styled block");
|
||||
frame.render_widget(paragraph.clone().block(block), area);
|
||||
@@ -181,7 +184,8 @@ fn render_styled_block(paragraph: &Paragraph, frame: &mut Frame, area: Rect) {
|
||||
|
||||
// Note: this currently renders incorrectly, see https://github.com/ratatui-org/ratatui/issues/349
|
||||
fn render_styled_title(paragraph: &Paragraph, frame: &mut Frame, area: Rect) {
|
||||
let block = Block::bordered()
|
||||
let block = Block::new()
|
||||
.borders(Borders::ALL)
|
||||
.title("Styled title")
|
||||
.title_style(Style::new().blue().on_white().bold().italic());
|
||||
frame.render_widget(paragraph.clone().block(block), area);
|
||||
@@ -192,19 +196,21 @@ fn render_styled_title_content(paragraph: &Paragraph, frame: &mut Frame, area: R
|
||||
"Styled ".blue().on_white().bold().italic(),
|
||||
"title content".red().on_white().bold().italic(),
|
||||
]);
|
||||
let block = Block::bordered().title(title);
|
||||
let block = Block::new().borders(Borders::ALL).title(title);
|
||||
frame.render_widget(paragraph.clone().block(block), area);
|
||||
}
|
||||
|
||||
fn render_multiple_titles(paragraph: &Paragraph, frame: &mut Frame, area: Rect) {
|
||||
let block = Block::bordered()
|
||||
let block = Block::new()
|
||||
.borders(Borders::ALL)
|
||||
.title("Multiple".blue().on_white().bold().italic())
|
||||
.title("Titles".red().on_white().bold().italic());
|
||||
frame.render_widget(paragraph.clone().block(block), area);
|
||||
}
|
||||
|
||||
fn render_multiple_title_positions(paragraph: &Paragraph, frame: &mut Frame, area: Rect) {
|
||||
let block = Block::bordered()
|
||||
let block = Block::new()
|
||||
.borders(Borders::ALL)
|
||||
.title(
|
||||
Title::from("top left")
|
||||
.position(Position::Top)
|
||||
@@ -239,15 +245,16 @@ fn render_multiple_title_positions(paragraph: &Paragraph, frame: &mut Frame, are
|
||||
}
|
||||
|
||||
fn render_padding(paragraph: &Paragraph, frame: &mut Frame, area: Rect) {
|
||||
let block = Block::bordered()
|
||||
.padding(Padding::new(5, 10, 1, 2))
|
||||
.title("Padding");
|
||||
let block = Block::new()
|
||||
.borders(Borders::ALL)
|
||||
.title("Padding")
|
||||
.padding(Padding::new(5, 10, 1, 2));
|
||||
frame.render_widget(paragraph.clone().block(block), area);
|
||||
}
|
||||
|
||||
fn render_nested_blocks(paragraph: &Paragraph, frame: &mut Frame, area: Rect) {
|
||||
let outer_block = Block::bordered().title("Outer block");
|
||||
let inner_block = Block::bordered().title("Inner block");
|
||||
let outer_block = Block::new().borders(Borders::ALL).title("Outer block");
|
||||
let inner_block = Block::new().borders(Borders::ALL).title("Inner block");
|
||||
let inner = outer_block.inner(area);
|
||||
frame.render_widget(outer_block, area);
|
||||
frame.render_widget(paragraph.clone().block(inner_block), inner);
|
||||
|
||||
@@ -137,7 +137,7 @@ impl App {
|
||||
|
||||
fn map_canvas(&self) -> impl Widget + '_ {
|
||||
Canvas::default()
|
||||
.block(Block::bordered().title("World"))
|
||||
.block(Block::default().borders(Borders::ALL).title("World"))
|
||||
.marker(self.marker)
|
||||
.paint(|ctx| {
|
||||
ctx.draw(&Map {
|
||||
@@ -152,7 +152,7 @@ impl App {
|
||||
|
||||
fn pong_canvas(&self) -> impl Widget + '_ {
|
||||
Canvas::default()
|
||||
.block(Block::bordered().title("Pong"))
|
||||
.block(Block::default().borders(Borders::ALL).title("Pong"))
|
||||
.marker(self.marker)
|
||||
.paint(|ctx| {
|
||||
ctx.draw(&self.ball);
|
||||
@@ -167,7 +167,7 @@ impl App {
|
||||
let bottom = 0.0;
|
||||
let top = f64::from(area.height).mul_add(2.0, -4.0);
|
||||
Canvas::default()
|
||||
.block(Block::bordered().title("Rects"))
|
||||
.block(Block::default().borders(Borders::ALL).title("Rects"))
|
||||
.marker(self.marker)
|
||||
.x_bounds([left, right])
|
||||
.y_bounds([bottom, top])
|
||||
|
||||
@@ -26,7 +26,7 @@ use crossterm::{
|
||||
};
|
||||
use ratatui::{
|
||||
prelude::*,
|
||||
widgets::{block::Title, Axis, Block, Chart, Dataset, GraphType, LegendPosition},
|
||||
widgets::{block::Title, Axis, Block, Borders, Chart, Dataset, GraphType, LegendPosition},
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
@@ -184,7 +184,11 @@ fn render_chart1(f: &mut Frame, area: Rect, app: &App) {
|
||||
];
|
||||
|
||||
let chart = Chart::new(datasets)
|
||||
.block(Block::bordered().title("Chart 1".cyan().bold()))
|
||||
.block(
|
||||
Block::default()
|
||||
.title("Chart 1".cyan().bold())
|
||||
.borders(Borders::ALL),
|
||||
)
|
||||
.x_axis(
|
||||
Axis::default()
|
||||
.title("X Axis")
|
||||
@@ -213,11 +217,13 @@ fn render_line_chart(f: &mut Frame, area: Rect) {
|
||||
|
||||
let chart = Chart::new(datasets)
|
||||
.block(
|
||||
Block::bordered().title(
|
||||
Title::default()
|
||||
.content("Line chart".cyan().bold())
|
||||
.alignment(Alignment::Center),
|
||||
),
|
||||
Block::default()
|
||||
.title(
|
||||
Title::default()
|
||||
.content("Line chart".cyan().bold())
|
||||
.alignment(Alignment::Center),
|
||||
)
|
||||
.borders(Borders::ALL),
|
||||
)
|
||||
.x_axis(
|
||||
Axis::default()
|
||||
@@ -263,7 +269,7 @@ fn render_scatter(f: &mut Frame, area: Rect) {
|
||||
|
||||
let chart = Chart::new(datasets)
|
||||
.block(
|
||||
Block::bordered().title(
|
||||
Block::new().borders(Borders::all()).title(
|
||||
Title::default()
|
||||
.content("Scatter chart".cyan().bold())
|
||||
.alignment(Alignment::Center),
|
||||
|
||||
@@ -230,12 +230,12 @@ fn render_indexed_colors(frame: &mut Frame, area: Rect) {
|
||||
}
|
||||
|
||||
fn title_block(title: String) -> Block<'static> {
|
||||
Block::new()
|
||||
Block::default()
|
||||
.borders(Borders::TOP)
|
||||
.title_alignment(Alignment::Center)
|
||||
.border_style(Style::new().dark_gray())
|
||||
.title_style(Style::new().reset())
|
||||
.title(title)
|
||||
.title_alignment(Alignment::Center)
|
||||
.title_style(Style::new().reset())
|
||||
}
|
||||
|
||||
fn render_indexed_grayscale(frame: &mut Frame, area: Rect) {
|
||||
|
||||
@@ -436,7 +436,7 @@ impl ConstraintBlock {
|
||||
} else {
|
||||
main_color
|
||||
};
|
||||
Block::new()
|
||||
Block::default()
|
||||
.fg(Self::TEXT_COLOR)
|
||||
.bg(selected_color)
|
||||
.render(area, buf);
|
||||
|
||||
@@ -19,7 +19,7 @@ use std::io::{self, stdout};
|
||||
|
||||
use color_eyre::{config::HookBuilder, Result};
|
||||
use crossterm::{
|
||||
event::{self, Event, KeyCode, KeyEventKind},
|
||||
event::{self, Event, KeyCode},
|
||||
terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
|
||||
ExecutableCommand,
|
||||
};
|
||||
@@ -109,9 +109,6 @@ impl App {
|
||||
fn handle_events(&mut self) -> Result<()> {
|
||||
if let Event::Key(key) = event::read()? {
|
||||
use KeyCode::*;
|
||||
if key.kind != KeyEventKind::Press {
|
||||
return Ok(());
|
||||
}
|
||||
match key.code {
|
||||
Char('q') | Esc => self.quit(),
|
||||
Char('l') | Right => self.next(),
|
||||
@@ -197,7 +194,7 @@ impl App {
|
||||
);
|
||||
Paragraph::new(width_bar.dark_gray())
|
||||
.centered()
|
||||
.block(Block::new().padding(Padding {
|
||||
.block(Block::default().padding(Padding {
|
||||
left: 0,
|
||||
right: 0,
|
||||
top: 1,
|
||||
|
||||
@@ -14,7 +14,7 @@ pub fn draw(f: &mut Frame, app: &mut App) {
|
||||
.iter()
|
||||
.map(|t| text::Line::from(Span::styled(*t, Style::default().fg(Color::Green))))
|
||||
.collect::<Tabs>()
|
||||
.block(Block::bordered().title(app.title))
|
||||
.block(Block::default().borders(Borders::ALL).title(app.title))
|
||||
.highlight_style(Style::default().fg(Color::Yellow))
|
||||
.select(app.tabs.index);
|
||||
f.render_widget(tabs, chunks[0]);
|
||||
@@ -46,12 +46,12 @@ fn draw_gauges(f: &mut Frame, app: &mut App, area: Rect) {
|
||||
])
|
||||
.margin(1)
|
||||
.split(area);
|
||||
let block = Block::bordered().title("Graphs");
|
||||
let block = Block::default().borders(Borders::ALL).title("Graphs");
|
||||
f.render_widget(block, area);
|
||||
|
||||
let label = format!("{:.2}%", app.progress * 100.0);
|
||||
let gauge = Gauge::default()
|
||||
.block(Block::new().title("Gauge:"))
|
||||
.block(Block::default().title("Gauge:"))
|
||||
.gauge_style(
|
||||
Style::default()
|
||||
.fg(Color::Magenta)
|
||||
@@ -64,7 +64,7 @@ fn draw_gauges(f: &mut Frame, app: &mut App, area: Rect) {
|
||||
f.render_widget(gauge, chunks[0]);
|
||||
|
||||
let sparkline = Sparkline::default()
|
||||
.block(Block::new().title("Sparkline:"))
|
||||
.block(Block::default().title("Sparkline:"))
|
||||
.style(Style::default().fg(Color::Green))
|
||||
.data(&app.sparkline.points)
|
||||
.bar_set(if app.enhanced_graphics {
|
||||
@@ -75,7 +75,7 @@ fn draw_gauges(f: &mut Frame, app: &mut App, area: Rect) {
|
||||
f.render_widget(sparkline, chunks[1]);
|
||||
|
||||
let line_gauge = LineGauge::default()
|
||||
.block(Block::new().title("LineGauge:"))
|
||||
.block(Block::default().title("LineGauge:"))
|
||||
.gauge_style(Style::default().fg(Color::Magenta))
|
||||
.line_set(if app.enhanced_graphics {
|
||||
symbols::line::THICK
|
||||
@@ -110,7 +110,7 @@ fn draw_charts(f: &mut Frame, app: &mut App, area: Rect) {
|
||||
.map(|i| ListItem::new(vec![text::Line::from(Span::raw(*i))]))
|
||||
.collect();
|
||||
let tasks = List::new(tasks)
|
||||
.block(Block::bordered().title("List"))
|
||||
.block(Block::default().borders(Borders::ALL).title("List"))
|
||||
.highlight_style(Style::default().add_modifier(Modifier::BOLD))
|
||||
.highlight_symbol("> ");
|
||||
f.render_stateful_widget(tasks, chunks[0], &mut app.tasks.state);
|
||||
@@ -138,12 +138,12 @@ fn draw_charts(f: &mut Frame, app: &mut App, area: Rect) {
|
||||
ListItem::new(content)
|
||||
})
|
||||
.collect();
|
||||
let logs = List::new(logs).block(Block::bordered().title("List"));
|
||||
let logs = List::new(logs).block(Block::default().borders(Borders::ALL).title("List"));
|
||||
f.render_stateful_widget(logs, chunks[1], &mut app.logs.state);
|
||||
}
|
||||
|
||||
let barchart = BarChart::default()
|
||||
.block(Block::bordered().title("Bar chart"))
|
||||
.block(Block::default().borders(Borders::ALL).title("Bar chart"))
|
||||
.data(&app.barchart)
|
||||
.bar_width(3)
|
||||
.bar_gap(2)
|
||||
@@ -195,12 +195,14 @@ fn draw_charts(f: &mut Frame, app: &mut App, area: Rect) {
|
||||
];
|
||||
let chart = Chart::new(datasets)
|
||||
.block(
|
||||
Block::bordered().title(Span::styled(
|
||||
"Chart",
|
||||
Style::default()
|
||||
.fg(Color::Cyan)
|
||||
.add_modifier(Modifier::BOLD),
|
||||
)),
|
||||
Block::default()
|
||||
.title(Span::styled(
|
||||
"Chart",
|
||||
Style::default()
|
||||
.fg(Color::Cyan)
|
||||
.add_modifier(Modifier::BOLD),
|
||||
))
|
||||
.borders(Borders::ALL),
|
||||
)
|
||||
.x_axis(
|
||||
Axis::default()
|
||||
@@ -252,7 +254,7 @@ fn draw_text(f: &mut Frame, area: Rect) {
|
||||
"One more thing is that it should display unicode characters: 10€"
|
||||
),
|
||||
];
|
||||
let block = Block::bordered().title(Span::styled(
|
||||
let block = Block::default().borders(Borders::ALL).title(Span::styled(
|
||||
"Footer",
|
||||
Style::default()
|
||||
.fg(Color::Magenta)
|
||||
@@ -290,11 +292,11 @@ fn draw_second_tab(f: &mut Frame, app: &mut App, area: Rect) {
|
||||
.style(Style::default().fg(Color::Yellow))
|
||||
.bottom_margin(1),
|
||||
)
|
||||
.block(Block::bordered().title("Servers"));
|
||||
.block(Block::default().title("Servers").borders(Borders::ALL));
|
||||
f.render_widget(table, chunks[0]);
|
||||
|
||||
let map = Canvas::default()
|
||||
.block(Block::bordered().title("World"))
|
||||
.block(Block::default().title("World").borders(Borders::ALL))
|
||||
.paint(|ctx| {
|
||||
ctx.draw(&Map {
|
||||
color: Color::White,
|
||||
@@ -388,6 +390,6 @@ fn draw_third_tab(f: &mut Frame, _app: &mut App, area: Rect) {
|
||||
Constraint::Ratio(1, 3),
|
||||
],
|
||||
)
|
||||
.block(Block::bordered().title("Colors"));
|
||||
.block(Block::default().title("Colors").borders(Borders::ALL));
|
||||
f.render_widget(table, chunks[0]);
|
||||
}
|
||||
|
||||
@@ -38,10 +38,14 @@ enum Tab {
|
||||
}
|
||||
|
||||
pub fn run(terminal: &mut Terminal<impl Backend>) -> Result<()> {
|
||||
App::default().run(terminal)
|
||||
App::new().run(terminal)
|
||||
}
|
||||
|
||||
impl App {
|
||||
pub fn new() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
|
||||
/// Run the app until the user quits.
|
||||
pub fn run(&mut self, terminal: &mut Terminal<impl Backend>) -> Result<()> {
|
||||
while self.is_running() {
|
||||
|
||||
@@ -39,7 +39,7 @@ pub use theme::*;
|
||||
fn main() -> Result<()> {
|
||||
errors::init_hooks()?;
|
||||
let terminal = &mut term::init()?;
|
||||
App::default().run(terminal)?;
|
||||
App::new().run(terminal)?;
|
||||
term::restore()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -49,10 +49,10 @@ fn render_hops(selected_row: usize, area: Rect, buf: &mut Buffer) {
|
||||
.iter()
|
||||
.map(|hop| Row::new(vec![hop.host, hop.address]))
|
||||
.collect_vec();
|
||||
let block = Block::new()
|
||||
.padding(Padding::new(1, 1, 1, 1))
|
||||
let block = Block::default()
|
||||
.title("Traceroute bad.horse".bold().white())
|
||||
.title_alignment(Alignment::Center)
|
||||
.title("Traceroute bad.horse".bold().white());
|
||||
.padding(Padding::new(1, 1, 1, 1));
|
||||
StatefulWidget::render(
|
||||
Table::new(rows, [Constraint::Max(100), Constraint::Length(15)])
|
||||
.header(Row::new(vec!["Host", "Address"]).set_style(THEME.traceroute.header))
|
||||
|
||||
@@ -51,7 +51,8 @@ fn main() -> io::Result<()> {
|
||||
|
||||
fn hello_world(frame: &mut Frame) {
|
||||
frame.render_widget(
|
||||
Paragraph::new("Hello World!").block(Block::bordered().title("Greeting")),
|
||||
Paragraph::new("Hello World!")
|
||||
.block(Block::default().title("Greeting").borders(Borders::ALL)),
|
||||
frame.size(),
|
||||
);
|
||||
}
|
||||
@@ -86,8 +87,8 @@ fn layout(frame: &mut Frame) {
|
||||
Block::new().borders(Borders::TOP).title("Status Bar"),
|
||||
status_bar,
|
||||
);
|
||||
frame.render_widget(Block::bordered().title("Left"), left);
|
||||
frame.render_widget(Block::bordered().title("Right"), right);
|
||||
frame.render_widget(Block::default().borders(Borders::ALL).title("Left"), left);
|
||||
frame.render_widget(Block::default().borders(Borders::ALL).title("Right"), right);
|
||||
}
|
||||
|
||||
fn styling(frame: &mut Frame) {
|
||||
|
||||
@@ -206,11 +206,11 @@ impl App {
|
||||
|
||||
fn title_block(title: &str) -> Block {
|
||||
let title = Title::from(title).alignment(Alignment::Center);
|
||||
Block::new()
|
||||
.borders(Borders::NONE)
|
||||
.padding(Padding::vertical(1))
|
||||
Block::default()
|
||||
.title(title)
|
||||
.borders(Borders::NONE)
|
||||
.fg(CUSTOM_LABEL_COLOR)
|
||||
.padding(Padding::vertical(1))
|
||||
}
|
||||
|
||||
fn init_error_hooks() -> color_eyre::Result<()> {
|
||||
|
||||
@@ -236,7 +236,7 @@ fn run_app<B: Backend>(
|
||||
fn ui(f: &mut Frame, downloads: &Downloads) {
|
||||
let area = f.size();
|
||||
|
||||
let block = Block::new().title(block::Title::from("Progress").alignment(Alignment::Center));
|
||||
let block = Block::default().title(block::Title::from("Progress").alignment(Alignment::Center));
|
||||
f.render_widget(block, area);
|
||||
|
||||
let vertical = Layout::vertical([Constraint::Length(2), Constraint::Length(4)]).margin(1);
|
||||
|
||||
@@ -26,7 +26,7 @@ use itertools::Itertools;
|
||||
use ratatui::{
|
||||
layout::Constraint::*,
|
||||
prelude::*,
|
||||
widgets::{Block, Paragraph},
|
||||
widgets::{Block, Borders, Paragraph},
|
||||
};
|
||||
|
||||
fn main() -> Result<(), Box<dyn Error>> {
|
||||
@@ -190,9 +190,10 @@ fn render_example_combination(
|
||||
title: &str,
|
||||
constraints: Vec<(Constraint, Constraint)>,
|
||||
) {
|
||||
let block = Block::bordered()
|
||||
let block = Block::default()
|
||||
.title(title.gray())
|
||||
.style(Style::reset())
|
||||
.borders(Borders::ALL)
|
||||
.border_style(Style::default().fg(Color::DarkGray));
|
||||
let inner = block.inner(area);
|
||||
frame.render_widget(block, area);
|
||||
|
||||
@@ -189,13 +189,13 @@ impl Widget for &mut App<'_> {
|
||||
impl App<'_> {
|
||||
fn render_todo(&mut self, area: Rect, buf: &mut Buffer) {
|
||||
// We create two blocks, one is for the header (outer) and the other is for list (inner).
|
||||
let outer_block = Block::new()
|
||||
let outer_block = Block::default()
|
||||
.borders(Borders::NONE)
|
||||
.title_alignment(Alignment::Center)
|
||||
.title("TODO List")
|
||||
.fg(TEXT_COLOR)
|
||||
.bg(TODO_HEADER_BG);
|
||||
let inner_block = Block::new()
|
||||
.bg(TODO_HEADER_BG)
|
||||
.title("TODO List")
|
||||
.title_alignment(Alignment::Center);
|
||||
let inner_block = Block::default()
|
||||
.borders(Borders::NONE)
|
||||
.fg(TEXT_COLOR)
|
||||
.bg(NORMAL_ROW_COLOR);
|
||||
@@ -246,16 +246,16 @@ impl App<'_> {
|
||||
};
|
||||
|
||||
// We show the list item's info under the list in this paragraph
|
||||
let outer_info_block = Block::new()
|
||||
let outer_info_block = Block::default()
|
||||
.borders(Borders::NONE)
|
||||
.title_alignment(Alignment::Center)
|
||||
.title("TODO Info")
|
||||
.fg(TEXT_COLOR)
|
||||
.bg(TODO_HEADER_BG);
|
||||
let inner_info_block = Block::new()
|
||||
.bg(TODO_HEADER_BG)
|
||||
.title("TODO Info")
|
||||
.title_alignment(Alignment::Center);
|
||||
let inner_info_block = Block::default()
|
||||
.borders(Borders::NONE)
|
||||
.padding(Padding::horizontal(1))
|
||||
.bg(NORMAL_ROW_COLOR);
|
||||
.bg(NORMAL_ROW_COLOR)
|
||||
.padding(Padding::horizontal(1));
|
||||
|
||||
// This is a similar process to what we did for list. outer_info_area will be used for
|
||||
// header inner_info_area will be used for the list info.
|
||||
|
||||
@@ -37,7 +37,7 @@ use crossterm::{
|
||||
};
|
||||
use ratatui::{
|
||||
prelude::*,
|
||||
widgets::{Block, Paragraph},
|
||||
widgets::{Block, Borders, Paragraph},
|
||||
};
|
||||
|
||||
type Result<T> = std::result::Result<T, Box<dyn Error>>;
|
||||
@@ -142,9 +142,11 @@ fn ui(f: &mut Frame, app: &App) {
|
||||
Line::from("try first without the panic handler to see the difference"),
|
||||
];
|
||||
|
||||
let paragraph = Paragraph::new(text)
|
||||
.block(Block::bordered().title("Panic Handler Demo"))
|
||||
.centered();
|
||||
let b = Block::default()
|
||||
.title("Panic Handler Demo")
|
||||
.borders(Borders::ALL);
|
||||
|
||||
f.render_widget(paragraph, f.size());
|
||||
let p = Paragraph::new(text).block(b).centered();
|
||||
|
||||
f.render_widget(p, f.size());
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ use crossterm::{
|
||||
};
|
||||
use ratatui::{
|
||||
prelude::*,
|
||||
widgets::{Block, Paragraph, Wrap},
|
||||
widgets::{Block, Borders, Paragraph, Wrap},
|
||||
};
|
||||
|
||||
struct App {
|
||||
@@ -105,7 +105,7 @@ fn ui(f: &mut Frame, app: &App) {
|
||||
let mut long_line = s.repeat(usize::from(size.width) / s.len() + 4);
|
||||
long_line.push('\n');
|
||||
|
||||
let block = Block::new().black();
|
||||
let block = Block::default().black();
|
||||
f.render_widget(block, size);
|
||||
|
||||
let layout = Layout::vertical([Constraint::Ratio(1, 4); 4]).split(size);
|
||||
@@ -127,7 +127,8 @@ fn ui(f: &mut Frame, app: &App) {
|
||||
];
|
||||
|
||||
let create_block = |title| {
|
||||
Block::bordered()
|
||||
Block::default()
|
||||
.borders(Borders::ALL)
|
||||
.style(Style::default().fg(Color::Gray))
|
||||
.title(Span::styled(
|
||||
title,
|
||||
|
||||
@@ -25,7 +25,7 @@ use crossterm::{
|
||||
};
|
||||
use ratatui::{
|
||||
prelude::*,
|
||||
widgets::{Block, Clear, Paragraph, Wrap},
|
||||
widgets::{Block, Borders, Clear, Paragraph, Wrap},
|
||||
};
|
||||
|
||||
struct App {
|
||||
@@ -98,11 +98,14 @@ fn ui(f: &mut Frame, app: &App) {
|
||||
.wrap(Wrap { trim: true });
|
||||
f.render_widget(paragraph, instructions);
|
||||
|
||||
let block = Block::bordered().title("Content").on_blue();
|
||||
let block = Block::default()
|
||||
.title("Content")
|
||||
.borders(Borders::ALL)
|
||||
.on_blue();
|
||||
f.render_widget(block, content);
|
||||
|
||||
if app.show_popup {
|
||||
let block = Block::bordered().title("Popup");
|
||||
let block = Block::default().title("Popup").borders(Borders::ALL);
|
||||
let area = centered_rect(60, 20, area);
|
||||
f.render_widget(Clear, area); //this clears out the background
|
||||
f.render_widget(block, area);
|
||||
|
||||
@@ -151,18 +151,18 @@ fn ui(f: &mut Frame, app: &App) {
|
||||
.split(f.size());
|
||||
let sparkline = Sparkline::default()
|
||||
.block(
|
||||
Block::new()
|
||||
.borders(Borders::LEFT | Borders::RIGHT)
|
||||
.title("Data1"),
|
||||
Block::default()
|
||||
.title("Data1")
|
||||
.borders(Borders::LEFT | Borders::RIGHT),
|
||||
)
|
||||
.data(&app.data1)
|
||||
.style(Style::default().fg(Color::Yellow));
|
||||
f.render_widget(sparkline, chunks[0]);
|
||||
let sparkline = Sparkline::default()
|
||||
.block(
|
||||
Block::new()
|
||||
.borders(Borders::LEFT | Borders::RIGHT)
|
||||
.title("Data2"),
|
||||
Block::default()
|
||||
.title("Data2")
|
||||
.borders(Borders::LEFT | Borders::RIGHT),
|
||||
)
|
||||
.data(&app.data2)
|
||||
.style(Style::default().bg(Color::Green));
|
||||
@@ -170,9 +170,9 @@ fn ui(f: &mut Frame, app: &App) {
|
||||
// Multiline
|
||||
let sparkline = Sparkline::default()
|
||||
.block(
|
||||
Block::new()
|
||||
.borders(Borders::LEFT | Borders::RIGHT)
|
||||
.title("Data3"),
|
||||
Block::default()
|
||||
.title("Data3")
|
||||
.borders(Borders::LEFT | Borders::RIGHT),
|
||||
)
|
||||
.data(&app.data3)
|
||||
.style(Style::default().fg(Color::Red));
|
||||
|
||||
@@ -331,9 +331,10 @@ fn render_footer(f: &mut Frame, app: &App, area: Rect) {
|
||||
.style(Style::new().fg(app.colors.row_fg).bg(app.colors.buffer_bg))
|
||||
.centered()
|
||||
.block(
|
||||
Block::bordered()
|
||||
.border_type(BorderType::Double)
|
||||
.border_style(Style::new().fg(app.colors.footer_border_color)),
|
||||
Block::default()
|
||||
.borders(Borders::ALL)
|
||||
.border_style(Style::new().fg(app.colors.footer_border_color))
|
||||
.border_type(BorderType::Double),
|
||||
);
|
||||
f.render_widget(info_footer, area);
|
||||
}
|
||||
|
||||
@@ -205,7 +205,8 @@ impl SelectedTab {
|
||||
|
||||
/// A block surrounding the tab's content
|
||||
fn block(self) -> Block<'static> {
|
||||
Block::bordered()
|
||||
Block::default()
|
||||
.borders(Borders::ALL)
|
||||
.border_set(symbols::border::PROPORTIONAL_TALL)
|
||||
.padding(Padding::horizontal(1))
|
||||
.border_style(self.palette().c700)
|
||||
|
||||
@@ -36,7 +36,7 @@ use crossterm::{
|
||||
};
|
||||
use ratatui::{
|
||||
prelude::*,
|
||||
widgets::{Block, List, ListItem, Paragraph},
|
||||
widgets::{Block, Borders, List, ListItem, Paragraph},
|
||||
};
|
||||
|
||||
enum InputMode {
|
||||
@@ -49,7 +49,7 @@ struct App {
|
||||
/// Current value of the input box
|
||||
input: String,
|
||||
/// Position of cursor in the editor area.
|
||||
character_index: usize,
|
||||
cursor_position: usize,
|
||||
/// Current input mode
|
||||
input_mode: InputMode,
|
||||
/// History of recorded messages
|
||||
@@ -62,46 +62,34 @@ impl App {
|
||||
input: String::new(),
|
||||
input_mode: InputMode::Normal,
|
||||
messages: Vec::new(),
|
||||
character_index: 0,
|
||||
cursor_position: 0,
|
||||
}
|
||||
}
|
||||
|
||||
fn move_cursor_left(&mut self) {
|
||||
let cursor_moved_left = self.character_index.saturating_sub(1);
|
||||
self.character_index = self.clamp_cursor(cursor_moved_left);
|
||||
let cursor_moved_left = self.cursor_position.saturating_sub(1);
|
||||
self.cursor_position = self.clamp_cursor(cursor_moved_left);
|
||||
}
|
||||
|
||||
fn move_cursor_right(&mut self) {
|
||||
let cursor_moved_right = self.character_index.saturating_add(1);
|
||||
self.character_index = self.clamp_cursor(cursor_moved_right);
|
||||
let cursor_moved_right = self.cursor_position.saturating_add(1);
|
||||
self.cursor_position = self.clamp_cursor(cursor_moved_right);
|
||||
}
|
||||
|
||||
fn enter_char(&mut self, new_char: char) {
|
||||
let index = self.byte_index();
|
||||
self.input.insert(index, new_char);
|
||||
self.input.insert(self.cursor_position, new_char);
|
||||
|
||||
self.move_cursor_right();
|
||||
}
|
||||
|
||||
/// Returns the byte index based on the character position.
|
||||
///
|
||||
/// Since each character in a string can be contain multiple bytes, it's necessary to calculate
|
||||
/// the byte index based on the index of the character.
|
||||
fn byte_index(&mut self) -> usize {
|
||||
self.input
|
||||
.char_indices()
|
||||
.map(|(i, _)| i)
|
||||
.nth(self.character_index)
|
||||
.unwrap_or(self.input.len())
|
||||
}
|
||||
|
||||
fn delete_char(&mut self) {
|
||||
let is_not_cursor_leftmost = self.character_index != 0;
|
||||
let is_not_cursor_leftmost = self.cursor_position != 0;
|
||||
if is_not_cursor_leftmost {
|
||||
// Method "remove" is not used on the saved text for deleting the selected char.
|
||||
// Reason: Using remove on String works on bytes instead of the chars.
|
||||
// Using remove would require special care because of char boundaries.
|
||||
|
||||
let current_index = self.character_index;
|
||||
let current_index = self.cursor_position;
|
||||
let from_left_to_current_index = current_index - 1;
|
||||
|
||||
// Getting all characters before the selected character.
|
||||
@@ -117,11 +105,11 @@ impl App {
|
||||
}
|
||||
|
||||
fn clamp_cursor(&self, new_cursor_pos: usize) -> usize {
|
||||
new_cursor_pos.clamp(0, self.input.chars().count())
|
||||
new_cursor_pos.clamp(0, self.input.len())
|
||||
}
|
||||
|
||||
fn reset_cursor(&mut self) {
|
||||
self.character_index = 0;
|
||||
self.cursor_position = 0;
|
||||
}
|
||||
|
||||
fn submit_message(&mut self) {
|
||||
@@ -238,7 +226,7 @@ fn ui(f: &mut Frame, app: &App) {
|
||||
InputMode::Normal => Style::default(),
|
||||
InputMode::Editing => Style::default().fg(Color::Yellow),
|
||||
})
|
||||
.block(Block::bordered().title("Input"));
|
||||
.block(Block::default().borders(Borders::ALL).title("Input"));
|
||||
f.render_widget(input, input_area);
|
||||
match app.input_mode {
|
||||
InputMode::Normal =>
|
||||
@@ -252,7 +240,7 @@ fn ui(f: &mut Frame, app: &App) {
|
||||
f.set_cursor(
|
||||
// Draw the cursor at the current position in the input field.
|
||||
// This position is can be controlled via the left and right arrow key
|
||||
input_area.x + app.character_index as u16 + 1,
|
||||
input_area.x + app.cursor_position as u16 + 1,
|
||||
// Move one line down, from the border to the input line
|
||||
input_area.y + 1,
|
||||
);
|
||||
@@ -268,6 +256,7 @@ fn ui(f: &mut Frame, app: &App) {
|
||||
ListItem::new(content)
|
||||
})
|
||||
.collect();
|
||||
let messages = List::new(messages).block(Block::bordered().title("Messages"));
|
||||
let messages =
|
||||
List::new(messages).block(Block::default().borders(Borders::ALL).title("Messages"));
|
||||
f.render_widget(messages, messages_area);
|
||||
}
|
||||
|
||||
@@ -10,8 +10,8 @@ use crossterm::{
|
||||
cursor::{Hide, MoveTo, Show},
|
||||
execute, queue,
|
||||
style::{
|
||||
Attribute as CAttribute, Attributes as CAttributes, Color as CColor, Colors, ContentStyle,
|
||||
Print, SetAttribute, SetBackgroundColor, SetColors, SetForegroundColor,
|
||||
Attribute as CAttribute, Attributes as CAttributes, Color as CColor, ContentStyle, Print,
|
||||
SetAttribute, SetBackgroundColor, SetForegroundColor,
|
||||
},
|
||||
terminal::{self, Clear},
|
||||
};
|
||||
@@ -145,12 +145,14 @@ where
|
||||
diff.queue(&mut self.writer)?;
|
||||
modifier = cell.modifier;
|
||||
}
|
||||
if cell.fg != fg || cell.bg != bg {
|
||||
queue!(
|
||||
self.writer,
|
||||
SetColors(Colors::new(cell.fg.into(), cell.bg.into()))
|
||||
)?;
|
||||
if cell.fg != fg {
|
||||
let color = CColor::from(cell.fg);
|
||||
queue!(self.writer, SetForegroundColor(color))?;
|
||||
fg = cell.fg;
|
||||
}
|
||||
if cell.bg != bg {
|
||||
let color = CColor::from(cell.bg);
|
||||
queue!(self.writer, SetBackgroundColor(color))?;
|
||||
bg = cell.bg;
|
||||
}
|
||||
#[cfg(feature = "underline-color")]
|
||||
@@ -226,7 +228,7 @@ where
|
||||
Ok(Rect::new(0, 0, width, height))
|
||||
}
|
||||
|
||||
fn window_size(&mut self) -> io::Result<WindowSize> {
|
||||
fn window_size(&mut self) -> Result<WindowSize, io::Error> {
|
||||
let crossterm::terminal::WindowSize {
|
||||
columns,
|
||||
rows,
|
||||
|
||||
@@ -198,7 +198,7 @@ where
|
||||
Ok(Rect::new(0, 0, terminal.0, terminal.1))
|
||||
}
|
||||
|
||||
fn window_size(&mut self) -> io::Result<WindowSize> {
|
||||
fn window_size(&mut self) -> Result<WindowSize, io::Error> {
|
||||
Ok(WindowSize {
|
||||
columns_rows: termion::terminal_size()?.into(),
|
||||
pixels: termion::terminal_size_pixels()?.into(),
|
||||
|
||||
@@ -111,7 +111,7 @@ impl TermwizBackend {
|
||||
}
|
||||
|
||||
impl Backend for TermwizBackend {
|
||||
fn draw<'a, I>(&mut self, content: I) -> io::Result<()>
|
||||
fn draw<'a, I>(&mut self, content: I) -> Result<(), io::Error>
|
||||
where
|
||||
I: Iterator<Item = (u16, u16, &'a Cell)>,
|
||||
{
|
||||
@@ -181,13 +181,13 @@ impl Backend for TermwizBackend {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn hide_cursor(&mut self) -> io::Result<()> {
|
||||
fn hide_cursor(&mut self) -> Result<(), io::Error> {
|
||||
self.buffered_terminal
|
||||
.add_change(Change::CursorVisibility(CursorVisibility::Hidden));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn show_cursor(&mut self) -> io::Result<()> {
|
||||
fn show_cursor(&mut self) -> Result<(), io::Error> {
|
||||
self.buffered_terminal
|
||||
.add_change(Change::CursorVisibility(CursorVisibility::Visible));
|
||||
Ok(())
|
||||
@@ -207,18 +207,18 @@ impl Backend for TermwizBackend {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn clear(&mut self) -> io::Result<()> {
|
||||
fn clear(&mut self) -> Result<(), io::Error> {
|
||||
self.buffered_terminal
|
||||
.add_change(Change::ClearScreen(termwiz::color::ColorAttribute::Default));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn size(&self) -> io::Result<Rect> {
|
||||
fn size(&self) -> Result<Rect, io::Error> {
|
||||
let (cols, rows) = self.buffered_terminal.dimensions();
|
||||
Ok(Rect::new(0, 0, u16_max(cols), u16_max(rows)))
|
||||
}
|
||||
|
||||
fn window_size(&mut self) -> io::Result<WindowSize> {
|
||||
fn window_size(&mut self) -> Result<WindowSize, io::Error> {
|
||||
let ScreenSize {
|
||||
cols,
|
||||
rows,
|
||||
@@ -241,7 +241,7 @@ impl Backend for TermwizBackend {
|
||||
})
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
fn flush(&mut self) -> Result<(), io::Error> {
|
||||
self.buffered_terminal
|
||||
.flush()
|
||||
.map_err(|e| io::Error::new(io::ErrorKind::Other, e))?;
|
||||
@@ -271,7 +271,7 @@ impl From<CellAttributes> for Style {
|
||||
|
||||
style.fg = Some(value.foreground().into());
|
||||
style.bg = Some(value.background().into());
|
||||
#[cfg(feature = "underline-color")]
|
||||
#[cfg(feature = "underline_color")]
|
||||
{
|
||||
style.underline_color = Some(value.underline_color().into());
|
||||
}
|
||||
@@ -600,7 +600,7 @@ mod tests {
|
||||
Style::new().fg(Color::Reset).bg(Color::Indexed(31))
|
||||
);
|
||||
// underline color
|
||||
#[cfg(feature = "underline-color")]
|
||||
#[cfg(feature = "underline_color")]
|
||||
assert_eq!(
|
||||
Style::from(
|
||||
CellAttributes::default()
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
//! It is used in the integration tests to verify the correctness of the library.
|
||||
|
||||
use std::{
|
||||
fmt::{self, Write},
|
||||
fmt::{Display, Write},
|
||||
io,
|
||||
};
|
||||
|
||||
@@ -105,16 +105,16 @@ impl TestBackend {
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for TestBackend {
|
||||
impl Display for TestBackend {
|
||||
/// Formats the `TestBackend` for display by calling the `buffer_view` function
|
||||
/// on its internal buffer.
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{}", buffer_view(&self.buffer))
|
||||
}
|
||||
}
|
||||
|
||||
impl Backend for TestBackend {
|
||||
fn draw<'a, I>(&mut self, content: I) -> io::Result<()>
|
||||
fn draw<'a, I>(&mut self, content: I) -> Result<(), io::Error>
|
||||
where
|
||||
I: Iterator<Item = (u16, u16, &'a Cell)>,
|
||||
{
|
||||
@@ -125,26 +125,26 @@ impl Backend for TestBackend {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn hide_cursor(&mut self) -> io::Result<()> {
|
||||
fn hide_cursor(&mut self) -> Result<(), io::Error> {
|
||||
self.cursor = false;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn show_cursor(&mut self) -> io::Result<()> {
|
||||
fn show_cursor(&mut self) -> Result<(), io::Error> {
|
||||
self.cursor = true;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn get_cursor(&mut self) -> io::Result<(u16, u16)> {
|
||||
fn get_cursor(&mut self) -> Result<(u16, u16), io::Error> {
|
||||
Ok(self.pos)
|
||||
}
|
||||
|
||||
fn set_cursor(&mut self, x: u16, y: u16) -> io::Result<()> {
|
||||
fn set_cursor(&mut self, x: u16, y: u16) -> Result<(), io::Error> {
|
||||
self.pos = (x, y);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn clear(&mut self) -> io::Result<()> {
|
||||
fn clear(&mut self) -> Result<(), io::Error> {
|
||||
self.buffer.reset();
|
||||
Ok(())
|
||||
}
|
||||
@@ -214,11 +214,11 @@ impl Backend for TestBackend {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn size(&self) -> io::Result<Rect> {
|
||||
fn size(&self) -> Result<Rect, io::Error> {
|
||||
Ok(Rect::new(0, 0, self.width, self.height))
|
||||
}
|
||||
|
||||
fn window_size(&mut self) -> io::Result<WindowSize> {
|
||||
fn window_size(&mut self) -> Result<WindowSize, io::Error> {
|
||||
// Some arbitrary window pixel size, probably doesn't need much testing.
|
||||
static WINDOW_PIXEL_SIZE: Size = Size {
|
||||
width: 640,
|
||||
@@ -230,7 +230,7 @@ impl Backend for TestBackend {
|
||||
})
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
fn flush(&mut self) -> Result<(), io::Error> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
use std::fmt;
|
||||
use std::{
|
||||
cmp::min,
|
||||
fmt::{Debug, Formatter, Result},
|
||||
};
|
||||
|
||||
use unicode_segmentation::UnicodeSegmentation;
|
||||
use unicode_width::UnicodeWidthStr;
|
||||
@@ -52,21 +55,22 @@ pub struct Buffer {
|
||||
|
||||
impl Buffer {
|
||||
/// Returns a Buffer with all cells set to the default one
|
||||
#[must_use]
|
||||
pub fn empty(area: Rect) -> Self {
|
||||
Self::filled(area, &Cell::default())
|
||||
let cell = Cell::default();
|
||||
Self::filled(area, &cell)
|
||||
}
|
||||
|
||||
/// Returns a Buffer with all cells initialized with the attributes of the given Cell
|
||||
#[must_use]
|
||||
pub fn filled(area: Rect, cell: &Cell) -> Self {
|
||||
let size = area.area() as usize;
|
||||
let content = vec![cell.clone(); size];
|
||||
let mut content = Vec::with_capacity(size);
|
||||
for _ in 0..size {
|
||||
content.push(cell.clone());
|
||||
}
|
||||
Self { area, content }
|
||||
}
|
||||
|
||||
/// Returns a Buffer containing the given lines
|
||||
#[must_use]
|
||||
pub fn with_lines<'a, Iter>(lines: Iter) -> Self
|
||||
where
|
||||
Iter: IntoIterator,
|
||||
@@ -93,14 +97,12 @@ impl Buffer {
|
||||
}
|
||||
|
||||
/// Returns a reference to Cell at the given coordinates
|
||||
#[track_caller]
|
||||
pub fn get(&self, x: u16, y: u16) -> &Cell {
|
||||
let i = self.index_of(x, y);
|
||||
&self.content[i]
|
||||
}
|
||||
|
||||
/// Returns a mutable reference to Cell at the given coordinates
|
||||
#[track_caller]
|
||||
pub fn get_mut(&mut self, x: u16, y: u16) -> &mut Cell {
|
||||
let i = self.index_of(x, y);
|
||||
&mut self.content[i]
|
||||
@@ -132,7 +134,6 @@ impl Buffer {
|
||||
/// // starts at (200, 100).
|
||||
/// buffer.index_of(0, 0); // Panics
|
||||
/// ```
|
||||
#[track_caller]
|
||||
pub fn index_of(&self, x: u16, y: u16) -> usize {
|
||||
debug_assert!(
|
||||
x >= self.area.left()
|
||||
@@ -183,56 +184,65 @@ impl Buffer {
|
||||
}
|
||||
|
||||
/// Print a string, starting at the position (x, y)
|
||||
///
|
||||
/// `style` accepts any type that is convertible to [`Style`] (e.g. [`Style`], [`Color`], or
|
||||
/// your own type that implements [`Into<Style>`]).
|
||||
pub fn set_string<T, S>(&mut self, x: u16, y: u16, string: T, style: S)
|
||||
where
|
||||
T: AsRef<str>,
|
||||
S: Into<Style>,
|
||||
{
|
||||
self.set_stringn(x, y, string, usize::MAX, style);
|
||||
self.set_stringn(x, y, string, usize::MAX, style.into());
|
||||
}
|
||||
|
||||
/// Print at most the first n characters of a string if enough space is available
|
||||
/// until the end of the line.
|
||||
/// until the end of the line
|
||||
///
|
||||
/// Use [`Buffer::set_string`] when the maximum amount of characters can be printed.
|
||||
/// `style` accepts any type that is convertible to [`Style`] (e.g. [`Style`], [`Color`], or
|
||||
/// your own type that implements [`Into<Style>`]).
|
||||
pub fn set_stringn<T, S>(
|
||||
&mut self,
|
||||
mut x: u16,
|
||||
x: u16,
|
||||
y: u16,
|
||||
string: T,
|
||||
max_width: usize,
|
||||
width: usize,
|
||||
style: S,
|
||||
) -> (u16, u16)
|
||||
where
|
||||
T: AsRef<str>,
|
||||
S: Into<Style>,
|
||||
{
|
||||
let max_width = max_width.try_into().unwrap_or(u16::MAX);
|
||||
let mut remaining_width = self.area.right().saturating_sub(x).min(max_width);
|
||||
let graphemes = UnicodeSegmentation::graphemes(string.as_ref(), true)
|
||||
.map(|symbol| (symbol, symbol.width() as u16))
|
||||
.filter(|(_symbol, width)| *width > 0)
|
||||
.map_while(|(symbol, width)| {
|
||||
remaining_width = remaining_width.checked_sub(width)?;
|
||||
Some((symbol, width))
|
||||
});
|
||||
let style = style.into();
|
||||
for (symbol, width) in graphemes {
|
||||
self.get_mut(x, y).set_symbol(symbol).set_style(style);
|
||||
let next_symbol = x + width;
|
||||
x += 1;
|
||||
// Reset following cells if multi-width (they would be hidden by the grapheme),
|
||||
while x < next_symbol {
|
||||
self.get_mut(x, y).reset();
|
||||
x += 1;
|
||||
let mut index = self.index_of(x, y);
|
||||
let mut x_offset = x as usize;
|
||||
let graphemes = UnicodeSegmentation::graphemes(string.as_ref(), true);
|
||||
let max_offset = min(self.area.right() as usize, width.saturating_add(x as usize));
|
||||
for s in graphemes {
|
||||
let width = s.width();
|
||||
if width == 0 {
|
||||
continue;
|
||||
}
|
||||
// `x_offset + width > max_offset` could be integer overflow on 32-bit machines if we
|
||||
// change dimensions to usize or u32 and someone resizes the terminal to 1x2^32.
|
||||
if width > max_offset.saturating_sub(x_offset) {
|
||||
break;
|
||||
}
|
||||
|
||||
self.content[index].set_symbol(s);
|
||||
self.content[index].set_style(style);
|
||||
// Reset following cells if multi-width (they would be hidden by the grapheme),
|
||||
for i in index + 1..index + width {
|
||||
self.content[i].reset();
|
||||
}
|
||||
index += width;
|
||||
x_offset += width;
|
||||
}
|
||||
(x, y)
|
||||
(x_offset as u16, y)
|
||||
}
|
||||
|
||||
/// Print a line, starting at the position (x, y)
|
||||
pub fn set_line(&mut self, x: u16, y: u16, line: &Line<'_>, max_width: u16) -> (u16, u16) {
|
||||
let mut remaining_width = max_width;
|
||||
pub fn set_line(&mut self, x: u16, y: u16, line: &Line<'_>, width: u16) -> (u16, u16) {
|
||||
let mut remaining_width = width;
|
||||
let mut x = x;
|
||||
for span in line {
|
||||
if remaining_width == 0 {
|
||||
@@ -253,8 +263,8 @@ impl Buffer {
|
||||
}
|
||||
|
||||
/// Print a span, starting at the position (x, y)
|
||||
pub fn set_span(&mut self, x: u16, y: u16, span: &Span<'_>, max_width: u16) -> (u16, u16) {
|
||||
self.set_stringn(x, y, &span.content, max_width as usize, span.style)
|
||||
pub fn set_span(&mut self, x: u16, y: u16, span: &Span<'_>, width: u16) -> (u16, u16) {
|
||||
self.set_stringn(x, y, span.content.as_ref(), width as usize, span.style)
|
||||
}
|
||||
|
||||
/// Set the style of all cells in the given area.
|
||||
@@ -293,7 +303,8 @@ impl Buffer {
|
||||
/// Merge an other buffer into this one
|
||||
pub fn merge(&mut self, other: &Self) {
|
||||
let area = self.area.union(other.area);
|
||||
self.content.resize(area.area() as usize, Cell::default());
|
||||
let cell = Cell::default();
|
||||
self.content.resize(area.area() as usize, cell.clone());
|
||||
|
||||
// Move original content to the appropriate space
|
||||
let size = self.area.area() as usize;
|
||||
@@ -303,7 +314,7 @@ impl Buffer {
|
||||
let k = ((y - area.y) * area.width + x - area.x) as usize;
|
||||
if i != k {
|
||||
self.content[k] = self.content[i].clone();
|
||||
self.content[i] = Cell::default();
|
||||
self.content[i] = cell.clone();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -372,7 +383,7 @@ impl Buffer {
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Buffer {
|
||||
impl Debug for Buffer {
|
||||
/// Writes a debug representation of the buffer to the given formatter.
|
||||
///
|
||||
/// The format is like a pretty printed struct, with the following fields:
|
||||
@@ -380,7 +391,7 @@ impl fmt::Debug for Buffer {
|
||||
/// * `content`: displayed as a list of strings representing the content of the buffer
|
||||
/// * `styles`: displayed as a list of: `{ x: 1, y: 2, fg: Color::Red, bg: Color::Blue,
|
||||
/// modifier: Modifier::BOLD }` only showing a value when there is a change in style.
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
|
||||
f.write_fmt(format_args!(
|
||||
"Buffer {{\n area: {:?},\n content: [\n",
|
||||
&self.area
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use std::fmt;
|
||||
use std::fmt::{self, Display};
|
||||
|
||||
use itertools::Itertools;
|
||||
use strum::EnumIs;
|
||||
@@ -362,7 +362,7 @@ impl Default for Constraint {
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Constraint {
|
||||
impl Display for Constraint {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Self::Percentage(p) => write!(f, "Percentage({p})"),
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use std::fmt;
|
||||
use std::fmt::{self, Display};
|
||||
|
||||
#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash)]
|
||||
pub struct Margin {
|
||||
@@ -15,7 +15,7 @@ impl Margin {
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Margin {
|
||||
impl Display for Margin {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{}x{}", self.horizontal, self.vertical)
|
||||
}
|
||||
|
||||
@@ -40,6 +40,16 @@ pub struct Offset {
|
||||
pub y: i32,
|
||||
}
|
||||
|
||||
impl<X: Into<i32>, Y: Into<i32>> From<(X, Y)> for Offset {
|
||||
/// Creates a new `Offset` from a tuple of (x, y).
|
||||
fn from((x, y): (X, Y)) -> Self {
|
||||
Self {
|
||||
x: x.into(),
|
||||
y: y.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Rect {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{}x{}+{}+{}", self.width, self.height, self.x, self.y)
|
||||
@@ -135,9 +145,20 @@ impl Rect {
|
||||
/// - Positive `x` moves the whole `Rect` to the right, negative to the left.
|
||||
/// - Positive `y` moves the whole `Rect` to the bottom, negative to the top.
|
||||
///
|
||||
/// See [`Offset`] for details.
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// # use ratatui::{prelude::*, layout::Offset};
|
||||
/// let rect = Rect::new(1, 2, 3, 4);
|
||||
/// let rect = rect.offset(Offset { x: 10, y: 20 });
|
||||
/// assert_eq!(rect, Rect::new(11, 22, 3, 4));
|
||||
///
|
||||
/// // offset can also be called with a tuple of (x, y)
|
||||
/// let rect = rect.offset((10, 20));
|
||||
/// ```
|
||||
#[must_use = "method returns the modified value"]
|
||||
pub fn offset(self, offset: Offset) -> Self {
|
||||
pub fn offset<T: Into<Offset>>(self, offset: T) -> Self {
|
||||
let offset = offset.into();
|
||||
Self {
|
||||
x: i32::from(self.x)
|
||||
.saturating_add(offset.x)
|
||||
@@ -423,6 +444,11 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn offset_from_tuple() {
|
||||
assert_eq!(Rect::new(1, 2, 3, 4).offset((5, 6)), Rect::new(6, 8, 3, 4));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn union() {
|
||||
assert_eq!(
|
||||
|
||||
13
src/lib.rs
13
src/lib.rs
@@ -139,7 +139,8 @@
|
||||
//!
|
||||
//! fn ui(frame: &mut Frame) {
|
||||
//! frame.render_widget(
|
||||
//! Paragraph::new("Hello World!").block(Block::bordered().title("Greeting")),
|
||||
//! Paragraph::new("Hello World!")
|
||||
//! .block(Block::default().title("Greeting").borders(Borders::ALL)),
|
||||
//! frame.size(),
|
||||
//! );
|
||||
//! }
|
||||
@@ -183,8 +184,14 @@
|
||||
//! [Constraint::Percentage(50), Constraint::Percentage(50)],
|
||||
//! )
|
||||
//! .split(main_layout[1]);
|
||||
//! frame.render_widget(Block::bordered().title("Left"), inner_layout[0]);
|
||||
//! frame.render_widget(Block::bordered().title("Right"), inner_layout[1]);
|
||||
//! frame.render_widget(
|
||||
//! Block::default().borders(Borders::ALL).title("Left"),
|
||||
//! inner_layout[0],
|
||||
//! );
|
||||
//! frame.render_widget(
|
||||
//! Block::default().borders(Borders::ALL).title("Right"),
|
||||
//! inner_layout[1],
|
||||
//! );
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
|
||||
50
src/style.rs
50
src/style.rs
@@ -68,14 +68,14 @@
|
||||
//! [`prelude`]: crate::prelude
|
||||
//! [`Span`]: crate::text::Span
|
||||
|
||||
use std::fmt;
|
||||
use std::fmt::{self, Debug};
|
||||
|
||||
use bitflags::bitflags;
|
||||
|
||||
mod color;
|
||||
mod stylize;
|
||||
|
||||
pub use color::{Color, ParseColorError};
|
||||
pub use color::Color;
|
||||
pub use stylize::{Styled, Stylize};
|
||||
pub mod palette;
|
||||
|
||||
@@ -119,7 +119,7 @@ impl fmt::Debug for Modifier {
|
||||
if self.is_empty() {
|
||||
return write!(f, "NONE");
|
||||
}
|
||||
write!(f, "{}", self.0)
|
||||
fmt::Debug::fmt(&self.0, f)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -552,26 +552,32 @@ impl From<(Color, Color, Modifier, Modifier)> for Style {
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
fn styles() -> Vec<Style> {
|
||||
vec![
|
||||
Style::default(),
|
||||
Style::default().fg(Color::Yellow),
|
||||
Style::default().bg(Color::Yellow),
|
||||
Style::default().add_modifier(Modifier::BOLD),
|
||||
Style::default().remove_modifier(Modifier::BOLD),
|
||||
Style::default().add_modifier(Modifier::ITALIC),
|
||||
Style::default().remove_modifier(Modifier::ITALIC),
|
||||
Style::default().add_modifier(Modifier::ITALIC | Modifier::BOLD),
|
||||
Style::default().remove_modifier(Modifier::ITALIC | Modifier::BOLD),
|
||||
]
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn combined_patch_gives_same_result_as_individual_patch() {
|
||||
let styles = [
|
||||
Style::new(),
|
||||
Style::new().fg(Color::Yellow),
|
||||
Style::new().bg(Color::Yellow),
|
||||
Style::new().add_modifier(Modifier::BOLD),
|
||||
Style::new().remove_modifier(Modifier::BOLD),
|
||||
Style::new().add_modifier(Modifier::ITALIC),
|
||||
Style::new().remove_modifier(Modifier::ITALIC),
|
||||
Style::new().add_modifier(Modifier::ITALIC | Modifier::BOLD),
|
||||
Style::new().remove_modifier(Modifier::ITALIC | Modifier::BOLD),
|
||||
];
|
||||
let styles = styles();
|
||||
for &a in &styles {
|
||||
for &b in &styles {
|
||||
for &c in &styles {
|
||||
for &d in &styles {
|
||||
let combined = a.patch(b.patch(c.patch(d)));
|
||||
|
||||
assert_eq!(
|
||||
Style::new().patch(a).patch(b).patch(c).patch(d),
|
||||
Style::new().patch(a.patch(b.patch(c.patch(d))))
|
||||
Style::default().patch(a).patch(b).patch(c).patch(d),
|
||||
Style::default().patch(combined)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -583,7 +589,7 @@ mod tests {
|
||||
fn combine_individual_modifiers() {
|
||||
use crate::{buffer::Buffer, layout::Rect};
|
||||
|
||||
let mods = [
|
||||
let mods = vec![
|
||||
Modifier::BOLD,
|
||||
Modifier::DIM,
|
||||
Modifier::ITALIC,
|
||||
@@ -597,12 +603,14 @@ mod tests {
|
||||
|
||||
let mut buffer = Buffer::empty(Rect::new(0, 0, 1, 1));
|
||||
|
||||
for m in mods {
|
||||
for m in &mods {
|
||||
buffer.get_mut(0, 0).set_style(Style::reset());
|
||||
buffer.get_mut(0, 0).set_style(Style::new().add_modifier(m));
|
||||
buffer
|
||||
.get_mut(0, 0)
|
||||
.set_style(Style::default().add_modifier(*m));
|
||||
let style = buffer.get(0, 0).style();
|
||||
assert!(style.add_modifier.contains(m));
|
||||
assert!(!style.sub_modifier.contains(m));
|
||||
assert!(style.add_modifier.contains(*m));
|
||||
assert!(!style.sub_modifier.contains(*m));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
#![allow(clippy::unreadable_literal)]
|
||||
|
||||
use std::{fmt, str::FromStr};
|
||||
use std::{
|
||||
fmt::{self, Debug, Display},
|
||||
str::FromStr,
|
||||
};
|
||||
|
||||
/// ANSI Color
|
||||
///
|
||||
@@ -63,6 +66,7 @@ use std::{fmt, str::FromStr};
|
||||
///
|
||||
/// [ANSI color table]: https://en.wikipedia.org/wiki/ANSI_escape_code#Colors
|
||||
#[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
|
||||
pub enum Color {
|
||||
/// Resets the foreground or background color
|
||||
#[default]
|
||||
@@ -137,102 +141,14 @@ impl Color {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
impl serde::Serialize for Color {
|
||||
/// This utilises the [`fmt::Display`] implementation for serialization.
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::Serializer,
|
||||
{
|
||||
serializer.serialize_str(&self.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
impl<'de> serde::Deserialize<'de> for Color {
|
||||
/// This is used to deserialize a value into Color via serde.
|
||||
///
|
||||
/// This implementation uses the `FromStr` trait to deserialize strings, so named colours, RGB,
|
||||
/// and indexed values are able to be deserialized. In addition, values that were produced by
|
||||
/// the the older serialization implementation of Color are also able to be deserialized.
|
||||
///
|
||||
/// Prior to v0.26.0, Ratatui would be serialized using a map for indexed and RGB values, for
|
||||
/// examples in json `{"Indexed": 10}` and `{"Rgb": [255, 0, 255]}` respectively. Now they are
|
||||
/// serialized using the string representation of the index and the RGB hex value, for example
|
||||
/// in json it would now be `"10"` and `"#FF00FF"` respectively.
|
||||
///
|
||||
/// See the [`Color`] documentation for more information on color names.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use ratatui::prelude::*;
|
||||
///
|
||||
/// #[derive(Debug, serde::Deserialize)]
|
||||
/// struct Theme {
|
||||
/// color: Color,
|
||||
/// }
|
||||
///
|
||||
/// # fn get_theme() -> Result<(), serde_json::Error> {
|
||||
/// let theme: Theme = serde_json::from_str(r#"{"color": "bright-white"}"#)?;
|
||||
/// assert_eq!(theme.color, Color::White);
|
||||
///
|
||||
/// let theme: Theme = serde_json::from_str(r##"{"color": "#00FF00"}"##)?;
|
||||
/// assert_eq!(theme.color, Color::Rgb(0, 255, 0));
|
||||
///
|
||||
/// let theme: Theme = serde_json::from_str(r#"{"color": "42"}"#)?;
|
||||
/// assert_eq!(theme.color, Color::Indexed(42));
|
||||
///
|
||||
/// let err = serde_json::from_str::<Theme>(r#"{"color": "invalid"}"#).unwrap_err();
|
||||
/// assert!(err.is_data());
|
||||
/// assert_eq!(
|
||||
/// err.to_string(),
|
||||
/// "Failed to parse Colors at line 1 column 20"
|
||||
/// );
|
||||
///
|
||||
/// // Deserializing from the previous serialization implementation
|
||||
/// let theme: Theme = serde_json::from_str(r#"{"color": {"Rgb":[255,0,255]}}"#)?;
|
||||
/// assert_eq!(theme.color, Color::Rgb(255, 0, 255));
|
||||
///
|
||||
/// let theme: Theme = serde_json::from_str(r#"{"color": {"Indexed":10}}"#)?;
|
||||
/// assert_eq!(theme.color, Color::Indexed(10));
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: serde::Deserializer<'de>,
|
||||
{
|
||||
/// Colors are currently serialized with the `Display` implementation, so
|
||||
/// RGB values are serialized via hex, for example "#FFFFFF".
|
||||
///
|
||||
/// Previously they were serialized using serde derive, which encoded
|
||||
/// RGB values as a map, for example { "rgb": [255, 255, 255] }.
|
||||
///
|
||||
/// The deserialization implementation utilises a `Helper` struct
|
||||
/// to be able to support both formats for backwards compatibility.
|
||||
#[derive(serde::Deserialize)]
|
||||
enum ColorWrapper {
|
||||
Rgb(u8, u8, u8),
|
||||
Indexed(u8),
|
||||
}
|
||||
|
||||
#[derive(serde::Deserialize)]
|
||||
#[serde(untagged)]
|
||||
enum ColorFormat {
|
||||
V2(String),
|
||||
V1(ColorWrapper),
|
||||
}
|
||||
|
||||
let multi_type = ColorFormat::deserialize(deserializer)
|
||||
.map_err(|err| serde::de::Error::custom(format!("Failed to parse Colors: {err}")))?;
|
||||
match multi_type {
|
||||
ColorFormat::V2(s) => FromStr::from_str(&s).map_err(serde::de::Error::custom),
|
||||
ColorFormat::V1(color_wrapper) => match color_wrapper {
|
||||
ColorWrapper::Rgb(red, green, blue) => Ok(Self::Rgb(red, green, blue)),
|
||||
ColorWrapper::Indexed(index) => Ok(Self::Indexed(index)),
|
||||
},
|
||||
}
|
||||
let s = String::deserialize(deserializer)?;
|
||||
FromStr::from_str(&s).map_err(serde::de::Error::custom)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -240,8 +156,8 @@ impl<'de> serde::Deserialize<'de> for Color {
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
|
||||
pub struct ParseColorError;
|
||||
|
||||
impl fmt::Display for ParseColorError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
impl std::fmt::Display for ParseColorError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "Failed to parse Colors")
|
||||
}
|
||||
}
|
||||
@@ -333,7 +249,7 @@ impl FromStr for Color {
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Color {
|
||||
impl Display for Color {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Self::Reset => write!(f, "Reset"),
|
||||
@@ -663,42 +579,4 @@ mod tests {
|
||||
Color::deserialize("#00000000".into_deserializer());
|
||||
assert!(color.is_err());
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
#[test]
|
||||
fn serialize_then_deserialize() -> Result<(), serde_json::Error> {
|
||||
let json_rgb = serde_json::to_string(&Color::Rgb(255, 0, 255))?;
|
||||
assert_eq!(json_rgb, r##""#FF00FF""##);
|
||||
assert_eq!(
|
||||
serde_json::from_str::<Color>(&json_rgb)?,
|
||||
Color::Rgb(255, 0, 255)
|
||||
);
|
||||
|
||||
let json_white = serde_json::to_string(&Color::White)?;
|
||||
assert_eq!(json_white, r#""White""#);
|
||||
|
||||
let json_indexed = serde_json::to_string(&Color::Indexed(10))?;
|
||||
assert_eq!(json_indexed, r#""10""#);
|
||||
assert_eq!(
|
||||
serde_json::from_str::<Color>(&json_indexed)?,
|
||||
Color::Indexed(10)
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
#[test]
|
||||
fn deserialize_with_previous_format() -> Result<(), serde_json::Error> {
|
||||
assert_eq!(Color::White, serde_json::from_str::<Color>("\"White\"")?);
|
||||
assert_eq!(
|
||||
Color::Rgb(255, 0, 255),
|
||||
serde_json::from_str::<Color>(r#"{"Rgb":[255,0,255]}"#)?
|
||||
);
|
||||
assert_eq!(
|
||||
Color::Indexed(10),
|
||||
serde_json::from_str::<Color>(r#"{"Indexed":10}"#)?
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,7 +133,11 @@ macro_rules! modifier {
|
||||
/// "world".green().on_yellow().not_bold(),
|
||||
/// ]);
|
||||
/// let paragraph = Paragraph::new(line).italic().underlined();
|
||||
/// let block = Block::bordered().title("Title").on_white().bold();
|
||||
/// let block = Block::default()
|
||||
/// .title("Title")
|
||||
/// .borders(Borders::ALL)
|
||||
/// .on_white()
|
||||
/// .bold();
|
||||
/// ```
|
||||
pub trait Stylize<'a, T>: Sized {
|
||||
#[must_use = "`bg` returns the modified style without modifying the original"]
|
||||
|
||||
@@ -65,7 +65,7 @@ impl Frame<'_> {
|
||||
/// # let backend = TestBackend::new(5, 5);
|
||||
/// # let mut terminal = Terminal::new(backend).unwrap();
|
||||
/// # let mut frame = terminal.get_frame();
|
||||
/// let block = Block::new();
|
||||
/// let block = Block::default();
|
||||
/// let area = Rect::new(0, 0, 5, 5);
|
||||
/// frame.render_widget(block, area);
|
||||
/// ```
|
||||
@@ -87,7 +87,7 @@ impl Frame<'_> {
|
||||
/// # let backend = TestBackend::new(5, 5);
|
||||
/// # let mut terminal = Terminal::new(backend).unwrap();
|
||||
/// # let mut frame = terminal.get_frame();
|
||||
/// let block = Block::new();
|
||||
/// let block = Block::default();
|
||||
/// let area = Rect::new(0, 0, 5, 5);
|
||||
/// frame.render_widget_ref(block, area);
|
||||
/// ```
|
||||
|
||||
@@ -25,20 +25,21 @@
|
||||
//! // Converted to Line(vec![
|
||||
//! // Span { content: Cow::Borrowed("My title"), style: Style { .. } }
|
||||
//! // ])
|
||||
//! let block = Block::new().title("My title");
|
||||
//! let block = Block::default().title("My title");
|
||||
//!
|
||||
//! // A simple string with a unique style.
|
||||
//! // Converted to Line(vec![
|
||||
//! // Span { content: Cow::Borrowed("My title"), style: Style { fg: Some(Color::Yellow), .. }
|
||||
//! // ])
|
||||
//! let block = Block::new().title(Span::styled("My title", Style::default().fg(Color::Yellow)));
|
||||
//! let block =
|
||||
//! Block::default().title(Span::styled("My title", Style::default().fg(Color::Yellow)));
|
||||
//!
|
||||
//! // A string with multiple styles.
|
||||
//! // Converted to Line(vec![
|
||||
//! // Span { content: Cow::Borrowed("My"), style: Style { fg: Some(Color::Yellow), .. } },
|
||||
//! // Span { content: Cow::Borrowed(" title"), .. }
|
||||
//! // ])
|
||||
//! let block = Block::new().title(vec![
|
||||
//! let block = Block::default().title(vec![
|
||||
//! Span::styled("My", Style::default().fg(Color::Yellow)),
|
||||
//! Span::raw(" title"),
|
||||
//! ]);
|
||||
|
||||
107
src/text/line.rs
107
src/text/line.rs
@@ -1,5 +1,5 @@
|
||||
#![deny(missing_docs)]
|
||||
use std::{borrow::Cow, fmt};
|
||||
use std::borrow::Cow;
|
||||
|
||||
use super::StyledGrapheme;
|
||||
use crate::prelude::*;
|
||||
@@ -453,39 +453,6 @@ impl<'a> Line<'a> {
|
||||
self.spans.iter_mut()
|
||||
}
|
||||
|
||||
/// Returns a line that's truncated corresponding to it's alignment and result width
|
||||
#[must_use = "method returns the modified value"]
|
||||
fn truncated(&'a self, result_width: u16) -> Self {
|
||||
let mut truncated_line = Line::default();
|
||||
let width = self.width() as u16;
|
||||
let mut offset = match self.alignment {
|
||||
Some(Alignment::Center) => (width.saturating_sub(result_width)) / 2,
|
||||
Some(Alignment::Right) => width.saturating_sub(result_width),
|
||||
_ => 0,
|
||||
};
|
||||
let mut x = 0;
|
||||
for span in &self.spans {
|
||||
let span_width = span.width() as u16;
|
||||
if offset >= span_width {
|
||||
offset -= span_width;
|
||||
continue;
|
||||
}
|
||||
let mut new_span = span.clone();
|
||||
let new_span_width = span_width - offset;
|
||||
if x + new_span_width > result_width {
|
||||
let span_end = (result_width - x + offset) as usize;
|
||||
new_span.content = Cow::from(&span.content[offset as usize..span_end]);
|
||||
truncated_line.spans.push(new_span);
|
||||
break;
|
||||
}
|
||||
|
||||
new_span.content = Cow::from(&span.content[offset as usize..]);
|
||||
truncated_line.spans.push(new_span);
|
||||
x += new_span_width;
|
||||
offset = 0;
|
||||
}
|
||||
truncated_line
|
||||
}
|
||||
/// Adds a span to the line.
|
||||
///
|
||||
/// `span` can be any type that is convertible into a `Span`. For example, you can pass a
|
||||
@@ -587,23 +554,17 @@ impl WidgetRef for Line<'_> {
|
||||
let area = area.intersection(buf.area);
|
||||
buf.set_style(area, self.style);
|
||||
let width = self.width() as u16;
|
||||
let mut x = area.left();
|
||||
let line = if width > area.width {
|
||||
self.truncated(area.width)
|
||||
} else {
|
||||
let offset = match self.alignment {
|
||||
Some(Alignment::Center) => (area.width.saturating_sub(width)) / 2,
|
||||
Some(Alignment::Right) => area.width.saturating_sub(width),
|
||||
Some(Alignment::Left) | None => 0,
|
||||
};
|
||||
x = x.saturating_add(offset);
|
||||
self.to_owned()
|
||||
let offset = match self.alignment {
|
||||
Some(Alignment::Center) => (area.width.saturating_sub(width)) / 2,
|
||||
Some(Alignment::Right) => area.width.saturating_sub(width),
|
||||
Some(Alignment::Left) | None => 0,
|
||||
};
|
||||
for span in &line.spans {
|
||||
let mut x = area.left().saturating_add(offset);
|
||||
for span in &self.spans {
|
||||
let span_width = span.width() as u16;
|
||||
let span_area = Rect {
|
||||
x,
|
||||
width: span_width.min(area.right().saturating_sub(x)),
|
||||
width: span_width.min(area.right() - x),
|
||||
..area
|
||||
};
|
||||
span.render(span_area, buf);
|
||||
@@ -615,8 +576,8 @@ impl WidgetRef for Line<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Line<'_> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
impl std::fmt::Display for Line<'_> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
for span in &self.spans {
|
||||
write!(f, "{span}")?;
|
||||
}
|
||||
@@ -643,7 +604,6 @@ mod tests {
|
||||
use rstest::{fixture, rstest};
|
||||
|
||||
use super::*;
|
||||
use crate::assert_buffer_eq;
|
||||
|
||||
#[fixture]
|
||||
fn small_buf() -> Buffer {
|
||||
@@ -887,53 +847,6 @@ mod tests {
|
||||
|
||||
assert_eq!(format!("{line_from_styled_span}"), "Hello, world!");
|
||||
}
|
||||
#[test]
|
||||
fn render_truncates_left() {
|
||||
let mut buf = Buffer::empty(Rect::new(0, 0, 5, 1));
|
||||
Line::from("Hello world")
|
||||
.left_aligned()
|
||||
.render(buf.area, &mut buf);
|
||||
let expected = Buffer::with_lines(vec!["Hello"]);
|
||||
assert_buffer_eq!(buf, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn render_truncates_right() {
|
||||
let mut buf = Buffer::empty(Rect::new(0, 0, 5, 1));
|
||||
Line::from("Hello world")
|
||||
.right_aligned()
|
||||
.render(buf.area, &mut buf);
|
||||
let expected = Buffer::with_lines(vec!["world"]);
|
||||
assert_buffer_eq!(buf, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn render_truncates_center() {
|
||||
let mut buf = Buffer::empty(Rect::new(0, 0, 5, 1));
|
||||
Line::from("Hello world")
|
||||
.centered()
|
||||
.render(buf.area, &mut buf);
|
||||
let expected = Buffer::with_lines(vec!["lo wo"]);
|
||||
assert_buffer_eq!(buf, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn truncate_line_with_multiple_spans() {
|
||||
let line = Line::default().spans(vec!["foo", "bar"]);
|
||||
assert_eq!(
|
||||
line.right_aligned().truncated(4).to_string(),
|
||||
String::from("obar")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn truncation_ignores_useless_spans() {
|
||||
let line = Line::default().spans(vec!["foo", "bar"]);
|
||||
assert_eq!(
|
||||
line.right_aligned().truncated(3),
|
||||
Line::default().spans(vec!["bar"])
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn left_aligned() {
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
use std::{borrow::Cow, fmt};
|
||||
use std::{
|
||||
borrow::Cow,
|
||||
fmt::{self, Debug, Display},
|
||||
};
|
||||
|
||||
use super::Text;
|
||||
|
||||
@@ -43,17 +46,17 @@ impl<'a> Masked<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Masked<'_> {
|
||||
impl Debug for Masked<'_> {
|
||||
/// Debug representation of a masked string is the underlying string
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.write_str(&self.inner)
|
||||
Display::fmt(&self.inner, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Masked<'_> {
|
||||
impl Display for Masked<'_> {
|
||||
/// Display representation of a masked string is the masked string
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.write_str(&self.value())
|
||||
Display::fmt(&self.value(), f)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use std::{borrow::Cow, fmt};
|
||||
use std::{borrow::Cow, fmt::Debug};
|
||||
|
||||
use unicode_segmentation::UnicodeSegmentation;
|
||||
use unicode_width::UnicodeWidthStr;
|
||||
@@ -395,8 +395,8 @@ impl WidgetRef for Span<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Span<'_> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
impl std::fmt::Display for Span<'_> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{}", &self.content)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#![warn(missing_docs)]
|
||||
use std::{borrow::Cow, fmt};
|
||||
use std::borrow::Cow;
|
||||
|
||||
use itertools::{Itertools, Position};
|
||||
|
||||
@@ -580,8 +580,8 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Text<'_> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
impl std::fmt::Display for Text<'_> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
for (position, line) in self.iter().with_position() {
|
||||
if position == Position::Last {
|
||||
write!(f, "{line}")?;
|
||||
|
||||
@@ -45,7 +45,7 @@ pub use bar_group::BarGroup;
|
||||
/// use ratatui::{prelude::*, widgets::*};
|
||||
///
|
||||
/// BarChart::default()
|
||||
/// .block(Block::bordered().title("BarChart"))
|
||||
/// .block(Block::default().title("BarChart").borders(Borders::ALL))
|
||||
/// .bar_width(3)
|
||||
/// .bar_gap(1)
|
||||
/// .group_gap(3)
|
||||
@@ -615,7 +615,10 @@ mod tests {
|
||||
use itertools::iproduct;
|
||||
|
||||
use super::*;
|
||||
use crate::{assert_buffer_eq, widgets::BorderType};
|
||||
use crate::{
|
||||
assert_buffer_eq,
|
||||
widgets::{BorderType, Borders},
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn default() {
|
||||
@@ -643,9 +646,10 @@ mod tests {
|
||||
#[test]
|
||||
fn block() {
|
||||
let mut buffer = Buffer::empty(Rect::new(0, 0, 15, 5));
|
||||
let block = Block::bordered()
|
||||
let block = Block::default()
|
||||
.title("Block")
|
||||
.border_type(BorderType::Double)
|
||||
.title("Block");
|
||||
.borders(Borders::ALL);
|
||||
let widget = BarChart::default()
|
||||
.data(&[("foo", 1), ("bar", 2)])
|
||||
.block(block);
|
||||
|
||||
@@ -41,12 +41,12 @@ pub use title::{Position, Title};
|
||||
/// ```
|
||||
/// use ratatui::{prelude::*, widgets::*};
|
||||
///
|
||||
/// Block::new()
|
||||
/// .border_type(BorderType::Rounded)
|
||||
/// Block::default()
|
||||
/// .title("Block")
|
||||
/// .borders(Borders::LEFT | Borders::RIGHT)
|
||||
/// .border_style(Style::default().fg(Color::White))
|
||||
/// .style(Style::default().bg(Color::Black))
|
||||
/// .title("Block");
|
||||
/// .border_type(BorderType::Rounded)
|
||||
/// .style(Style::default().bg(Color::Black));
|
||||
/// ```
|
||||
///
|
||||
/// You may also use multiple titles like in the following:
|
||||
@@ -56,7 +56,7 @@ pub use title::{Position, Title};
|
||||
/// widgets::{block::*, *},
|
||||
/// };
|
||||
///
|
||||
/// Block::new()
|
||||
/// Block::default()
|
||||
/// .title("Title 1")
|
||||
/// .title(Title::from("Title 2").position(Position::Bottom));
|
||||
/// ```
|
||||
@@ -173,11 +173,6 @@ impl<'a> Block<'a> {
|
||||
}
|
||||
|
||||
/// Create a new block with [all borders](Borders::ALL) shown
|
||||
///
|
||||
/// ```
|
||||
/// # use ratatui::widgets::{Block, Borders};
|
||||
/// assert_eq!(Block::bordered(), Block::new().borders(Borders::ALL));
|
||||
/// ```
|
||||
pub const fn bordered() -> Self {
|
||||
let mut block = Self::new();
|
||||
block.borders = Borders::ALL;
|
||||
@@ -224,7 +219,7 @@ impl<'a> Block<'a> {
|
||||
/// widgets::{block::*, *},
|
||||
/// };
|
||||
///
|
||||
/// Block::new()
|
||||
/// Block::default()
|
||||
/// .title("Title") // By default in the top left corner
|
||||
/// .title(Title::from("Left").alignment(Alignment::Left)) // also on the left
|
||||
/// .title(Title::from("Right").alignment(Alignment::Right))
|
||||
@@ -330,12 +325,12 @@ impl<'a> Block<'a> {
|
||||
/// widgets::{block::*, *},
|
||||
/// };
|
||||
///
|
||||
/// Block::new()
|
||||
/// .title_alignment(Alignment::Center)
|
||||
/// Block::default()
|
||||
/// // This title won't be aligned in the center
|
||||
/// .title(Title::from("right").alignment(Alignment::Right))
|
||||
/// .title("foo")
|
||||
/// .title("bar");
|
||||
/// .title("bar")
|
||||
/// .title_alignment(Alignment::Center);
|
||||
/// ```
|
||||
#[must_use = "method moves the value of self and returns the modified value"]
|
||||
pub const fn title_alignment(mut self, alignment: Alignment) -> Self {
|
||||
@@ -357,12 +352,12 @@ impl<'a> Block<'a> {
|
||||
/// widgets::{block::*, *},
|
||||
/// };
|
||||
///
|
||||
/// Block::new()
|
||||
/// .title_position(Position::Bottom)
|
||||
/// Block::default()
|
||||
/// // This title won't be aligned in the center
|
||||
/// .title(Title::from("top").position(Position::Top))
|
||||
/// .title("foo")
|
||||
/// .title("bar");
|
||||
/// .title("bar")
|
||||
/// .title_position(Position::Bottom);
|
||||
/// ```
|
||||
#[must_use = "method moves the value of self and returns the modified value"]
|
||||
pub const fn title_position(mut self, position: Position) -> Self {
|
||||
@@ -382,7 +377,9 @@ impl<'a> Block<'a> {
|
||||
/// This example shows a `Block` with blue borders.
|
||||
/// ```
|
||||
/// # use ratatui::{prelude::*, widgets::*};
|
||||
/// Block::bordered().border_style(Style::new().blue());
|
||||
/// Block::default()
|
||||
/// .borders(Borders::ALL)
|
||||
/// .border_style(Style::new().blue());
|
||||
/// ```
|
||||
#[must_use = "method moves the value of self and returns the modified value"]
|
||||
pub fn border_style<S: Into<Style>>(mut self, style: S) -> Self {
|
||||
@@ -412,13 +409,17 @@ impl<'a> Block<'a> {
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Simply show all borders.
|
||||
/// ```
|
||||
/// # use ratatui::{prelude::*, widgets::*};
|
||||
/// Block::default().borders(Borders::ALL);
|
||||
/// ```
|
||||
///
|
||||
/// Display left and right borders.
|
||||
/// ```
|
||||
/// # use ratatui::{prelude::*, widgets::*};
|
||||
/// Block::new().borders(Borders::LEFT | Borders::RIGHT);
|
||||
/// Block::default().borders(Borders::LEFT | Borders::RIGHT);
|
||||
/// ```
|
||||
///
|
||||
/// To show all borders you can abbreviate this with [`Block::bordered`]
|
||||
#[must_use = "method moves the value of self and returns the modified value"]
|
||||
pub const fn borders(mut self, flag: Borders) -> Self {
|
||||
self.borders = flag;
|
||||
@@ -436,9 +437,10 @@ impl<'a> Block<'a> {
|
||||
///
|
||||
/// ```
|
||||
/// # use ratatui::{prelude::*, widgets::*};
|
||||
/// Block::bordered()
|
||||
/// .border_type(BorderType::Rounded)
|
||||
/// .title("Block");
|
||||
/// Block::default()
|
||||
/// .title("Block")
|
||||
/// .borders(Borders::ALL)
|
||||
/// .border_type(BorderType::Rounded);
|
||||
/// // Renders
|
||||
/// // ╭Block╮
|
||||
/// // │ │
|
||||
@@ -458,7 +460,7 @@ impl<'a> Block<'a> {
|
||||
///
|
||||
/// ```
|
||||
/// # use ratatui::{prelude::*, widgets::*};
|
||||
/// Block::bordered().border_set(symbols::border::DOUBLE).title("Block");
|
||||
/// Block::default().title("Block").borders(Borders::ALL).border_set(symbols::border::DOUBLE);
|
||||
/// // Renders
|
||||
/// // ╔Block╗
|
||||
/// // ║ ║
|
||||
@@ -477,8 +479,8 @@ impl<'a> Block<'a> {
|
||||
/// ```
|
||||
/// # use ratatui::{prelude::*, widgets::*};
|
||||
/// # fn render_nested_block(frame: &mut Frame) {
|
||||
/// let outer_block = Block::bordered().title("Outer");
|
||||
/// let inner_block = Block::bordered().title("Inner");
|
||||
/// let outer_block = Block::default().title("Outer").borders(Borders::ALL);
|
||||
/// let inner_block = Block::default().title("Inner").borders(Borders::ALL);
|
||||
///
|
||||
/// let outer_area = frame.size();
|
||||
/// let inner_area = outer_block.inner(outer_area);
|
||||
@@ -499,14 +501,14 @@ impl<'a> Block<'a> {
|
||||
inner.x = inner.x.saturating_add(1).min(inner.right());
|
||||
inner.width = inner.width.saturating_sub(1);
|
||||
}
|
||||
if self.borders.intersects(Borders::TOP) || self.has_title_at_position(Position::Top) {
|
||||
if self.borders.intersects(Borders::TOP) || self.have_title_at_position(Position::Top) {
|
||||
inner.y = inner.y.saturating_add(1).min(inner.bottom());
|
||||
inner.height = inner.height.saturating_sub(1);
|
||||
}
|
||||
if self.borders.intersects(Borders::RIGHT) {
|
||||
inner.width = inner.width.saturating_sub(1);
|
||||
}
|
||||
if self.borders.intersects(Borders::BOTTOM) || self.has_title_at_position(Position::Bottom)
|
||||
if self.borders.intersects(Borders::BOTTOM) || self.have_title_at_position(Position::Bottom)
|
||||
{
|
||||
inner.height = inner.height.saturating_sub(1);
|
||||
}
|
||||
@@ -524,7 +526,7 @@ impl<'a> Block<'a> {
|
||||
inner
|
||||
}
|
||||
|
||||
fn has_title_at_position(&self, position: Position) -> bool {
|
||||
fn have_title_at_position(&self, position: Position) -> bool {
|
||||
self.titles
|
||||
.iter()
|
||||
.any(|title| title.position.unwrap_or(self.titles_position) == position)
|
||||
@@ -539,7 +541,9 @@ impl<'a> Block<'a> {
|
||||
/// This renders a `Block` with no padding (the default).
|
||||
/// ```
|
||||
/// # use ratatui::{prelude::*, widgets::*};
|
||||
/// Block::bordered().padding(Padding::zero());
|
||||
/// Block::default()
|
||||
/// .borders(Borders::ALL)
|
||||
/// .padding(Padding::zero());
|
||||
/// // Renders
|
||||
/// // ┌───────┐
|
||||
/// // │content│
|
||||
@@ -550,7 +554,9 @@ impl<'a> Block<'a> {
|
||||
/// Notice the two spaces before and after the content.
|
||||
/// ```
|
||||
/// # use ratatui::{prelude::*, widgets::*};
|
||||
/// Block::bordered().padding(Padding::horizontal(2));
|
||||
/// Block::default()
|
||||
/// .borders(Borders::ALL)
|
||||
/// .padding(Padding::horizontal(2));
|
||||
/// // Renders
|
||||
/// // ┌───────────┐
|
||||
/// // │ content │
|
||||
@@ -876,33 +882,33 @@ mod tests {
|
||||
fn inner_takes_into_account_the_borders() {
|
||||
// No borders
|
||||
assert_eq!(
|
||||
Block::new().inner(Rect::default()),
|
||||
Block::default().inner(Rect::default()),
|
||||
Rect::new(0, 0, 0, 0),
|
||||
"no borders, width=0, height=0"
|
||||
);
|
||||
assert_eq!(
|
||||
Block::new().inner(Rect::new(0, 0, 1, 1)),
|
||||
Block::default().inner(Rect::new(0, 0, 1, 1)),
|
||||
Rect::new(0, 0, 1, 1),
|
||||
"no borders, width=1, height=1"
|
||||
);
|
||||
|
||||
// Left border
|
||||
assert_eq!(
|
||||
Block::new()
|
||||
Block::default()
|
||||
.borders(Borders::LEFT)
|
||||
.inner(Rect::new(0, 0, 0, 1)),
|
||||
Rect::new(0, 0, 0, 1),
|
||||
"left, width=0"
|
||||
);
|
||||
assert_eq!(
|
||||
Block::new()
|
||||
Block::default()
|
||||
.borders(Borders::LEFT)
|
||||
.inner(Rect::new(0, 0, 1, 1)),
|
||||
Rect::new(1, 0, 0, 1),
|
||||
"left, width=1"
|
||||
);
|
||||
assert_eq!(
|
||||
Block::new()
|
||||
Block::default()
|
||||
.borders(Borders::LEFT)
|
||||
.inner(Rect::new(0, 0, 2, 1)),
|
||||
Rect::new(1, 0, 1, 1),
|
||||
@@ -911,21 +917,21 @@ mod tests {
|
||||
|
||||
// Top border
|
||||
assert_eq!(
|
||||
Block::new()
|
||||
Block::default()
|
||||
.borders(Borders::TOP)
|
||||
.inner(Rect::new(0, 0, 1, 0)),
|
||||
Rect::new(0, 0, 1, 0),
|
||||
"top, height=0"
|
||||
);
|
||||
assert_eq!(
|
||||
Block::new()
|
||||
Block::default()
|
||||
.borders(Borders::TOP)
|
||||
.inner(Rect::new(0, 0, 1, 1)),
|
||||
Rect::new(0, 1, 1, 0),
|
||||
"top, height=1"
|
||||
);
|
||||
assert_eq!(
|
||||
Block::new()
|
||||
Block::default()
|
||||
.borders(Borders::TOP)
|
||||
.inner(Rect::new(0, 0, 1, 2)),
|
||||
Rect::new(0, 1, 1, 1),
|
||||
@@ -934,21 +940,21 @@ mod tests {
|
||||
|
||||
// Right border
|
||||
assert_eq!(
|
||||
Block::new()
|
||||
Block::default()
|
||||
.borders(Borders::RIGHT)
|
||||
.inner(Rect::new(0, 0, 0, 1)),
|
||||
Rect::new(0, 0, 0, 1),
|
||||
"right, width=0"
|
||||
);
|
||||
assert_eq!(
|
||||
Block::new()
|
||||
Block::default()
|
||||
.borders(Borders::RIGHT)
|
||||
.inner(Rect::new(0, 0, 1, 1)),
|
||||
Rect::new(0, 0, 0, 1),
|
||||
"right, width=1"
|
||||
);
|
||||
assert_eq!(
|
||||
Block::new()
|
||||
Block::default()
|
||||
.borders(Borders::RIGHT)
|
||||
.inner(Rect::new(0, 0, 2, 1)),
|
||||
Rect::new(0, 0, 1, 1),
|
||||
@@ -957,21 +963,21 @@ mod tests {
|
||||
|
||||
// Bottom border
|
||||
assert_eq!(
|
||||
Block::new()
|
||||
Block::default()
|
||||
.borders(Borders::BOTTOM)
|
||||
.inner(Rect::new(0, 0, 1, 0)),
|
||||
Rect::new(0, 0, 1, 0),
|
||||
"bottom, height=0"
|
||||
);
|
||||
assert_eq!(
|
||||
Block::new()
|
||||
Block::default()
|
||||
.borders(Borders::BOTTOM)
|
||||
.inner(Rect::new(0, 0, 1, 1)),
|
||||
Rect::new(0, 0, 1, 0),
|
||||
"bottom, height=1"
|
||||
);
|
||||
assert_eq!(
|
||||
Block::new()
|
||||
Block::default()
|
||||
.borders(Borders::BOTTOM)
|
||||
.inner(Rect::new(0, 0, 1, 2)),
|
||||
Rect::new(0, 0, 1, 1),
|
||||
@@ -980,22 +986,30 @@ mod tests {
|
||||
|
||||
// All borders
|
||||
assert_eq!(
|
||||
Block::bordered().inner(Rect::default()),
|
||||
Block::default()
|
||||
.borders(Borders::ALL)
|
||||
.inner(Rect::default()),
|
||||
Rect::new(0, 0, 0, 0),
|
||||
"all borders, width=0, height=0"
|
||||
);
|
||||
assert_eq!(
|
||||
Block::bordered().inner(Rect::new(0, 0, 1, 1)),
|
||||
Block::default()
|
||||
.borders(Borders::ALL)
|
||||
.inner(Rect::new(0, 0, 1, 1)),
|
||||
Rect::new(1, 1, 0, 0),
|
||||
"all borders, width=1, height=1"
|
||||
);
|
||||
assert_eq!(
|
||||
Block::bordered().inner(Rect::new(0, 0, 2, 2)),
|
||||
Block::default()
|
||||
.borders(Borders::ALL)
|
||||
.inner(Rect::new(0, 0, 2, 2)),
|
||||
Rect::new(1, 1, 0, 0),
|
||||
"all borders, width=2, height=2"
|
||||
);
|
||||
assert_eq!(
|
||||
Block::bordered().inner(Rect::new(0, 0, 3, 3)),
|
||||
Block::default()
|
||||
.borders(Borders::ALL)
|
||||
.inner(Rect::new(0, 0, 3, 3)),
|
||||
Rect::new(1, 1, 1, 1),
|
||||
"all borders, width=3, height=3"
|
||||
);
|
||||
@@ -1004,17 +1018,17 @@ mod tests {
|
||||
#[test]
|
||||
fn inner_takes_into_account_the_title() {
|
||||
assert_eq!(
|
||||
Block::new().title("Test").inner(Rect::new(0, 0, 0, 1)),
|
||||
Block::default().title("Test").inner(Rect::new(0, 0, 0, 1)),
|
||||
Rect::new(0, 1, 0, 0),
|
||||
);
|
||||
assert_eq!(
|
||||
Block::new()
|
||||
Block::default()
|
||||
.title(Title::from("Test").alignment(Alignment::Center))
|
||||
.inner(Rect::new(0, 0, 0, 1)),
|
||||
Rect::new(0, 1, 0, 0),
|
||||
);
|
||||
assert_eq!(
|
||||
Block::new()
|
||||
Block::default()
|
||||
.title(Title::from("Test").alignment(Alignment::Right))
|
||||
.inner(Rect::new(0, 0, 0, 1)),
|
||||
Rect::new(0, 1, 0, 0),
|
||||
@@ -1025,72 +1039,72 @@ mod tests {
|
||||
fn inner_takes_into_account_border_and_title() {
|
||||
let test_rect = Rect::new(0, 0, 0, 2);
|
||||
|
||||
let top_top = Block::new()
|
||||
.borders(Borders::TOP)
|
||||
.title(Title::from("Test").position(Position::Top));
|
||||
let top_top = Block::default()
|
||||
.title(Title::from("Test").position(Position::Top))
|
||||
.borders(Borders::TOP);
|
||||
assert_eq!(top_top.inner(test_rect), Rect::new(0, 1, 0, 1));
|
||||
|
||||
let top_bot = Block::new()
|
||||
.borders(Borders::BOTTOM)
|
||||
.title(Title::from("Test").position(Position::Top));
|
||||
let top_bot = Block::default()
|
||||
.title(Title::from("Test").position(Position::Top))
|
||||
.borders(Borders::BOTTOM);
|
||||
assert_eq!(top_bot.inner(test_rect), Rect::new(0, 1, 0, 0));
|
||||
|
||||
let bot_top = Block::new()
|
||||
.borders(Borders::TOP)
|
||||
.title(Title::from("Test").position(Position::Bottom));
|
||||
let bot_top = Block::default()
|
||||
.title(Title::from("Test").position(Position::Bottom))
|
||||
.borders(Borders::TOP);
|
||||
assert_eq!(bot_top.inner(test_rect), Rect::new(0, 1, 0, 0));
|
||||
|
||||
let bot_bot = Block::new()
|
||||
.borders(Borders::BOTTOM)
|
||||
.title(Title::from("Test").position(Position::Bottom));
|
||||
let bot_bot = Block::default()
|
||||
.title(Title::from("Test").position(Position::Bottom))
|
||||
.borders(Borders::BOTTOM);
|
||||
assert_eq!(bot_bot.inner(test_rect), Rect::new(0, 0, 0, 1));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn has_title_at_position_takes_into_account_all_positioning_declarations() {
|
||||
let block = Block::new();
|
||||
assert!(!block.has_title_at_position(Position::Top));
|
||||
assert!(!block.has_title_at_position(Position::Bottom));
|
||||
fn have_title_at_position_takes_into_account_all_positioning_declarations() {
|
||||
let block = Block::default();
|
||||
assert!(!block.have_title_at_position(Position::Top));
|
||||
assert!(!block.have_title_at_position(Position::Bottom));
|
||||
|
||||
let block = Block::new().title(Title::from("Test").position(Position::Top));
|
||||
assert!(block.has_title_at_position(Position::Top));
|
||||
assert!(!block.has_title_at_position(Position::Bottom));
|
||||
let block = Block::default().title(Title::from("Test").position(Position::Top));
|
||||
assert!(block.have_title_at_position(Position::Top));
|
||||
assert!(!block.have_title_at_position(Position::Bottom));
|
||||
|
||||
let block = Block::new().title(Title::from("Test").position(Position::Bottom));
|
||||
assert!(!block.has_title_at_position(Position::Top));
|
||||
assert!(block.has_title_at_position(Position::Bottom));
|
||||
let block = Block::default().title(Title::from("Test").position(Position::Bottom));
|
||||
assert!(!block.have_title_at_position(Position::Top));
|
||||
assert!(block.have_title_at_position(Position::Bottom));
|
||||
|
||||
let block = Block::new()
|
||||
let block = Block::default()
|
||||
.title(Title::from("Test").position(Position::Top))
|
||||
.title_position(Position::Bottom);
|
||||
assert!(block.has_title_at_position(Position::Top));
|
||||
assert!(!block.has_title_at_position(Position::Bottom));
|
||||
assert!(block.have_title_at_position(Position::Top));
|
||||
assert!(!block.have_title_at_position(Position::Bottom));
|
||||
|
||||
let block = Block::new()
|
||||
let block = Block::default()
|
||||
.title(Title::from("Test").position(Position::Bottom))
|
||||
.title_position(Position::Top);
|
||||
assert!(!block.has_title_at_position(Position::Top));
|
||||
assert!(block.has_title_at_position(Position::Bottom));
|
||||
assert!(!block.have_title_at_position(Position::Top));
|
||||
assert!(block.have_title_at_position(Position::Bottom));
|
||||
|
||||
let block = Block::new()
|
||||
let block = Block::default()
|
||||
.title(Title::from("Test").position(Position::Top))
|
||||
.title(Title::from("Test").position(Position::Bottom));
|
||||
assert!(block.has_title_at_position(Position::Top));
|
||||
assert!(block.has_title_at_position(Position::Bottom));
|
||||
assert!(block.have_title_at_position(Position::Top));
|
||||
assert!(block.have_title_at_position(Position::Bottom));
|
||||
|
||||
let block = Block::new()
|
||||
let block = Block::default()
|
||||
.title(Title::from("Test").position(Position::Top))
|
||||
.title(Title::from("Test"))
|
||||
.title_position(Position::Bottom);
|
||||
assert!(block.has_title_at_position(Position::Top));
|
||||
assert!(block.has_title_at_position(Position::Bottom));
|
||||
assert!(block.have_title_at_position(Position::Top));
|
||||
assert!(block.have_title_at_position(Position::Bottom));
|
||||
|
||||
let block = Block::new()
|
||||
let block = Block::default()
|
||||
.title(Title::from("Test"))
|
||||
.title(Title::from("Test").position(Position::Bottom))
|
||||
.title_position(Position::Top);
|
||||
assert!(block.has_title_at_position(Position::Top));
|
||||
assert!(block.has_title_at_position(Position::Bottom));
|
||||
assert!(block.have_title_at_position(Position::Top));
|
||||
assert!(block.have_title_at_position(Position::Bottom));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -1120,49 +1134,50 @@ mod tests {
|
||||
const fn block_can_be_const() {
|
||||
const _DEFAULT_STYLE: Style = Style::new();
|
||||
const _DEFAULT_PADDING: Padding = Padding::uniform(1);
|
||||
const _DEFAULT_BLOCK: Block = Block::bordered()
|
||||
const _DEFAULT_BLOCK: Block = Block::new()
|
||||
// the following methods are no longer const because they use Into<Style>
|
||||
// .style(_DEFAULT_STYLE) // no longer const
|
||||
// .border_style(_DEFAULT_STYLE) // no longer const
|
||||
// .title_style(_DEFAULT_STYLE) // no longer const
|
||||
.title_alignment(Alignment::Left)
|
||||
.title_position(Position::Top)
|
||||
.borders(Borders::ALL)
|
||||
.padding(_DEFAULT_PADDING);
|
||||
}
|
||||
|
||||
/// Ensure Style from/into works the way a user would use it.
|
||||
/// This test ensures that we have some coverage on the [`Style::from()`] implementations
|
||||
#[test]
|
||||
fn style_into_works_from_user_view() {
|
||||
fn block_style() {
|
||||
// nominal style
|
||||
let block = Block::new().style(Style::new().red());
|
||||
let block = Block::default().style(Style::new().red());
|
||||
assert_eq!(block.style, Style::new().red());
|
||||
|
||||
// auto-convert from Color
|
||||
let block = Block::new().style(Color::Red);
|
||||
let block = Block::default().style(Color::Red);
|
||||
assert_eq!(block.style, Style::new().red());
|
||||
|
||||
// auto-convert from (Color, Color)
|
||||
let block = Block::new().style((Color::Red, Color::Blue));
|
||||
let block = Block::default().style((Color::Red, Color::Blue));
|
||||
assert_eq!(block.style, Style::new().red().on_blue());
|
||||
|
||||
// auto-convert from Modifier
|
||||
let block = Block::new().style(Modifier::BOLD | Modifier::ITALIC);
|
||||
let block = Block::default().style(Modifier::BOLD | Modifier::ITALIC);
|
||||
assert_eq!(block.style, Style::new().bold().italic());
|
||||
|
||||
// auto-convert from (Modifier, Modifier)
|
||||
let block = Block::new().style((Modifier::BOLD | Modifier::ITALIC, Modifier::DIM));
|
||||
let block = Block::default().style((Modifier::BOLD | Modifier::ITALIC, Modifier::DIM));
|
||||
assert_eq!(block.style, Style::new().bold().italic().not_dim());
|
||||
|
||||
// auto-convert from (Color, Modifier)
|
||||
let block = Block::new().style((Color::Red, Modifier::BOLD));
|
||||
let block = Block::default().style((Color::Red, Modifier::BOLD));
|
||||
assert_eq!(block.style, Style::new().red().bold());
|
||||
|
||||
// auto-convert from (Color, Color, Modifier)
|
||||
let block = Block::new().style((Color::Red, Color::Blue, Modifier::BOLD));
|
||||
let block = Block::default().style((Color::Red, Color::Blue, Modifier::BOLD));
|
||||
assert_eq!(block.style, Style::new().red().on_blue().bold());
|
||||
|
||||
// auto-convert from (Color, Color, Modifier, Modifier)
|
||||
let block = Block::new().style((
|
||||
let block = Block::default().style((
|
||||
Color::Red,
|
||||
Color::Blue,
|
||||
Modifier::BOLD | Modifier::ITALIC,
|
||||
@@ -1176,7 +1191,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn can_be_stylized() {
|
||||
let block = Block::new().black().on_white().bold().not_dim();
|
||||
let block = Block::default().black().on_white().bold().not_dim();
|
||||
assert_eq!(
|
||||
block.style,
|
||||
Style::default()
|
||||
@@ -1240,9 +1255,9 @@ mod tests {
|
||||
];
|
||||
for (alignment, expected) in tests {
|
||||
let mut buffer = Buffer::empty(Rect::new(0, 0, 8, 1));
|
||||
Block::new()
|
||||
.title_alignment(alignment)
|
||||
Block::default()
|
||||
.title("test")
|
||||
.title_alignment(alignment)
|
||||
.render(buffer.area, &mut buffer);
|
||||
assert_buffer_eq!(buffer, Buffer::with_lines(vec![expected]));
|
||||
}
|
||||
@@ -1257,9 +1272,9 @@ mod tests {
|
||||
];
|
||||
for (block_title_alignment, alignment, expected) in tests {
|
||||
let mut buffer = Buffer::empty(Rect::new(0, 0, 8, 1));
|
||||
Block::new()
|
||||
.title_alignment(block_title_alignment)
|
||||
Block::default()
|
||||
.title(Title::from("test").alignment(alignment))
|
||||
.title_alignment(block_title_alignment)
|
||||
.render(buffer.area, &mut buffer);
|
||||
assert_buffer_eq!(buffer, Buffer::with_lines(vec![expected]));
|
||||
}
|
||||
@@ -1269,9 +1284,9 @@ mod tests {
|
||||
#[test]
|
||||
fn render_right_aligned_empty_title() {
|
||||
let mut buffer = Buffer::empty(Rect::new(0, 0, 15, 3));
|
||||
Block::new()
|
||||
.title_alignment(Alignment::Right)
|
||||
Block::default()
|
||||
.title("")
|
||||
.title_alignment(Alignment::Right)
|
||||
.render(buffer.area, &mut buffer);
|
||||
assert_buffer_eq!(
|
||||
buffer,
|
||||
@@ -1286,9 +1301,9 @@ mod tests {
|
||||
#[test]
|
||||
fn title_position() {
|
||||
let mut buffer = Buffer::empty(Rect::new(0, 0, 4, 2));
|
||||
Block::new()
|
||||
.title_position(Position::Bottom)
|
||||
Block::default()
|
||||
.title("test")
|
||||
.title_position(Position::Bottom)
|
||||
.render(buffer.area, &mut buffer);
|
||||
assert_buffer_eq!(buffer, Buffer::with_lines(vec![" ", "test"]));
|
||||
}
|
||||
@@ -1297,9 +1312,9 @@ mod tests {
|
||||
fn title_content_style() {
|
||||
for alignment in [Alignment::Left, Alignment::Center, Alignment::Right] {
|
||||
let mut buffer = Buffer::empty(Rect::new(0, 0, 4, 1));
|
||||
Block::new()
|
||||
.title_alignment(alignment)
|
||||
Block::default()
|
||||
.title("test".yellow())
|
||||
.title_alignment(alignment)
|
||||
.render(buffer.area, &mut buffer);
|
||||
|
||||
let mut expected_buffer = Buffer::with_lines(vec!["test"]);
|
||||
@@ -1313,10 +1328,10 @@ mod tests {
|
||||
fn block_title_style() {
|
||||
for alignment in [Alignment::Left, Alignment::Center, Alignment::Right] {
|
||||
let mut buffer = Buffer::empty(Rect::new(0, 0, 4, 1));
|
||||
Block::new()
|
||||
.title_alignment(alignment)
|
||||
.title_style(Style::new().yellow())
|
||||
Block::default()
|
||||
.title("test")
|
||||
.title_style(Style::new().yellow())
|
||||
.title_alignment(alignment)
|
||||
.render(buffer.area, &mut buffer);
|
||||
|
||||
let mut expected_buffer = Buffer::with_lines(vec!["test"]);
|
||||
@@ -1330,10 +1345,10 @@ mod tests {
|
||||
fn title_style_overrides_block_title_style() {
|
||||
for alignment in [Alignment::Left, Alignment::Center, Alignment::Right] {
|
||||
let mut buffer = Buffer::empty(Rect::new(0, 0, 4, 1));
|
||||
Block::new()
|
||||
.title_alignment(alignment)
|
||||
.title_style(Style::new().green().on_red())
|
||||
Block::default()
|
||||
.title("test".yellow())
|
||||
.title_style(Style::new().green().on_red())
|
||||
.title_alignment(alignment)
|
||||
.render(buffer.area, &mut buffer);
|
||||
|
||||
let mut expected_buffer = Buffer::with_lines(vec!["test"]);
|
||||
@@ -1346,8 +1361,9 @@ mod tests {
|
||||
#[test]
|
||||
fn title_border_style() {
|
||||
let mut buffer = Buffer::empty(Rect::new(0, 0, 15, 3));
|
||||
Block::bordered()
|
||||
Block::default()
|
||||
.title("test")
|
||||
.borders(Borders::ALL)
|
||||
.border_style(Style::new().yellow())
|
||||
.render(buffer.area, &mut buffer);
|
||||
|
||||
@@ -1382,7 +1398,8 @@ mod tests {
|
||||
#[test]
|
||||
fn render_plain_border() {
|
||||
let mut buffer = Buffer::empty(Rect::new(0, 0, 15, 3));
|
||||
Block::bordered()
|
||||
Block::default()
|
||||
.borders(Borders::ALL)
|
||||
.border_type(BorderType::Plain)
|
||||
.render(buffer.area, &mut buffer);
|
||||
assert_buffer_eq!(
|
||||
@@ -1398,7 +1415,8 @@ mod tests {
|
||||
#[test]
|
||||
fn render_rounded_border() {
|
||||
let mut buffer = Buffer::empty(Rect::new(0, 0, 15, 3));
|
||||
Block::bordered()
|
||||
Block::default()
|
||||
.borders(Borders::ALL)
|
||||
.border_type(BorderType::Rounded)
|
||||
.render(buffer.area, &mut buffer);
|
||||
assert_buffer_eq!(
|
||||
@@ -1414,7 +1432,8 @@ mod tests {
|
||||
#[test]
|
||||
fn render_double_border() {
|
||||
let mut buffer = Buffer::empty(Rect::new(0, 0, 15, 3));
|
||||
Block::bordered()
|
||||
Block::default()
|
||||
.borders(Borders::ALL)
|
||||
.border_type(BorderType::Double)
|
||||
.render(buffer.area, &mut buffer);
|
||||
assert_buffer_eq!(
|
||||
@@ -1430,7 +1449,8 @@ mod tests {
|
||||
#[test]
|
||||
fn render_quadrant_inside() {
|
||||
let mut buffer = Buffer::empty(Rect::new(0, 0, 15, 3));
|
||||
Block::bordered()
|
||||
Block::default()
|
||||
.borders(Borders::ALL)
|
||||
.border_type(BorderType::QuadrantInside)
|
||||
.render(buffer.area, &mut buffer);
|
||||
assert_buffer_eq!(
|
||||
@@ -1446,7 +1466,8 @@ mod tests {
|
||||
#[test]
|
||||
fn render_border_quadrant_outside() {
|
||||
let mut buffer = Buffer::empty(Rect::new(0, 0, 15, 3));
|
||||
Block::bordered()
|
||||
Block::default()
|
||||
.borders(Borders::ALL)
|
||||
.border_type(BorderType::QuadrantOutside)
|
||||
.render(buffer.area, &mut buffer);
|
||||
assert_buffer_eq!(
|
||||
@@ -1462,7 +1483,8 @@ mod tests {
|
||||
#[test]
|
||||
fn render_solid_border() {
|
||||
let mut buffer = Buffer::empty(Rect::new(0, 0, 15, 3));
|
||||
Block::bordered()
|
||||
Block::default()
|
||||
.borders(Borders::ALL)
|
||||
.border_type(BorderType::Thick)
|
||||
.render(buffer.area, &mut buffer);
|
||||
assert_buffer_eq!(
|
||||
@@ -1478,7 +1500,8 @@ mod tests {
|
||||
#[test]
|
||||
fn render_custom_border_set() {
|
||||
let mut buffer = Buffer::empty(Rect::new(0, 0, 15, 3));
|
||||
Block::bordered()
|
||||
Block::default()
|
||||
.borders(Borders::ALL)
|
||||
.border_set(border::Set {
|
||||
top_left: "1",
|
||||
top_right: "2",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use std::fmt;
|
||||
use std::fmt::{self, Debug};
|
||||
|
||||
use bitflags::bitflags;
|
||||
|
||||
@@ -24,7 +24,7 @@ bitflags! {
|
||||
/// Implement the `Debug` trait for the `Borders` bitflags. This is a manual implementation to
|
||||
/// display the flags in a more readable way. The default implementation would display the
|
||||
/// flags as 'Border(0x0)' for `Borders::NONE` for example.
|
||||
impl fmt::Debug for Borders {
|
||||
impl Debug for Borders {
|
||||
/// Display the Borders bitflags as a list of names. For example, `Borders::NONE` will be
|
||||
/// displayed as `NONE` and `Borders::ALL` will be displayed as `ALL`. If multiple flags are
|
||||
/// set, they will be displayed separated by a pipe character.
|
||||
|
||||
@@ -28,14 +28,14 @@ pub struct Monthly<'a, DS: DateStyler> {
|
||||
|
||||
impl<'a, DS: DateStyler> Monthly<'a, DS> {
|
||||
/// Construct a calendar for the `display_date` and highlight the `events`
|
||||
pub const fn new(display_date: Date, events: DS) -> Self {
|
||||
pub fn new(display_date: Date, events: DS) -> Self {
|
||||
Self {
|
||||
display_date,
|
||||
events,
|
||||
show_surrounding: None,
|
||||
show_weekday: None,
|
||||
show_month: None,
|
||||
default_style: Style::new(),
|
||||
default_style: Style::default(),
|
||||
block: None,
|
||||
}
|
||||
}
|
||||
@@ -90,10 +90,10 @@ impl<'a, DS: DateStyler> Monthly<'a, DS> {
|
||||
}
|
||||
|
||||
/// Return a style with only the background from the default style
|
||||
const fn default_bg(&self) -> Style {
|
||||
fn default_bg(&self) -> Style {
|
||||
match self.default_style.bg {
|
||||
None => Style::new(),
|
||||
Some(c) => Style::new().bg(c),
|
||||
None => Style::default(),
|
||||
Some(c) => Style::default().bg(c),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -164,7 +164,7 @@ impl<DS: DateStyler> Monthly<'_, DS> {
|
||||
|
||||
let mut y = days_area.y;
|
||||
// go through all the weeks containing a day in the target month.
|
||||
while curr_day.month() != self.display_date.month().next() {
|
||||
while curr_day.month() as u8 != self.display_date.month().next() as u8 {
|
||||
let mut spans = Vec::with_capacity(14);
|
||||
for i in 0..7 {
|
||||
// Draw the gutter. Do it here so we can avoid worrying about
|
||||
|
||||
@@ -19,7 +19,7 @@ mod points;
|
||||
mod rectangle;
|
||||
mod world;
|
||||
|
||||
use std::{fmt, iter::zip};
|
||||
use std::{fmt::Debug, iter::zip};
|
||||
|
||||
use itertools::Itertools;
|
||||
|
||||
@@ -70,7 +70,7 @@ struct Layer {
|
||||
/// resolution of the grid might exceed the number of rows and columns. For example, a grid of
|
||||
/// Braille patterns will have a resolution of 2x4 dots per cell. This means that a grid of 10x10
|
||||
/// cells will have a resolution of 20x40 dots.
|
||||
trait Grid: fmt::Debug {
|
||||
trait Grid: Debug {
|
||||
/// Get the resolution of the grid in number of dots.
|
||||
///
|
||||
/// This doesn't have to be the same as the number of rows and columns of the grid. For example,
|
||||
@@ -567,7 +567,7 @@ impl<'a> Context<'a> {
|
||||
/// };
|
||||
///
|
||||
/// Canvas::default()
|
||||
/// .block(Block::bordered().title("Canvas"))
|
||||
/// .block(Block::default().title("Canvas").borders(Borders::ALL))
|
||||
/// .x_bounds([-180.0, 180.0])
|
||||
/// .y_bounds([-90.0, 90.0])
|
||||
/// .paint(|ctx| {
|
||||
|
||||
@@ -27,7 +27,7 @@ pub enum MapResolution {
|
||||
}
|
||||
|
||||
impl MapResolution {
|
||||
const fn data(self) -> &'static [(f64, f64)] {
|
||||
fn data(self) -> &'static [(f64, f64)] {
|
||||
match self {
|
||||
Self::Low => &WORLD_LOW_RESOLUTION,
|
||||
Self::High => &WORLD_HIGH_RESOLUTION,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/// [Source data](http://www.gnuplotting.org/plotting-the-world-revisited)
|
||||
pub const WORLD_HIGH_RESOLUTION: [(f64, f64); 5125] = [
|
||||
pub static WORLD_HIGH_RESOLUTION: [(f64, f64); 5125] = [
|
||||
(-163.7128, -78.5956),
|
||||
(-163.1058, -78.2233),
|
||||
(-161.2451, -78.3801),
|
||||
@@ -5127,7 +5127,7 @@ pub const WORLD_HIGH_RESOLUTION: [(f64, f64); 5125] = [
|
||||
(180.0, -84.71338),
|
||||
];
|
||||
|
||||
pub const WORLD_LOW_RESOLUTION: [(f64, f64); 1166] = [
|
||||
pub static WORLD_LOW_RESOLUTION: [(f64, f64); 1166] = [
|
||||
(-92.32, 48.24),
|
||||
(-88.13, 48.92),
|
||||
(-83.11, 46.27),
|
||||
|
||||
@@ -8,7 +8,7 @@ use crate::{
|
||||
prelude::*,
|
||||
widgets::{
|
||||
canvas::{Canvas, Line as CanvasLine, Points},
|
||||
Block,
|
||||
Block, Borders,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -475,7 +475,7 @@ struct ChartLayout {
|
||||
///
|
||||
/// // Create the chart and link all the parts together
|
||||
/// let chart = Chart::new(datasets)
|
||||
/// .block(Block::new().title("Chart"))
|
||||
/// .block(Block::default().title("Chart"))
|
||||
/// .x_axis(x_axis)
|
||||
/// .y_axis(y_axis);
|
||||
/// ```
|
||||
@@ -1050,7 +1050,9 @@ impl WidgetRef for Chart<'_> {
|
||||
|
||||
if let Some(legend_area) = layout.legend_area {
|
||||
buf.set_style(legend_area, original_style);
|
||||
Block::bordered().render(legend_area, buf);
|
||||
Block::default()
|
||||
.borders(Borders::ALL)
|
||||
.render(legend_area, buf);
|
||||
|
||||
for (i, (dataset_name, dataset_style)) in self
|
||||
.datasets
|
||||
|
||||
@@ -11,7 +11,7 @@ use crate::prelude::*;
|
||||
/// use ratatui::{prelude::*, widgets::*};
|
||||
///
|
||||
/// fn draw_on_clear(f: &mut Frame, area: Rect) {
|
||||
/// let block = Block::bordered().title("Block");
|
||||
/// let block = Block::default().title("Block").borders(Borders::ALL);
|
||||
/// f.render_widget(Clear, area); // <- this will clear/reset the area first
|
||||
/// f.render_widget(block, area); // now render the block widget
|
||||
/// }
|
||||
|
||||
@@ -17,7 +17,7 @@ use crate::{prelude::*, widgets::Block};
|
||||
/// use ratatui::{prelude::*, widgets::*};
|
||||
///
|
||||
/// Gauge::default()
|
||||
/// .block(Block::bordered().title("Progress"))
|
||||
/// .block(Block::default().borders(Borders::ALL).title("Progress"))
|
||||
/// .gauge_style(
|
||||
/// Style::default()
|
||||
/// .fg(Color::White)
|
||||
@@ -164,12 +164,12 @@ impl WidgetRef for Gauge<'_> {
|
||||
buf.set_style(area, self.style);
|
||||
self.block.render_ref(area, buf);
|
||||
let inner = self.block.inner_if_some(area);
|
||||
self.render_gauge(inner, buf);
|
||||
self.render_gague(inner, buf);
|
||||
}
|
||||
}
|
||||
|
||||
impl Gauge<'_> {
|
||||
fn render_gauge(&self, gauge_area: Rect, buf: &mut Buffer) {
|
||||
fn render_gague(&self, gauge_area: Rect, buf: &mut Buffer) {
|
||||
if gauge_area.is_empty() {
|
||||
return;
|
||||
}
|
||||
@@ -249,7 +249,7 @@ fn get_unicode_block<'a>(frac: f64) -> &'a str {
|
||||
/// use ratatui::{prelude::*, widgets::*};
|
||||
///
|
||||
/// LineGauge::default()
|
||||
/// .block(Block::bordered().title("Progress"))
|
||||
/// .block(Block::default().borders(Borders::ALL).title("Progress"))
|
||||
/// .gauge_style(
|
||||
/// Style::default()
|
||||
/// .fg(Color::White)
|
||||
|
||||
@@ -384,7 +384,7 @@ where
|
||||
/// # let area = Rect::default();
|
||||
/// let items = ["Item 1", "Item 2", "Item 3"];
|
||||
/// let list = List::new(items)
|
||||
/// .block(Block::bordered().title("List"))
|
||||
/// .block(Block::default().title("List").borders(Borders::ALL))
|
||||
/// .style(Style::default().fg(Color::White))
|
||||
/// .highlight_style(Style::default().add_modifier(Modifier::ITALIC))
|
||||
/// .highlight_symbol(">>")
|
||||
@@ -405,7 +405,7 @@ where
|
||||
/// let mut state = ListState::default();
|
||||
/// let items = ["Item 1", "Item 2", "Item 3"];
|
||||
/// let list = List::new(items)
|
||||
/// .block(Block::bordered().title("List"))
|
||||
/// .block(Block::default().title("List").borders(Borders::ALL))
|
||||
/// .highlight_style(Style::new().add_modifier(Modifier::REVERSED))
|
||||
/// .highlight_symbol(">>")
|
||||
/// .repeat_highlight_symbol(true);
|
||||
@@ -537,7 +537,7 @@ impl<'a> List<'a> {
|
||||
/// ```rust
|
||||
/// # use ratatui::{prelude::*, widgets::*};
|
||||
/// # let items = vec!["Item 1"];
|
||||
/// let block = Block::bordered().title("List");
|
||||
/// let block = Block::default().title("List").borders(Borders::ALL);
|
||||
/// let list = List::new(items).block(block);
|
||||
/// ```
|
||||
#[must_use = "method moves the value of self and returns the modified value"]
|
||||
@@ -1049,7 +1049,7 @@ mod tests {
|
||||
use rstest::{fixture, rstest};
|
||||
|
||||
use super::*;
|
||||
use crate::assert_buffer_eq;
|
||||
use crate::{assert_buffer_eq, widgets::Borders};
|
||||
|
||||
#[test]
|
||||
fn test_list_state_selected() {
|
||||
@@ -1229,7 +1229,7 @@ mod tests {
|
||||
|
||||
let list = List::new(items)
|
||||
.highlight_symbol(">>")
|
||||
.block(Block::bordered());
|
||||
.block(Block::default().borders(Borders::all()));
|
||||
// attempt to render into an area of the buffer with zero height after
|
||||
// setting the block borders
|
||||
Widget::render(list, Rect::new(0, 0, 15, 2), &mut buffer);
|
||||
@@ -1474,7 +1474,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_list_with_empty_strings() {
|
||||
let items = list_items(vec!["Item 0", "", "", "Item 1", "Item 2"]);
|
||||
let list = List::new(items).block(Block::bordered().title("List"));
|
||||
let list = List::new(items).block(Block::default().title("List").borders(Borders::ALL));
|
||||
let buffer = render_widget(list, 10, 7);
|
||||
|
||||
let expected = Buffer::with_lines(vec![
|
||||
@@ -1499,7 +1499,7 @@ mod tests {
|
||||
#[test]
|
||||
fn test_list_block() {
|
||||
let items = list_items(vec!["Item 0", "Item 1", "Item 2"]);
|
||||
let list = List::new(items).block(Block::bordered().title("List"));
|
||||
let list = List::new(items).block(Block::default().title("List").borders(Borders::ALL));
|
||||
let buffer = render_widget(list, 10, 7);
|
||||
|
||||
let expected = Buffer::with_lines(vec![
|
||||
|
||||
@@ -31,7 +31,7 @@ const fn get_line_offset(line_width: u16, text_area_width: u16, alignment: Align
|
||||
/// "Third line".into(),
|
||||
/// ];
|
||||
/// Paragraph::new(text)
|
||||
/// .block(Block::bordered().title("Paragraph"))
|
||||
/// .block(Block::new().title("Paragraph").borders(Borders::ALL))
|
||||
/// .style(Style::new().white().on_black())
|
||||
/// .alignment(Alignment::Center)
|
||||
/// .wrap(Wrap { trim: true });
|
||||
@@ -126,7 +126,8 @@ impl<'a> Paragraph<'a> {
|
||||
///
|
||||
/// ```rust
|
||||
/// # use ratatui::{prelude::*, widgets::*};
|
||||
/// let paragraph = Paragraph::new("Hello, world!").block(Block::bordered().title("Paragraph"));
|
||||
/// let paragraph = Paragraph::new("Hello, world!")
|
||||
/// .block(Block::default().title("Paragraph").borders(Borders::ALL));
|
||||
/// ```
|
||||
#[must_use = "method moves the value of self and returns the modified value"]
|
||||
pub fn block(mut self, block: Block<'a>) -> Self {
|
||||
@@ -255,8 +256,6 @@ impl<'a> Paragraph<'a> {
|
||||
/// need in order to be fully rendered. For paragraphs that do not use wrapping, this count is
|
||||
/// simply the number of lines present in the paragraph.
|
||||
///
|
||||
/// Note: The design for text wrapping is not stable and might affect this API.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```ignore
|
||||
@@ -268,6 +267,7 @@ impl<'a> Paragraph<'a> {
|
||||
/// ```
|
||||
#[stability::unstable(
|
||||
feature = "rendered-line-info",
|
||||
reason = "The design for text wrapping is not stable and might affect this API.",
|
||||
issue = "https://github.com/ratatui-org/ratatui/issues/293"
|
||||
)]
|
||||
pub fn line_count(&self, width: u16) -> usize {
|
||||
@@ -297,8 +297,6 @@ impl<'a> Paragraph<'a> {
|
||||
|
||||
/// Calculates the shortest line width needed to avoid any word being wrapped or truncated.
|
||||
///
|
||||
/// Note: The design for text wrapping is not stable and might affect this API.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```ignore
|
||||
@@ -311,6 +309,7 @@ impl<'a> Paragraph<'a> {
|
||||
/// ```
|
||||
#[stability::unstable(
|
||||
feature = "rendered-line-info",
|
||||
reason = "The design for text wrapping is not stable and might affect this API.",
|
||||
issue = "https://github.com/ratatui-org/ratatui/issues/293"
|
||||
)]
|
||||
pub fn line_width(&self) -> usize {
|
||||
@@ -526,7 +525,8 @@ mod test {
|
||||
// We use the slightly unconventional "worlds" instead of "world" here to make sure when we
|
||||
// can truncate this without triggering the typos linter.
|
||||
let text = "Hello, worlds!";
|
||||
let truncated_paragraph = Paragraph::new(text).block(Block::bordered().title("Title"));
|
||||
let truncated_paragraph =
|
||||
Paragraph::new(text).block(Block::default().title("Title").borders(Borders::ALL));
|
||||
let wrapped_paragraph = truncated_paragraph.clone().wrap(Wrap { trim: false });
|
||||
let trimmed_paragraph = truncated_paragraph.clone().wrap(Wrap { trim: true });
|
||||
|
||||
@@ -625,10 +625,10 @@ mod test {
|
||||
|
||||
#[test]
|
||||
fn test_render_paragraph_with_block_with_bottom_title_and_border() {
|
||||
let block = Block::new()
|
||||
.borders(Borders::BOTTOM)
|
||||
let block = Block::default()
|
||||
.title("Title")
|
||||
.title_position(Position::Bottom)
|
||||
.title("Title");
|
||||
.borders(Borders::BOTTOM);
|
||||
let paragraph = Paragraph::new("Hello, world!").block(block);
|
||||
|
||||
test_case(
|
||||
|
||||
@@ -6,7 +6,6 @@ use unicode_width::UnicodeWidthStr;
|
||||
use crate::{layout::Alignment, text::StyledGrapheme};
|
||||
|
||||
const NBSP: &str = "\u{00a0}";
|
||||
const ZWSP: &str = "\u{200b}";
|
||||
|
||||
/// A state machine to pack styled symbols into lines.
|
||||
/// Cannot implement it as Iterator since it yields slices of the internal buffer (need streaming
|
||||
@@ -105,8 +104,8 @@ where
|
||||
|
||||
let mut has_seen_non_whitespace = false;
|
||||
for StyledGrapheme { symbol, style } in line_symbols {
|
||||
let symbol_whitespace = symbol == ZWSP
|
||||
|| (symbol.chars().all(&char::is_whitespace) && symbol != NBSP);
|
||||
let symbol_whitespace =
|
||||
symbol.chars().all(&char::is_whitespace) && symbol != NBSP;
|
||||
let symbol_width = symbol.width() as u16;
|
||||
// Ignore characters wider than the total max width
|
||||
if symbol_width > self.max_line_width {
|
||||
@@ -707,12 +706,4 @@ mod test {
|
||||
vec![Alignment::Left, Alignment::Right, Alignment::Center]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn line_composer_zero_width_white_space() {
|
||||
let width = 3;
|
||||
let line = "foo\u{200b}bar";
|
||||
let (word_wrapper, _, _) = run_composer(Composer::WordWrapper { trim: true }, line, width);
|
||||
assert_eq!(word_wrapper, vec!["foo", "bar"]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,11 +29,6 @@ use crate::{prelude::*, symbols::scrollbar::*};
|
||||
/// └─────────── begin
|
||||
/// ```
|
||||
///
|
||||
/// # Important
|
||||
///
|
||||
/// You must specify the [`ScrollbarState::content_length`] before rendering the `Scrollbar`, or
|
||||
/// else the `Scrollbar` will render blank.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
|
||||
@@ -24,7 +24,7 @@ use crate::{prelude::*, widgets::Block};
|
||||
/// use ratatui::{prelude::*, widgets::*};
|
||||
///
|
||||
/// Sparkline::default()
|
||||
/// .block(Block::bordered().title("Sparkline"))
|
||||
/// .block(Block::default().title("Sparkline").borders(Borders::ALL))
|
||||
/// .data(&[0, 2, 3, 4, 1, 4, 10])
|
||||
/// .max(5)
|
||||
/// .direction(RenderDirection::RightToLeft)
|
||||
|
||||
@@ -75,7 +75,7 @@ use crate::{layout::Flex, prelude::*, widgets::Block};
|
||||
/// // It has an optional footer, which is simply a Row always visible at the bottom.
|
||||
/// .footer(Row::new(vec!["Updated on Dec 28"]))
|
||||
/// // As any other widget, a Table can be wrapped in a Block.
|
||||
/// .block(Block::new().title("Table"))
|
||||
/// .block(Block::default().title("Table"))
|
||||
/// // The selected row and its content can also be styled.
|
||||
/// .highlight_style(Style::new().reversed())
|
||||
/// // ...and potentially show a symbol in front of the selection.
|
||||
@@ -178,7 +178,7 @@ use crate::{layout::Flex, prelude::*, widgets::Block};
|
||||
/// ];
|
||||
/// let widths = [Constraint::Length(5), Constraint::Length(5), Constraint::Length(10)];
|
||||
/// let table = Table::new(rows, widths)
|
||||
/// .block(Block::new().title("Table"))
|
||||
/// .block(Block::default().title("Table"))
|
||||
/// .highlight_style(Style::new().add_modifier(Modifier::REVERSED))
|
||||
/// .highlight_symbol(">>");
|
||||
///
|
||||
@@ -418,7 +418,7 @@ impl<'a> Table<'a> {
|
||||
/// # use ratatui::{prelude::*, widgets::*};
|
||||
/// # let rows = [Row::new(vec!["Cell1", "Cell2"])];
|
||||
/// # let widths = [Constraint::Length(5), Constraint::Length(5)];
|
||||
/// let block = Block::bordered().title("Table");
|
||||
/// let block = Block::default().title("Table").borders(Borders::ALL);
|
||||
/// let table = Table::new(rows, widths).block(block);
|
||||
/// ```
|
||||
#[must_use = "method moves the value of self and returns the modified value"]
|
||||
@@ -842,7 +842,7 @@ mod tests {
|
||||
use std::vec;
|
||||
|
||||
use super::*;
|
||||
use crate::{layout::Constraint::*, style::Style, text::Line};
|
||||
use crate::{layout::Constraint::*, style::Style, text::Line, widgets::Borders};
|
||||
|
||||
#[test]
|
||||
fn new() {
|
||||
@@ -930,7 +930,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn block() {
|
||||
let block = Block::bordered().title("Table");
|
||||
let block = Block::default().title("Table").borders(Borders::ALL);
|
||||
let table = Table::default().block(block.clone());
|
||||
assert_eq!(table.block, Some(block));
|
||||
}
|
||||
@@ -1027,7 +1027,7 @@ mod tests {
|
||||
Row::new(vec!["Cell1", "Cell2"]),
|
||||
Row::new(vec!["Cell3", "Cell4"]),
|
||||
];
|
||||
let block = Block::bordered().title("Block");
|
||||
let block = Block::new().borders(Borders::ALL).title("Block");
|
||||
let table = Table::new(rows, vec![Constraint::Length(5); 2]).block(block);
|
||||
Widget::render(table, Rect::new(0, 0, 15, 3), &mut buf);
|
||||
let expected = Buffer::with_lines(vec![
|
||||
|
||||
@@ -60,11 +60,8 @@ impl TableState {
|
||||
/// # use ratatui::{prelude::*, widgets::*};
|
||||
/// let state = TableState::new();
|
||||
/// ```
|
||||
pub const fn new() -> Self {
|
||||
Self {
|
||||
offset: 0,
|
||||
selected: None,
|
||||
}
|
||||
pub fn new() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
|
||||
/// Sets the index of the first row to be displayed
|
||||
|
||||
@@ -17,7 +17,7 @@ const DEFAULT_HIGHLIGHT_STYLE: Style = Style::new().add_modifier(Modifier::REVER
|
||||
/// use ratatui::{prelude::*, widgets::*};
|
||||
///
|
||||
/// Tabs::new(vec!["Tab1", "Tab2", "Tab3", "Tab4"])
|
||||
/// .block(Block::bordered().title("Tabs"))
|
||||
/// .block(Block::default().title("Tabs").borders(Borders::ALL))
|
||||
/// .style(Style::default().white())
|
||||
/// .highlight_style(Style::default().yellow())
|
||||
/// .select(2)
|
||||
@@ -333,7 +333,7 @@ where
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::assert_buffer_eq;
|
||||
use crate::{assert_buffer_eq, widgets::Borders};
|
||||
|
||||
#[test]
|
||||
fn new() {
|
||||
@@ -414,8 +414,8 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn render_with_block() {
|
||||
let tabs =
|
||||
Tabs::new(vec!["Tab1", "Tab2", "Tab3", "Tab4"]).block(Block::bordered().title("Tabs"));
|
||||
let tabs = Tabs::new(vec!["Tab1", "Tab2", "Tab3", "Tab4"])
|
||||
.block(Block::default().title("Tabs").borders(Borders::ALL));
|
||||
let mut expected = Buffer::with_lines(vec![
|
||||
"┌Tabs────────────────────────┐",
|
||||
"│ Tab1 │ Tab2 │ Tab3 │ Tab4 │",
|
||||
|
||||
@@ -62,7 +62,7 @@ fn assert_buffer(state: &mut AppState, expected: &Buffer) {
|
||||
.split(f.size());
|
||||
let list = List::new(items)
|
||||
.highlight_symbol(">>")
|
||||
.block(Block::new().borders(Borders::RIGHT));
|
||||
.block(Block::default().borders(Borders::RIGHT));
|
||||
f.render_stateful_widget(list, layout[0], &mut state.list);
|
||||
|
||||
let table = Table::new(
|
||||
|
||||
@@ -5,7 +5,7 @@ use ratatui::{
|
||||
buffer::Buffer,
|
||||
layout::Rect,
|
||||
style::{Color, Style, Stylize},
|
||||
widgets::{BarChart, Block, Paragraph},
|
||||
widgets::{BarChart, Block, Borders, Paragraph},
|
||||
Terminal,
|
||||
};
|
||||
|
||||
@@ -61,10 +61,11 @@ fn barchart_can_be_stylized() {
|
||||
|
||||
#[test]
|
||||
fn block_can_be_stylized() -> io::Result<()> {
|
||||
let block = Block::bordered()
|
||||
let block = Block::default()
|
||||
.title("Title".light_blue())
|
||||
.on_cyan()
|
||||
.cyan();
|
||||
.cyan()
|
||||
.borders(Borders::ALL);
|
||||
|
||||
let area = Rect::new(0, 0, 8, 3);
|
||||
let mut terminal = Terminal::new(TestBackend::new(11, 4))?;
|
||||
|
||||
@@ -2,7 +2,7 @@ use ratatui::{
|
||||
backend::TestBackend,
|
||||
buffer::Buffer,
|
||||
style::{Color, Style},
|
||||
widgets::{Bar, BarChart, BarGroup, Block},
|
||||
widgets::{Bar, BarChart, BarGroup, Block, Borders},
|
||||
Terminal,
|
||||
};
|
||||
|
||||
@@ -16,7 +16,7 @@ fn widgets_barchart_not_full_below_max_value() {
|
||||
.draw(|f| {
|
||||
let size = f.size();
|
||||
let barchart = BarChart::default()
|
||||
.block(Block::bordered())
|
||||
.block(Block::default().borders(Borders::ALL))
|
||||
.data(&[("empty", 0), ("half", 50), ("almost", 99), ("full", 100)])
|
||||
.max(100)
|
||||
.bar_width(7)
|
||||
@@ -53,7 +53,7 @@ fn widgets_barchart_group() {
|
||||
.draw(|f| {
|
||||
let size = f.size();
|
||||
let barchart = BarChart::default()
|
||||
.block(Block::bordered())
|
||||
.block(Block::default().borders(Borders::ALL))
|
||||
.data(
|
||||
BarGroup::default().label("Mar".into()).bars(&[
|
||||
Bar::default()
|
||||
|
||||
@@ -15,8 +15,9 @@ use ratatui::{
|
||||
fn widgets_block_renders() {
|
||||
let backend = TestBackend::new(10, 10);
|
||||
let mut terminal = Terminal::new(backend).unwrap();
|
||||
let block =
|
||||
Block::bordered().title(Span::styled("Title", Style::default().fg(Color::LightBlue)));
|
||||
let block = Block::default()
|
||||
.title(Span::styled("Title", Style::default().fg(Color::LightBlue)))
|
||||
.borders(Borders::ALL);
|
||||
terminal
|
||||
.draw(|frame| frame.render_widget(block, Rect::new(0, 0, 8, 8)))
|
||||
.unwrap();
|
||||
@@ -53,7 +54,7 @@ fn widgets_block_titles_overlap() {
|
||||
|
||||
// Left overrides the center
|
||||
test_case(
|
||||
Block::new()
|
||||
Block::default()
|
||||
.title(Title::from("aaaaa").alignment(Alignment::Left))
|
||||
.title(Title::from("bbb").alignment(Alignment::Center))
|
||||
.title(Title::from("ccc").alignment(Alignment::Right)),
|
||||
@@ -63,7 +64,7 @@ fn widgets_block_titles_overlap() {
|
||||
|
||||
// Left alignment overrides the center alignment which overrides the right alignment
|
||||
test_case(
|
||||
Block::new()
|
||||
Block::default()
|
||||
.title(Title::from("aaaaa").alignment(Alignment::Left))
|
||||
.title(Title::from("bbbbb").alignment(Alignment::Center))
|
||||
.title(Title::from("ccccc").alignment(Alignment::Right)),
|
||||
@@ -73,7 +74,7 @@ fn widgets_block_titles_overlap() {
|
||||
|
||||
// Multiple left alignment overrides the center alignment and the right alignment
|
||||
test_case(
|
||||
Block::new()
|
||||
Block::default()
|
||||
.title(Title::from("aaaaa").alignment(Alignment::Left))
|
||||
.title(Title::from("aaaaa").alignment(Alignment::Left))
|
||||
.title(Title::from("bbbbb").alignment(Alignment::Center))
|
||||
@@ -84,7 +85,7 @@ fn widgets_block_titles_overlap() {
|
||||
|
||||
// The right alignment doesn't override the center alignment, but pierces through it
|
||||
test_case(
|
||||
Block::new()
|
||||
Block::default()
|
||||
.title(Title::from("bbbbb").alignment(Alignment::Center))
|
||||
.title(Title::from("ccccccccccc").alignment(Alignment::Right)),
|
||||
Rect::new(0, 0, 11, 1),
|
||||
@@ -115,69 +116,69 @@ fn widgets_block_renders_on_small_areas() {
|
||||
];
|
||||
for (borders, symbol) in one_cell_test_cases {
|
||||
test_case(
|
||||
Block::new().borders(borders).title("Test"),
|
||||
Block::default().title("Test").borders(borders),
|
||||
Rect::new(0, 0, 0, 0),
|
||||
Buffer::empty(Rect::new(0, 0, 0, 0)),
|
||||
);
|
||||
test_case(
|
||||
Block::new().borders(borders).title("Test"),
|
||||
Block::default().title("Test").borders(borders),
|
||||
Rect::new(0, 0, 1, 0),
|
||||
Buffer::empty(Rect::new(0, 0, 1, 0)),
|
||||
);
|
||||
test_case(
|
||||
Block::new().borders(borders).title("Test"),
|
||||
Block::default().title("Test").borders(borders),
|
||||
Rect::new(0, 0, 0, 1),
|
||||
Buffer::empty(Rect::new(0, 0, 0, 1)),
|
||||
);
|
||||
test_case(
|
||||
Block::new().borders(borders).title("Test"),
|
||||
Block::default().title("Test").borders(borders),
|
||||
Rect::new(0, 0, 1, 1),
|
||||
Buffer::with_lines(vec![symbol]),
|
||||
);
|
||||
}
|
||||
test_case(
|
||||
Block::new().borders(Borders::LEFT).title("Test"),
|
||||
Block::default().title("Test").borders(Borders::LEFT),
|
||||
Rect::new(0, 0, 4, 1),
|
||||
Buffer::with_lines(vec!["│Tes"]),
|
||||
);
|
||||
test_case(
|
||||
Block::new().borders(Borders::RIGHT).title("Test"),
|
||||
Block::default().title("Test").borders(Borders::RIGHT),
|
||||
Rect::new(0, 0, 4, 1),
|
||||
Buffer::with_lines(vec!["Tes│"]),
|
||||
);
|
||||
test_case(
|
||||
Block::new().borders(Borders::RIGHT).title("Test"),
|
||||
Block::default().title("Test").borders(Borders::RIGHT),
|
||||
Rect::new(0, 0, 4, 1),
|
||||
Buffer::with_lines(vec!["Tes│"]),
|
||||
);
|
||||
test_case(
|
||||
Block::new()
|
||||
.borders(Borders::LEFT | Borders::RIGHT)
|
||||
.title("Test"),
|
||||
Block::default()
|
||||
.title("Test")
|
||||
.borders(Borders::LEFT | Borders::RIGHT),
|
||||
Rect::new(0, 0, 4, 1),
|
||||
Buffer::with_lines(vec!["│Te│"]),
|
||||
);
|
||||
test_case(
|
||||
Block::new().borders(Borders::TOP).title("Test"),
|
||||
Block::default().title("Test").borders(Borders::TOP),
|
||||
Rect::new(0, 0, 4, 1),
|
||||
Buffer::with_lines(vec!["Test"]),
|
||||
);
|
||||
test_case(
|
||||
Block::new().borders(Borders::TOP).title("Test"),
|
||||
Block::default().title("Test").borders(Borders::TOP),
|
||||
Rect::new(0, 0, 5, 1),
|
||||
Buffer::with_lines(vec!["Test─"]),
|
||||
);
|
||||
test_case(
|
||||
Block::new()
|
||||
.borders(Borders::LEFT | Borders::TOP)
|
||||
.title("Test"),
|
||||
Block::default()
|
||||
.title("Test")
|
||||
.borders(Borders::LEFT | Borders::TOP),
|
||||
Rect::new(0, 0, 5, 1),
|
||||
Buffer::with_lines(vec!["┌Test"]),
|
||||
);
|
||||
test_case(
|
||||
Block::new()
|
||||
.borders(Borders::LEFT | Borders::TOP)
|
||||
.title("Test"),
|
||||
Block::default()
|
||||
.title("Test")
|
||||
.borders(Borders::LEFT | Borders::TOP),
|
||||
Rect::new(0, 0, 6, 1),
|
||||
Buffer::with_lines(vec!["┌Test─"]),
|
||||
);
|
||||
@@ -192,14 +193,14 @@ fn widgets_block_title_alignment() {
|
||||
let backend = TestBackend::new(15, 3);
|
||||
let mut terminal = Terminal::new(backend).unwrap();
|
||||
|
||||
let block1 = Block::new()
|
||||
.borders(borders)
|
||||
.title(Title::from(Span::styled("Title", Style::default())).alignment(alignment));
|
||||
let block1 = Block::default()
|
||||
.title(Title::from(Span::styled("Title", Style::default())).alignment(alignment))
|
||||
.borders(borders);
|
||||
|
||||
let block2 = Block::new()
|
||||
.borders(borders)
|
||||
let block2 = Block::default()
|
||||
.title("Title")
|
||||
.title_alignment(alignment)
|
||||
.title("Title");
|
||||
.borders(borders);
|
||||
|
||||
let area = Rect::new(1, 0, 13, 3);
|
||||
|
||||
@@ -389,7 +390,7 @@ fn widgets_block_title_alignment_bottom() {
|
||||
let title = Title::from(Span::styled("Title", Style::default()))
|
||||
.alignment(alignment)
|
||||
.position(Position::Bottom);
|
||||
let block = Block::new().borders(borders).title(title);
|
||||
let block = Block::default().title(title).borders(borders);
|
||||
let area = Rect::new(1, 0, 13, 3);
|
||||
terminal
|
||||
.draw(|frame| frame.render_widget(block, area))
|
||||
@@ -572,7 +573,10 @@ fn widgets_block_multiple_titles() {
|
||||
let backend = TestBackend::new(15, 3);
|
||||
let mut terminal = Terminal::new(backend).unwrap();
|
||||
|
||||
let block = Block::new().borders(borders).title(title_a).title(title_b);
|
||||
let block = Block::default()
|
||||
.title(title_a)
|
||||
.title(title_b)
|
||||
.borders(borders);
|
||||
|
||||
let area = Rect::new(1, 0, 13, 3);
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ use ratatui::{
|
||||
style::{Color, Style},
|
||||
symbols,
|
||||
text::{self, Span},
|
||||
widgets::{Axis, Block, Chart, Dataset, GraphType::Line},
|
||||
widgets::{Axis, Block, Borders, Chart, Dataset, GraphType::Line},
|
||||
Terminal,
|
||||
};
|
||||
use rstest::rstest;
|
||||
@@ -46,7 +46,7 @@ fn widgets_chart_can_render_on_small_areas(#[case] width: u16, #[case] height: u
|
||||
.style(Style::default().fg(Color::Magenta))
|
||||
.data(&[(0.0, 0.0)])];
|
||||
let chart = Chart::new(datasets)
|
||||
.block(Block::bordered().title("Plot"))
|
||||
.block(Block::default().title("Plot").borders(Borders::ALL))
|
||||
.x_axis(
|
||||
Axis::default()
|
||||
.bounds([0.0, 0.0])
|
||||
@@ -265,7 +265,7 @@ fn widgets_chart_can_have_axis_with_zero_length_bounds() {
|
||||
.style(Style::default().fg(Color::Magenta))
|
||||
.data(&[(0.0, 0.0)])];
|
||||
let chart = Chart::new(datasets)
|
||||
.block(Block::bordered().title("Plot"))
|
||||
.block(Block::default().title("Plot").borders(Borders::ALL))
|
||||
.x_axis(
|
||||
Axis::default()
|
||||
.bounds([0.0, 0.0])
|
||||
@@ -305,7 +305,7 @@ fn widgets_chart_handles_overflows() {
|
||||
(1_588_298_496.0, 1.0),
|
||||
])];
|
||||
let chart = Chart::new(datasets)
|
||||
.block(Block::bordered().title("Plot"))
|
||||
.block(Block::default().title("Plot").borders(Borders::ALL))
|
||||
.x_axis(
|
||||
Axis::default()
|
||||
.bounds([1_588_298_471.0, 1_588_992_600.0])
|
||||
@@ -338,7 +338,11 @@ fn widgets_chart_can_have_empty_datasets() {
|
||||
.draw(|f| {
|
||||
let datasets = vec![Dataset::default().data(&[]).graph_type(Line)];
|
||||
let chart = Chart::new(datasets)
|
||||
.block(Block::bordered().title("Empty Dataset With Line"))
|
||||
.block(
|
||||
Block::default()
|
||||
.title("Empty Dataset With Line")
|
||||
.borders(Borders::ALL),
|
||||
)
|
||||
.x_axis(
|
||||
Axis::default()
|
||||
.bounds([0.0, 0.0])
|
||||
@@ -407,7 +411,7 @@ fn widgets_chart_can_have_a_legend() {
|
||||
];
|
||||
let chart = Chart::new(datasets)
|
||||
.style(Style::default().bg(Color::White))
|
||||
.block(Block::bordered().title("Chart Test"))
|
||||
.block(Block::default().title("Chart Test").borders(Borders::ALL))
|
||||
.x_axis(
|
||||
Axis::default()
|
||||
.bounds([0.0, 100.0])
|
||||
|
||||
@@ -5,7 +5,7 @@ use ratatui::{
|
||||
style::{Color, Modifier, Style, Stylize},
|
||||
symbols,
|
||||
text::Span,
|
||||
widgets::{Block, Gauge, LineGauge},
|
||||
widgets::{Block, Borders, Gauge, LineGauge},
|
||||
Terminal,
|
||||
};
|
||||
|
||||
@@ -22,13 +22,13 @@ fn widgets_gauge_renders() {
|
||||
.split(f.size());
|
||||
|
||||
let gauge = Gauge::default()
|
||||
.block(Block::bordered().title("Percentage"))
|
||||
.block(Block::default().title("Percentage").borders(Borders::ALL))
|
||||
.gauge_style(Style::default().bg(Color::Blue).fg(Color::Red))
|
||||
.use_unicode(true)
|
||||
.percent(43);
|
||||
f.render_widget(gauge, chunks[0]);
|
||||
let gauge = Gauge::default()
|
||||
.block(Block::bordered().title("Ratio"))
|
||||
.block(Block::default().title("Ratio").borders(Borders::ALL))
|
||||
.gauge_style(Style::default().bg(Color::Blue).fg(Color::Red))
|
||||
.use_unicode(true)
|
||||
.ratio(0.511_313_934_313_1);
|
||||
@@ -71,12 +71,12 @@ fn widgets_gauge_renders_no_unicode() {
|
||||
.split(f.size());
|
||||
|
||||
let gauge = Gauge::default()
|
||||
.block(Block::bordered().title("Percentage"))
|
||||
.block(Block::default().title("Percentage").borders(Borders::ALL))
|
||||
.percent(43)
|
||||
.use_unicode(false);
|
||||
f.render_widget(gauge, chunks[0]);
|
||||
let gauge = Gauge::default()
|
||||
.block(Block::bordered().title("Ratio"))
|
||||
.block(Block::default().title("Ratio").borders(Borders::ALL))
|
||||
.ratio(0.211_313_934_313_1)
|
||||
.use_unicode(false);
|
||||
f.render_widget(gauge, chunks[1]);
|
||||
@@ -106,7 +106,9 @@ fn widgets_gauge_applies_styles() {
|
||||
.draw(|f| {
|
||||
let gauge = Gauge::default()
|
||||
.block(
|
||||
Block::bordered().title(Span::styled("Test", Style::default().fg(Color::Red))),
|
||||
Block::default()
|
||||
.title(Span::styled("Test", Style::default().fg(Color::Red)))
|
||||
.borders(Borders::ALL),
|
||||
)
|
||||
.gauge_style(Style::default().fg(Color::Blue).bg(Color::Red))
|
||||
.percent(43)
|
||||
@@ -194,7 +196,7 @@ fn widgets_line_gauge_renders() {
|
||||
},
|
||||
);
|
||||
let gauge = LineGauge::default()
|
||||
.block(Block::bordered().title("Gauge 2"))
|
||||
.block(Block::default().title("Gauge 2").borders(Borders::ALL))
|
||||
.gauge_style(Style::default().fg(Color::Green))
|
||||
.line_set(symbols::line::THICK)
|
||||
.ratio(0.211_313_934_313_1);
|
||||
|
||||
@@ -127,7 +127,7 @@ fn widgets_list_should_truncate_items() {
|
||||
terminal
|
||||
.draw(|f| {
|
||||
let list = List::new(case.items.clone())
|
||||
.block(Block::new().borders(Borders::RIGHT))
|
||||
.block(Block::default().borders(Borders::RIGHT))
|
||||
.highlight_symbol(">> ");
|
||||
f.render_stateful_widget(list, Rect::new(0, 0, 8, 2), &mut state);
|
||||
})
|
||||
@@ -288,7 +288,7 @@ fn widgets_list_enable_always_highlight_spacing() {
|
||||
ListItem::new(vec![Line::from("Item 2"), Line::from("Item 2b")]),
|
||||
ListItem::new(vec![Line::from("Item 3"), Line::from("Item 3c")]),
|
||||
])
|
||||
.block(Block::bordered())
|
||||
.block(Block::default().borders(Borders::ALL))
|
||||
.highlight_symbol(">> ")
|
||||
.highlight_spacing(space);
|
||||
f.render_stateful_widget(table, size, state);
|
||||
|
||||
@@ -3,7 +3,7 @@ use ratatui::{
|
||||
buffer::Buffer,
|
||||
layout::Alignment,
|
||||
text::{Line, Span, Text},
|
||||
widgets::{Block, Padding, Paragraph, Wrap},
|
||||
widgets::{Block, Borders, Padding, Paragraph, Wrap},
|
||||
Terminal,
|
||||
};
|
||||
|
||||
@@ -30,7 +30,7 @@ fn widgets_paragraph_renders_double_width_graphemes() {
|
||||
|
||||
let text = vec![Line::from(s)];
|
||||
let paragraph = Paragraph::new(text)
|
||||
.block(Block::bordered())
|
||||
.block(Block::default().borders(Borders::ALL))
|
||||
.wrap(Wrap { trim: true });
|
||||
|
||||
test_case(
|
||||
@@ -61,7 +61,7 @@ fn widgets_paragraph_renders_mixed_width_graphemes() {
|
||||
let size = f.size();
|
||||
let text = vec![Line::from(s)];
|
||||
let paragraph = Paragraph::new(text)
|
||||
.block(Block::bordered())
|
||||
.block(Block::default().borders(Borders::ALL))
|
||||
.wrap(Wrap { trim: true });
|
||||
f.render_widget(paragraph, size);
|
||||
})
|
||||
@@ -84,7 +84,7 @@ fn widgets_paragraph_renders_mixed_width_graphemes() {
|
||||
fn widgets_paragraph_can_wrap_with_a_trailing_nbsp() {
|
||||
let nbsp = "\u{00a0}";
|
||||
let line = Line::from(vec![Span::raw("NBSP"), Span::raw(nbsp)]);
|
||||
let paragraph = Paragraph::new(line).block(Block::bordered());
|
||||
let paragraph = Paragraph::new(line).block(Block::default().borders(Borders::ALL));
|
||||
|
||||
test_case(
|
||||
paragraph,
|
||||
@@ -99,8 +99,8 @@ fn widgets_paragraph_can_wrap_with_a_trailing_nbsp() {
|
||||
#[test]
|
||||
fn widgets_paragraph_can_scroll_horizontally() {
|
||||
let text =
|
||||
Text::from("段落现在可以水平滚动了!\nParagraph can scroll horizontally!\nLittle line");
|
||||
let paragraph = Paragraph::new(text).block(Block::bordered());
|
||||
Text::from("段落现在可以水平滚动了!\nParagraph can scroll horizontally!\nShort line");
|
||||
let paragraph = Paragraph::new(text).block(Block::default().borders(Borders::ALL));
|
||||
|
||||
test_case(
|
||||
paragraph.clone().alignment(Alignment::Left).scroll((0, 7)),
|
||||
@@ -108,7 +108,7 @@ fn widgets_paragraph_can_scroll_horizontally() {
|
||||
"┌──────────────────┐",
|
||||
"│在可以水平滚动了!│",
|
||||
"│ph can scroll hori│",
|
||||
"│line │",
|
||||
"│ine │",
|
||||
"│ │",
|
||||
"│ │",
|
||||
"│ │",
|
||||
@@ -124,7 +124,7 @@ fn widgets_paragraph_can_scroll_horizontally() {
|
||||
"┌──────────────────┐",
|
||||
"│段落现在可以水平滚│",
|
||||
"│Paragraph can scro│",
|
||||
"│ Little line│",
|
||||
"│ Short line│",
|
||||
"│ │",
|
||||
"│ │",
|
||||
"│ │",
|
||||
@@ -144,7 +144,7 @@ const SAMPLE_STRING: &str = "The library is based on the principle of immediate
|
||||
fn widgets_paragraph_can_wrap_its_content() {
|
||||
let text = vec![Line::from(SAMPLE_STRING)];
|
||||
let paragraph = Paragraph::new(text)
|
||||
.block(Block::bordered())
|
||||
.block(Block::default().borders(Borders::ALL))
|
||||
.wrap(Wrap { trim: true });
|
||||
|
||||
test_case(
|
||||
@@ -196,14 +196,14 @@ fn widgets_paragraph_can_wrap_its_content() {
|
||||
|
||||
#[test]
|
||||
fn widgets_paragraph_works_with_padding() {
|
||||
let block = Block::bordered().padding(Padding {
|
||||
left: 2,
|
||||
right: 2,
|
||||
top: 1,
|
||||
bottom: 1,
|
||||
});
|
||||
let paragraph = Paragraph::new(vec![Line::from(SAMPLE_STRING)])
|
||||
.block(block.clone())
|
||||
let text = vec![Line::from(SAMPLE_STRING)];
|
||||
let paragraph = Paragraph::new(text)
|
||||
.block(Block::default().borders(Borders::ALL).padding(Padding {
|
||||
left: 2,
|
||||
right: 2,
|
||||
top: 1,
|
||||
bottom: 1,
|
||||
}))
|
||||
.wrap(Wrap { trim: true });
|
||||
|
||||
test_case(
|
||||
@@ -224,7 +224,7 @@ fn widgets_paragraph_works_with_padding() {
|
||||
]),
|
||||
);
|
||||
test_case(
|
||||
paragraph.alignment(Alignment::Right),
|
||||
paragraph.clone().alignment(Alignment::Right),
|
||||
Buffer::with_lines(vec![
|
||||
"┌────────────────────┐",
|
||||
"│ │",
|
||||
@@ -241,12 +241,16 @@ fn widgets_paragraph_works_with_padding() {
|
||||
]),
|
||||
);
|
||||
|
||||
let paragraph = Paragraph::new(vec![
|
||||
Line::from("This is always centered.").alignment(Alignment::Center),
|
||||
Line::from(SAMPLE_STRING),
|
||||
])
|
||||
.block(block)
|
||||
.wrap(Wrap { trim: true });
|
||||
let mut text = vec![Line::from("This is always centered.").alignment(Alignment::Center)];
|
||||
text.push(Line::from(SAMPLE_STRING));
|
||||
let paragraph = Paragraph::new(text)
|
||||
.block(Block::default().borders(Borders::ALL).padding(Padding {
|
||||
left: 2,
|
||||
right: 2,
|
||||
top: 1,
|
||||
bottom: 1,
|
||||
}))
|
||||
.wrap(Wrap { trim: true });
|
||||
|
||||
test_case(
|
||||
paragraph.alignment(Alignment::Right),
|
||||
@@ -279,7 +283,7 @@ fn widgets_paragraph_can_align_spans() {
|
||||
Line::from(default_s),
|
||||
];
|
||||
let paragraph = Paragraph::new(text)
|
||||
.block(Block::bordered())
|
||||
.block(Block::default().borders(Borders::ALL))
|
||||
.wrap(Wrap { trim: true });
|
||||
|
||||
test_case(
|
||||
@@ -329,7 +333,7 @@ fn widgets_paragraph_can_align_spans() {
|
||||
|
||||
let mut text = left_lines.clone();
|
||||
text.append(&mut lines);
|
||||
let paragraph = Paragraph::new(text).block(Block::bordered());
|
||||
let paragraph = Paragraph::new(text).block(Block::default().borders(Borders::ALL));
|
||||
|
||||
test_case(
|
||||
paragraph.clone().alignment(Alignment::Right),
|
||||
|
||||
@@ -33,7 +33,7 @@ fn widgets_table_column_spacing_can_be_changed() {
|
||||
],
|
||||
)
|
||||
.header(Row::new(vec!["Head1", "Head2", "Head3"]).bottom_margin(1))
|
||||
.block(Block::bordered())
|
||||
.block(Block::default().borders(Borders::ALL))
|
||||
.column_spacing(column_spacing);
|
||||
f.render_widget(table, size);
|
||||
})
|
||||
@@ -129,7 +129,7 @@ fn widgets_table_columns_widths_can_use_fixed_length_constraints() {
|
||||
widths,
|
||||
)
|
||||
.header(Row::new(vec!["Head1", "Head2", "Head3"]).bottom_margin(1))
|
||||
.block(Block::bordered());
|
||||
.block(Block::default().borders(Borders::ALL));
|
||||
f.render_widget(table, size);
|
||||
})
|
||||
.unwrap();
|
||||
@@ -221,7 +221,7 @@ fn widgets_table_columns_widths_can_use_percentage_constraints() {
|
||||
widths,
|
||||
)
|
||||
.header(Row::new(vec!["Head1", "Head2", "Head3"]).bottom_margin(1))
|
||||
.block(Block::bordered())
|
||||
.block(Block::default().borders(Borders::ALL))
|
||||
.column_spacing(0);
|
||||
f.render_widget(table, size);
|
||||
})
|
||||
@@ -331,7 +331,7 @@ fn widgets_table_columns_widths_can_use_mixed_constraints() {
|
||||
widths,
|
||||
)
|
||||
.header(Row::new(vec!["Head1", "Head2", "Head3"]).bottom_margin(1))
|
||||
.block(Block::bordered());
|
||||
.block(Block::default().borders(Borders::ALL));
|
||||
f.render_widget(table, size);
|
||||
})
|
||||
.unwrap();
|
||||
@@ -444,7 +444,7 @@ fn widgets_table_columns_widths_can_use_ratio_constraints() {
|
||||
widths,
|
||||
)
|
||||
.header(Row::new(vec!["Head1", "Head2", "Head3"]).bottom_margin(1))
|
||||
.block(Block::bordered())
|
||||
.block(Block::default().borders(Borders::ALL))
|
||||
.column_spacing(0);
|
||||
f.render_widget(table, size);
|
||||
})
|
||||
@@ -555,7 +555,7 @@ fn widgets_table_can_have_rows_with_multi_lines() {
|
||||
],
|
||||
)
|
||||
.header(Row::new(vec!["Head1", "Head2", "Head3"]).bottom_margin(1))
|
||||
.block(Block::bordered())
|
||||
.block(Block::default().borders(Borders::ALL))
|
||||
.highlight_symbol(">> ")
|
||||
.column_spacing(1);
|
||||
f.render_stateful_widget(table, size, state);
|
||||
@@ -652,7 +652,7 @@ fn widgets_table_enable_always_highlight_spacing() {
|
||||
],
|
||||
)
|
||||
.header(Row::new(vec!["Head1", "Head2", "Head3"]).bottom_margin(1))
|
||||
.block(Block::bordered())
|
||||
.block(Block::default().borders(Borders::ALL))
|
||||
.highlight_symbol(">> ")
|
||||
.highlight_spacing(space)
|
||||
.column_spacing(1);
|
||||
@@ -796,7 +796,7 @@ fn widgets_table_can_have_elements_styled_individually() {
|
||||
],
|
||||
)
|
||||
.header(Row::new(vec!["Head1", "Head2", "Head3"]).bottom_margin(1))
|
||||
.block(Block::new().borders(Borders::LEFT | Borders::RIGHT))
|
||||
.block(Block::default().borders(Borders::LEFT | Borders::RIGHT))
|
||||
.highlight_symbol(">> ")
|
||||
.highlight_style(Style::default().add_modifier(Modifier::BOLD))
|
||||
.column_spacing(1);
|
||||
@@ -861,7 +861,7 @@ fn widgets_table_should_render_even_if_empty() {
|
||||
],
|
||||
)
|
||||
.header(Row::new(vec!["Head1", "Head2", "Head3"]))
|
||||
.block(Block::new().borders(Borders::LEFT | Borders::RIGHT))
|
||||
.block(Block::default().borders(Borders::LEFT | Borders::RIGHT))
|
||||
.column_spacing(1);
|
||||
f.render_widget(table, size);
|
||||
})
|
||||
@@ -902,7 +902,7 @@ fn widgets_table_columns_dont_panic() {
|
||||
],
|
||||
)
|
||||
.header(Row::new(vec!["h1", "h2", "h3", "h4"]))
|
||||
.block(Block::bordered())
|
||||
.block(Block::default().borders(Borders::ALL))
|
||||
.highlight_symbol(">> ")
|
||||
.column_spacing(1);
|
||||
|
||||
@@ -940,7 +940,7 @@ fn widgets_table_should_clamp_offset_if_rows_are_removed() {
|
||||
],
|
||||
)
|
||||
.header(Row::new(vec!["Head1", "Head2", "Head3"]).bottom_margin(1))
|
||||
.block(Block::bordered())
|
||||
.block(Block::default().borders(Borders::ALL))
|
||||
.column_spacing(1);
|
||||
f.render_stateful_widget(table, size, &mut state);
|
||||
})
|
||||
@@ -971,7 +971,7 @@ fn widgets_table_should_clamp_offset_if_rows_are_removed() {
|
||||
],
|
||||
)
|
||||
.header(Row::new(vec!["Head1", "Head2", "Head3"]).bottom_margin(1))
|
||||
.block(Block::bordered())
|
||||
.block(Block::default().borders(Borders::ALL))
|
||||
.column_spacing(1);
|
||||
f.render_stateful_widget(table, size, &mut state);
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user