@akiojin/gwt 9.0.4 → 9.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.ja.md +106 -146
- package/README.md +103 -143
- package/bin/gwt.cjs +1 -1
- package/package.json +5 -5
- package/rustfmt.toml +0 -2
- package/scripts/check-release-flow.sh +2 -8
- package/scripts/postinstall.js +17 -7
- package/scripts/run-local-backend-tests-on-commit.sh +6 -12
- package/scripts/test-all.sh +1 -5
- package/scripts/check-e2e-coverage-threshold.mjs +0 -238
- package/scripts/run-local-e2e-coverage-on-commit.sh +0 -69
- package/scripts/run-local-e2e-on-commit.sh +0 -60
- package/scripts/verify-ci-node-toolchain.sh +0 -76
- package/scripts/voice-eval.sh +0 -48
- package/vendor/ratatui-core/src/backend/test.rs +0 -1077
- package/vendor/ratatui-core/src/backend.rs +0 -405
- package/vendor/ratatui-core/src/buffer/assert.rs +0 -71
- package/vendor/ratatui-core/src/buffer/buffer.rs +0 -1388
- package/vendor/ratatui-core/src/buffer/cell.rs +0 -377
- package/vendor/ratatui-core/src/buffer.rs +0 -9
- package/vendor/ratatui-core/src/layout/alignment.rs +0 -89
- package/vendor/ratatui-core/src/layout/constraint.rs +0 -526
- package/vendor/ratatui-core/src/layout/direction.rs +0 -63
- package/vendor/ratatui-core/src/layout/flex.rs +0 -212
- package/vendor/ratatui-core/src/layout/layout.rs +0 -2838
- package/vendor/ratatui-core/src/layout/margin.rs +0 -79
- package/vendor/ratatui-core/src/layout/offset.rs +0 -66
- package/vendor/ratatui-core/src/layout/position.rs +0 -253
- package/vendor/ratatui-core/src/layout/rect/iter.rs +0 -356
- package/vendor/ratatui-core/src/layout/rect/ops.rs +0 -136
- package/vendor/ratatui-core/src/layout/rect.rs +0 -1114
- package/vendor/ratatui-core/src/layout/size.rs +0 -147
- package/vendor/ratatui-core/src/layout.rs +0 -333
- package/vendor/ratatui-core/src/lib.rs +0 -82
- package/vendor/ratatui-core/src/style/anstyle.rs +0 -348
- package/vendor/ratatui-core/src/style/color.rs +0 -788
- package/vendor/ratatui-core/src/style/palette/material.rs +0 -608
- package/vendor/ratatui-core/src/style/palette/tailwind.rs +0 -653
- package/vendor/ratatui-core/src/style/palette.rs +0 -6
- package/vendor/ratatui-core/src/style/palette_conversion.rs +0 -82
- package/vendor/ratatui-core/src/style/stylize.rs +0 -668
- package/vendor/ratatui-core/src/style.rs +0 -1069
- package/vendor/ratatui-core/src/symbols/bar.rs +0 -51
- package/vendor/ratatui-core/src/symbols/block.rs +0 -51
- package/vendor/ratatui-core/src/symbols/border.rs +0 -709
- package/vendor/ratatui-core/src/symbols/braille.rs +0 -21
- package/vendor/ratatui-core/src/symbols/half_block.rs +0 -3
- package/vendor/ratatui-core/src/symbols/line.rs +0 -259
- package/vendor/ratatui-core/src/symbols/marker.rs +0 -82
- package/vendor/ratatui-core/src/symbols/merge.rs +0 -748
- package/vendor/ratatui-core/src/symbols/pixel.rs +0 -30
- package/vendor/ratatui-core/src/symbols/scrollbar.rs +0 -46
- package/vendor/ratatui-core/src/symbols/shade.rs +0 -5
- package/vendor/ratatui-core/src/symbols.rs +0 -15
- package/vendor/ratatui-core/src/terminal/frame.rs +0 -192
- package/vendor/ratatui-core/src/terminal/terminal.rs +0 -926
- package/vendor/ratatui-core/src/terminal/viewport.rs +0 -58
- package/vendor/ratatui-core/src/terminal.rs +0 -40
- package/vendor/ratatui-core/src/text/grapheme.rs +0 -84
- package/vendor/ratatui-core/src/text/line.rs +0 -1678
- package/vendor/ratatui-core/src/text/masked.rs +0 -149
- package/vendor/ratatui-core/src/text/span.rs +0 -904
- package/vendor/ratatui-core/src/text/text.rs +0 -1434
- package/vendor/ratatui-core/src/text.rs +0 -64
- package/vendor/ratatui-core/src/widgets/stateful_widget.rs +0 -193
- package/vendor/ratatui-core/src/widgets/widget.rs +0 -174
- package/vendor/ratatui-core/src/widgets.rs +0 -9
|
@@ -1,1434 +0,0 @@
|
|
|
1
|
-
#![warn(missing_docs)]
|
|
2
|
-
use alloc::borrow::{Cow, ToOwned};
|
|
3
|
-
use alloc::string::{String, ToString};
|
|
4
|
-
use alloc::vec;
|
|
5
|
-
use alloc::vec::Vec;
|
|
6
|
-
use core::fmt;
|
|
7
|
-
|
|
8
|
-
use unicode_width::UnicodeWidthStr;
|
|
9
|
-
|
|
10
|
-
use crate::buffer::Buffer;
|
|
11
|
-
use crate::layout::{Alignment, Rect};
|
|
12
|
-
use crate::style::{Style, Styled};
|
|
13
|
-
use crate::text::{Line, Span};
|
|
14
|
-
use crate::widgets::Widget;
|
|
15
|
-
|
|
16
|
-
/// A string split over one or more lines.
|
|
17
|
-
///
|
|
18
|
-
/// [`Text`] is used wherever text is displayed in the terminal and represents one or more [`Line`]s
|
|
19
|
-
/// of text. When a [`Text`] is rendered, each line is rendered as a single line of text from top to
|
|
20
|
-
/// bottom of the area. The text can be styled and aligned.
|
|
21
|
-
///
|
|
22
|
-
/// # Constructor Methods
|
|
23
|
-
///
|
|
24
|
-
/// - [`Text::raw`] creates a `Text` (potentially multiple lines) with no style.
|
|
25
|
-
/// - [`Text::styled`] creates a `Text` (potentially multiple lines) with a style.
|
|
26
|
-
/// - [`Text::default`] creates a `Text` with empty content and the default style.
|
|
27
|
-
///
|
|
28
|
-
/// # Conversion Methods
|
|
29
|
-
///
|
|
30
|
-
/// - [`Text::from`] creates a `Text` from a `String`.
|
|
31
|
-
/// - [`Text::from`] creates a `Text` from a `&str`.
|
|
32
|
-
/// - [`Text::from`] creates a `Text` from a `Cow<str>`.
|
|
33
|
-
/// - [`Text::from`] creates a `Text` from a [`Span`].
|
|
34
|
-
/// - [`Text::from`] creates a `Text` from a [`Line`].
|
|
35
|
-
/// - [`Text::from`] creates a `Text` from a `Vec<Line>`.
|
|
36
|
-
/// - [`Text::from_iter`] creates a `Text` from an iterator of items that can be converted into
|
|
37
|
-
/// `Line`.
|
|
38
|
-
///
|
|
39
|
-
/// # Setter Methods
|
|
40
|
-
///
|
|
41
|
-
/// These methods are fluent setters. They return a `Text` with the property set.
|
|
42
|
-
///
|
|
43
|
-
/// - [`Text::style`] sets the style of this `Text`.
|
|
44
|
-
/// - [`Text::alignment`] sets the alignment for this `Text`.
|
|
45
|
-
/// - [`Text::left_aligned`] sets the alignment to [`Alignment::Left`].
|
|
46
|
-
/// - [`Text::centered`] sets the alignment to [`Alignment::Center`].
|
|
47
|
-
/// - [`Text::right_aligned`] sets the alignment to [`Alignment::Right`].
|
|
48
|
-
///
|
|
49
|
-
/// # Iteration Methods
|
|
50
|
-
///
|
|
51
|
-
/// - [`Text::iter`] returns an iterator over the lines of the text.
|
|
52
|
-
/// - [`Text::iter_mut`] returns an iterator that allows modifying each line.
|
|
53
|
-
/// - [`Text::into_iter`] returns an iterator over the lines of the text.
|
|
54
|
-
///
|
|
55
|
-
/// # Other Methods
|
|
56
|
-
///
|
|
57
|
-
/// - [`Text::width`] returns the max width of all the lines.
|
|
58
|
-
/// - [`Text::height`] returns the height.
|
|
59
|
-
/// - [`Text::patch_style`] patches the style of this `Text`, adding modifiers from the given style.
|
|
60
|
-
/// - [`Text::reset_style`] resets the style of the `Text`.
|
|
61
|
-
/// - [`Text::push_line`] adds a line to the text.
|
|
62
|
-
/// - [`Text::push_span`] adds a span to the last line of the text.
|
|
63
|
-
///
|
|
64
|
-
/// # Examples
|
|
65
|
-
///
|
|
66
|
-
/// ## Creating Text
|
|
67
|
-
///
|
|
68
|
-
/// A [`Text`], like a [`Line`], can be constructed using one of the many `From` implementations or
|
|
69
|
-
/// via the [`Text::raw`] and [`Text::styled`] methods. Helpfully, [`Text`] also implements
|
|
70
|
-
/// [`core::iter::Extend`] which enables the concatenation of several [`Text`] blocks.
|
|
71
|
-
///
|
|
72
|
-
/// ```rust
|
|
73
|
-
/// use std::borrow::Cow;
|
|
74
|
-
/// use std::iter;
|
|
75
|
-
///
|
|
76
|
-
/// use ratatui_core::style::{Color, Modifier, Style, Stylize};
|
|
77
|
-
/// use ratatui_core::text::{Line, Span, Text};
|
|
78
|
-
///
|
|
79
|
-
/// let style = Style::new().yellow().italic();
|
|
80
|
-
/// let text = Text::raw("The first line\nThe second line").style(style);
|
|
81
|
-
/// let text = Text::styled("The first line\nThe second line", style);
|
|
82
|
-
/// let text = Text::styled(
|
|
83
|
-
/// "The first line\nThe second line",
|
|
84
|
-
/// (Color::Yellow, Modifier::ITALIC),
|
|
85
|
-
/// );
|
|
86
|
-
///
|
|
87
|
-
/// let text = Text::from("The first line\nThe second line");
|
|
88
|
-
/// let text = Text::from(String::from("The first line\nThe second line"));
|
|
89
|
-
/// let text = Text::from(Cow::Borrowed("The first line\nThe second line"));
|
|
90
|
-
/// let text = Text::from(Span::styled("The first line\nThe second line", style));
|
|
91
|
-
/// let text = Text::from(Line::from("The first line"));
|
|
92
|
-
/// let text = Text::from(vec![
|
|
93
|
-
/// Line::from("The first line"),
|
|
94
|
-
/// Line::from("The second line"),
|
|
95
|
-
/// ]);
|
|
96
|
-
/// let text = Text::from_iter(iter::once("The first line").chain(iter::once("The second line")));
|
|
97
|
-
///
|
|
98
|
-
/// let mut text = Text::default();
|
|
99
|
-
/// text.extend(vec![
|
|
100
|
-
/// Line::from("The first line"),
|
|
101
|
-
/// Line::from("The second line"),
|
|
102
|
-
/// ]);
|
|
103
|
-
/// text.extend(Text::from("The third line\nThe fourth line"));
|
|
104
|
-
/// ```
|
|
105
|
-
///
|
|
106
|
-
/// ## Styling Text
|
|
107
|
-
///
|
|
108
|
-
/// The text's [`Style`] is used by the rendering widget to determine how to style the text. Each
|
|
109
|
-
/// [`Line`] in the text will be styled with the [`Style`] of the text, and then with its own
|
|
110
|
-
/// [`Style`]. `Text` also implements [`Styled`] which means you can use the methods of the
|
|
111
|
-
/// [`Stylize`] trait.
|
|
112
|
-
///
|
|
113
|
-
/// ```rust
|
|
114
|
-
/// use ratatui_core::style::{Color, Modifier, Style, Stylize};
|
|
115
|
-
/// use ratatui_core::text::{Line, Text};
|
|
116
|
-
///
|
|
117
|
-
/// let text = Text::from("The first line\nThe second line").style(Style::new().yellow().italic());
|
|
118
|
-
/// let text = Text::from("The first line\nThe second line")
|
|
119
|
-
/// .yellow()
|
|
120
|
-
/// .italic();
|
|
121
|
-
/// let text = Text::from(vec![
|
|
122
|
-
/// Line::from("The first line").yellow(),
|
|
123
|
-
/// Line::from("The second line").yellow(),
|
|
124
|
-
/// ])
|
|
125
|
-
/// .italic();
|
|
126
|
-
/// ```
|
|
127
|
-
///
|
|
128
|
-
/// ## Aligning Text
|
|
129
|
-
/// The text's [`Alignment`] can be set using [`Text::alignment`] or the related helper methods.
|
|
130
|
-
/// Lines composing the text can also be individually aligned with [`Line::alignment`].
|
|
131
|
-
///
|
|
132
|
-
/// ```rust
|
|
133
|
-
/// use ratatui_core::layout::Alignment;
|
|
134
|
-
/// use ratatui_core::text::{Line, Text};
|
|
135
|
-
///
|
|
136
|
-
/// let text = Text::from("The first line\nThe second line").alignment(Alignment::Right);
|
|
137
|
-
/// let text = Text::from("The first line\nThe second line").right_aligned();
|
|
138
|
-
/// let text = Text::from(vec![
|
|
139
|
-
/// Line::from("The first line").left_aligned(),
|
|
140
|
-
/// Line::from("The second line").right_aligned(),
|
|
141
|
-
/// Line::from("The third line"),
|
|
142
|
-
/// ])
|
|
143
|
-
/// .centered();
|
|
144
|
-
/// ```
|
|
145
|
-
///
|
|
146
|
-
/// ## Rendering Text
|
|
147
|
-
/// `Text` implements the [`Widget`] trait, which means it can be rendered to a [`Buffer`] or to a
|
|
148
|
-
/// `Frame`.
|
|
149
|
-
///
|
|
150
|
-
/// ```rust
|
|
151
|
-
/// # use ratatui_core::{buffer::Buffer, layout::Rect};
|
|
152
|
-
/// use ratatui_core::text::Text;
|
|
153
|
-
/// use ratatui_core::widgets::Widget;
|
|
154
|
-
///
|
|
155
|
-
/// // within another widget's `render` method:
|
|
156
|
-
/// # fn render(area: Rect, buf: &mut Buffer) {
|
|
157
|
-
/// let text = Text::from("The first line\nThe second line");
|
|
158
|
-
/// text.render(area, buf);
|
|
159
|
-
/// # }
|
|
160
|
-
/// ```
|
|
161
|
-
///
|
|
162
|
-
/// Or you can use the `render_widget` method on a `Frame` within a `Terminal::draw` closure.
|
|
163
|
-
///
|
|
164
|
-
/// ```rust,ignore
|
|
165
|
-
/// # use ratatui::{Frame, layout::Rect, text::Text};
|
|
166
|
-
/// # fn draw(frame: &mut Frame, area: Rect) {
|
|
167
|
-
/// let text = Text::from("The first line\nThe second line");
|
|
168
|
-
/// frame.render_widget(text, area);
|
|
169
|
-
/// # }
|
|
170
|
-
/// ```
|
|
171
|
-
///
|
|
172
|
-
/// ## Rendering Text with a Paragraph Widget
|
|
173
|
-
///
|
|
174
|
-
/// Usually apps will use the `Paragraph` widget instead of rendering a `Text` directly as it
|
|
175
|
-
/// provides more functionality.
|
|
176
|
-
///
|
|
177
|
-
/// ```rust,ignore
|
|
178
|
-
/// use ratatui::{
|
|
179
|
-
/// buffer::Buffer,
|
|
180
|
-
/// layout::Rect,
|
|
181
|
-
/// text::Text,
|
|
182
|
-
/// widgets::{Paragraph, Widget, Wrap},
|
|
183
|
-
/// };
|
|
184
|
-
///
|
|
185
|
-
/// # fn render(area: Rect, buf: &mut Buffer) {
|
|
186
|
-
/// let text = Text::from("The first line\nThe second line");
|
|
187
|
-
/// let paragraph = Paragraph::new(text)
|
|
188
|
-
/// .wrap(Wrap { trim: true })
|
|
189
|
-
/// .scroll((1, 1))
|
|
190
|
-
/// .render(area, buf);
|
|
191
|
-
/// # }
|
|
192
|
-
/// ```
|
|
193
|
-
///
|
|
194
|
-
/// [`Stylize`]: crate::style::Stylize
|
|
195
|
-
#[derive(Default, Clone, Eq, PartialEq, Hash)]
|
|
196
|
-
pub struct Text<'a> {
|
|
197
|
-
/// The alignment of this text.
|
|
198
|
-
pub alignment: Option<Alignment>,
|
|
199
|
-
/// The style of this text.
|
|
200
|
-
pub style: Style,
|
|
201
|
-
/// The lines that make up this piece of text.
|
|
202
|
-
pub lines: Vec<Line<'a>>,
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
impl fmt::Debug for Text<'_> {
|
|
206
|
-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
207
|
-
if self.lines.is_empty() {
|
|
208
|
-
f.write_str("Text::default()")?;
|
|
209
|
-
} else if self.lines.len() == 1 {
|
|
210
|
-
write!(f, "Text::from({:?})", self.lines[0])?;
|
|
211
|
-
} else {
|
|
212
|
-
f.write_str("Text::from_iter(")?;
|
|
213
|
-
f.debug_list().entries(self.lines.iter()).finish()?;
|
|
214
|
-
f.write_str(")")?;
|
|
215
|
-
}
|
|
216
|
-
self.style.fmt_stylize(f)?;
|
|
217
|
-
match self.alignment {
|
|
218
|
-
Some(Alignment::Left) => f.write_str(".left_aligned()")?,
|
|
219
|
-
Some(Alignment::Center) => f.write_str(".centered()")?,
|
|
220
|
-
Some(Alignment::Right) => f.write_str(".right_aligned()")?,
|
|
221
|
-
_ => (),
|
|
222
|
-
}
|
|
223
|
-
Ok(())
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
impl<'a> Text<'a> {
|
|
228
|
-
/// Create some text (potentially multiple lines) with no style.
|
|
229
|
-
///
|
|
230
|
-
/// # Examples
|
|
231
|
-
///
|
|
232
|
-
/// ```rust
|
|
233
|
-
/// use ratatui_core::text::Text;
|
|
234
|
-
///
|
|
235
|
-
/// Text::raw("The first line\nThe second line");
|
|
236
|
-
/// Text::raw(String::from("The first line\nThe second line"));
|
|
237
|
-
/// ```
|
|
238
|
-
pub fn raw<T>(content: T) -> Self
|
|
239
|
-
where
|
|
240
|
-
T: Into<Cow<'a, str>>,
|
|
241
|
-
{
|
|
242
|
-
let lines: Vec<_> = match content.into() {
|
|
243
|
-
Cow::Borrowed("") => vec![Line::from("")],
|
|
244
|
-
Cow::Borrowed(s) => s.lines().map(Line::from).collect(),
|
|
245
|
-
Cow::Owned(s) if s.is_empty() => vec![Line::from("")],
|
|
246
|
-
Cow::Owned(s) => s.lines().map(|l| Line::from(l.to_owned())).collect(),
|
|
247
|
-
};
|
|
248
|
-
Self::from(lines)
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
/// Create some text (potentially multiple lines) with a style.
|
|
252
|
-
///
|
|
253
|
-
/// `style` accepts any type that is convertible to [`Style`] (e.g. [`Style`], [`Color`], or
|
|
254
|
-
/// your own type that implements [`Into<Style>`]).
|
|
255
|
-
///
|
|
256
|
-
/// # Examples
|
|
257
|
-
///
|
|
258
|
-
/// ```rust
|
|
259
|
-
/// use ratatui_core::style::{Color, Modifier, Style};
|
|
260
|
-
/// use ratatui_core::text::Text;
|
|
261
|
-
///
|
|
262
|
-
/// let style = Style::default()
|
|
263
|
-
/// .fg(Color::Yellow)
|
|
264
|
-
/// .add_modifier(Modifier::ITALIC);
|
|
265
|
-
/// Text::styled("The first line\nThe second line", style);
|
|
266
|
-
/// Text::styled(String::from("The first line\nThe second line"), style);
|
|
267
|
-
/// ```
|
|
268
|
-
///
|
|
269
|
-
/// [`Color`]: crate::style::Color
|
|
270
|
-
pub fn styled<T, S>(content: T, style: S) -> Self
|
|
271
|
-
where
|
|
272
|
-
T: Into<Cow<'a, str>>,
|
|
273
|
-
S: Into<Style>,
|
|
274
|
-
{
|
|
275
|
-
Self::raw(content).patch_style(style)
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
/// Returns the max width of all the lines.
|
|
279
|
-
///
|
|
280
|
-
/// # Examples
|
|
281
|
-
///
|
|
282
|
-
/// ```rust
|
|
283
|
-
/// use ratatui_core::text::Text;
|
|
284
|
-
///
|
|
285
|
-
/// let text = Text::from("The first line\nThe second line");
|
|
286
|
-
/// assert_eq!(15, text.width());
|
|
287
|
-
/// ```
|
|
288
|
-
pub fn width(&self) -> usize {
|
|
289
|
-
UnicodeWidthStr::width(self)
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
/// Returns the height.
|
|
293
|
-
///
|
|
294
|
-
/// # Examples
|
|
295
|
-
///
|
|
296
|
-
/// ```rust
|
|
297
|
-
/// use ratatui_core::text::Text;
|
|
298
|
-
///
|
|
299
|
-
/// let text = Text::from("The first line\nThe second line");
|
|
300
|
-
/// assert_eq!(2, text.height());
|
|
301
|
-
/// ```
|
|
302
|
-
pub fn height(&self) -> usize {
|
|
303
|
-
self.lines.len()
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
/// Sets the style of this text.
|
|
307
|
-
///
|
|
308
|
-
/// Defaults to [`Style::default()`].
|
|
309
|
-
///
|
|
310
|
-
/// Note: This field was added in v0.26.0. Prior to that, the style of a text was determined
|
|
311
|
-
/// only by the style of each [`Line`] contained in the line. For this reason, this field may
|
|
312
|
-
/// not be supported by all widgets (outside of the `ratatui` crate itself).
|
|
313
|
-
///
|
|
314
|
-
/// `style` accepts any type that is convertible to [`Style`] (e.g. [`Style`], [`Color`], or
|
|
315
|
-
/// your own type that implements [`Into<Style>`]).
|
|
316
|
-
///
|
|
317
|
-
/// # Examples
|
|
318
|
-
/// ```rust
|
|
319
|
-
/// use ratatui_core::style::{Style, Stylize};
|
|
320
|
-
/// use ratatui_core::text::Text;
|
|
321
|
-
///
|
|
322
|
-
/// let mut line = Text::from("foo").style(Style::new().red());
|
|
323
|
-
/// ```
|
|
324
|
-
///
|
|
325
|
-
/// [`Color`]: crate::style::Color
|
|
326
|
-
#[must_use = "method moves the value of self and returns the modified value"]
|
|
327
|
-
pub fn style<S: Into<Style>>(mut self, style: S) -> Self {
|
|
328
|
-
self.style = style.into();
|
|
329
|
-
self
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
/// Patches the style of this Text, adding modifiers from the given style.
|
|
333
|
-
///
|
|
334
|
-
/// This is useful for when you want to apply a style to a text that already has some styling.
|
|
335
|
-
/// In contrast to [`Text::style`], this method will not overwrite the existing style, but
|
|
336
|
-
/// instead will add the given style's modifiers to this text's style.
|
|
337
|
-
///
|
|
338
|
-
/// `Text` also implements [`Styled`] which means you can use the methods of the [`Stylize`]
|
|
339
|
-
/// trait.
|
|
340
|
-
///
|
|
341
|
-
/// `style` accepts any type that is convertible to [`Style`] (e.g. [`Style`], [`Color`], or
|
|
342
|
-
/// your own type that implements [`Into<Style>`]).
|
|
343
|
-
///
|
|
344
|
-
/// This is a fluent setter method which must be chained or used as it consumes self
|
|
345
|
-
///
|
|
346
|
-
/// # Examples
|
|
347
|
-
///
|
|
348
|
-
/// ```rust
|
|
349
|
-
/// use ratatui_core::style::{Color, Modifier};
|
|
350
|
-
/// use ratatui_core::text::Text;
|
|
351
|
-
///
|
|
352
|
-
/// let raw_text = Text::styled("The first line\nThe second line", Modifier::ITALIC);
|
|
353
|
-
/// let styled_text = Text::styled(
|
|
354
|
-
/// String::from("The first line\nThe second line"),
|
|
355
|
-
/// (Color::Yellow, Modifier::ITALIC),
|
|
356
|
-
/// );
|
|
357
|
-
/// assert_ne!(raw_text, styled_text);
|
|
358
|
-
///
|
|
359
|
-
/// let raw_text = raw_text.patch_style(Color::Yellow);
|
|
360
|
-
/// assert_eq!(raw_text, styled_text);
|
|
361
|
-
/// ```
|
|
362
|
-
///
|
|
363
|
-
/// [`Color`]: crate::style::Color
|
|
364
|
-
/// [`Stylize`]: crate::style::Stylize
|
|
365
|
-
#[must_use = "method moves the value of self and returns the modified value"]
|
|
366
|
-
pub fn patch_style<S: Into<Style>>(mut self, style: S) -> Self {
|
|
367
|
-
self.style = self.style.patch(style);
|
|
368
|
-
self
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
/// Resets the style of the Text.
|
|
372
|
-
///
|
|
373
|
-
/// Equivalent to calling [`patch_style(Style::reset())`](Text::patch_style).
|
|
374
|
-
///
|
|
375
|
-
/// This is a fluent setter method which must be chained or used as it consumes self
|
|
376
|
-
///
|
|
377
|
-
/// # Examples
|
|
378
|
-
///
|
|
379
|
-
/// ```rust
|
|
380
|
-
/// use ratatui_core::style::{Color, Modifier, Style};
|
|
381
|
-
/// use ratatui_core::text::Text;
|
|
382
|
-
///
|
|
383
|
-
/// let text = Text::styled(
|
|
384
|
-
/// "The first line\nThe second line",
|
|
385
|
-
/// (Color::Yellow, Modifier::ITALIC),
|
|
386
|
-
/// );
|
|
387
|
-
///
|
|
388
|
-
/// let text = text.reset_style();
|
|
389
|
-
/// assert_eq!(Style::reset(), text.style);
|
|
390
|
-
/// ```
|
|
391
|
-
#[must_use = "method moves the value of self and returns the modified value"]
|
|
392
|
-
pub fn reset_style(self) -> Self {
|
|
393
|
-
self.patch_style(Style::reset())
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
/// Sets the alignment for this text.
|
|
397
|
-
///
|
|
398
|
-
/// Defaults to: [`None`], meaning the alignment is determined by the rendering widget.
|
|
399
|
-
/// Setting the alignment of a Text generally overrides the alignment of its
|
|
400
|
-
/// parent Widget.
|
|
401
|
-
///
|
|
402
|
-
/// Alignment can be set individually on each line to override this text's alignment.
|
|
403
|
-
///
|
|
404
|
-
/// # Examples
|
|
405
|
-
///
|
|
406
|
-
/// Set alignment to the whole text.
|
|
407
|
-
///
|
|
408
|
-
/// ```rust
|
|
409
|
-
/// use ratatui_core::layout::Alignment;
|
|
410
|
-
/// use ratatui_core::text::Text;
|
|
411
|
-
///
|
|
412
|
-
/// let mut text = Text::from("Hi, what's up?");
|
|
413
|
-
/// assert_eq!(None, text.alignment);
|
|
414
|
-
/// assert_eq!(
|
|
415
|
-
/// Some(Alignment::Right),
|
|
416
|
-
/// text.alignment(Alignment::Right).alignment
|
|
417
|
-
/// )
|
|
418
|
-
/// ```
|
|
419
|
-
///
|
|
420
|
-
/// Set a default alignment and override it on a per line basis.
|
|
421
|
-
///
|
|
422
|
-
/// ```rust
|
|
423
|
-
/// use ratatui_core::layout::Alignment;
|
|
424
|
-
/// use ratatui_core::text::{Line, Text};
|
|
425
|
-
///
|
|
426
|
-
/// let text = Text::from(vec![
|
|
427
|
-
/// Line::from("left").alignment(Alignment::Left),
|
|
428
|
-
/// Line::from("default"),
|
|
429
|
-
/// Line::from("default"),
|
|
430
|
-
/// Line::from("right").alignment(Alignment::Right),
|
|
431
|
-
/// ])
|
|
432
|
-
/// .alignment(Alignment::Center);
|
|
433
|
-
/// ```
|
|
434
|
-
///
|
|
435
|
-
/// Will render the following
|
|
436
|
-
///
|
|
437
|
-
/// ```plain
|
|
438
|
-
/// left
|
|
439
|
-
/// default
|
|
440
|
-
/// default
|
|
441
|
-
/// right
|
|
442
|
-
/// ```
|
|
443
|
-
#[must_use = "method moves the value of self and returns the modified value"]
|
|
444
|
-
pub fn alignment(self, alignment: Alignment) -> Self {
|
|
445
|
-
Self {
|
|
446
|
-
alignment: Some(alignment),
|
|
447
|
-
..self
|
|
448
|
-
}
|
|
449
|
-
}
|
|
450
|
-
|
|
451
|
-
/// Left-aligns the whole text.
|
|
452
|
-
///
|
|
453
|
-
/// Convenience shortcut for `Text::alignment(Alignment::Left)`.
|
|
454
|
-
/// Setting the alignment of a Text generally overrides the alignment of its
|
|
455
|
-
/// parent Widget, with the default alignment being inherited from the parent.
|
|
456
|
-
///
|
|
457
|
-
/// Alignment can be set individually on each line to override this text's alignment.
|
|
458
|
-
///
|
|
459
|
-
/// # Examples
|
|
460
|
-
///
|
|
461
|
-
/// ```rust
|
|
462
|
-
/// use ratatui_core::text::Text;
|
|
463
|
-
///
|
|
464
|
-
/// let text = Text::from("Hi, what's up?").left_aligned();
|
|
465
|
-
/// ```
|
|
466
|
-
#[must_use = "method moves the value of self and returns the modified value"]
|
|
467
|
-
pub fn left_aligned(self) -> Self {
|
|
468
|
-
self.alignment(Alignment::Left)
|
|
469
|
-
}
|
|
470
|
-
|
|
471
|
-
/// Center-aligns the whole text.
|
|
472
|
-
///
|
|
473
|
-
/// Convenience shortcut for `Text::alignment(Alignment::Center)`.
|
|
474
|
-
/// Setting the alignment of a Text generally overrides the alignment of its
|
|
475
|
-
/// parent Widget, with the default alignment being inherited from the parent.
|
|
476
|
-
///
|
|
477
|
-
/// Alignment can be set individually on each line to override this text's alignment.
|
|
478
|
-
///
|
|
479
|
-
/// # Examples
|
|
480
|
-
///
|
|
481
|
-
/// ```rust
|
|
482
|
-
/// use ratatui_core::text::Text;
|
|
483
|
-
///
|
|
484
|
-
/// let text = Text::from("Hi, what's up?").centered();
|
|
485
|
-
/// ```
|
|
486
|
-
#[must_use = "method moves the value of self and returns the modified value"]
|
|
487
|
-
pub fn centered(self) -> Self {
|
|
488
|
-
self.alignment(Alignment::Center)
|
|
489
|
-
}
|
|
490
|
-
|
|
491
|
-
/// Right-aligns the whole text.
|
|
492
|
-
///
|
|
493
|
-
/// Convenience shortcut for `Text::alignment(Alignment::Right)`.
|
|
494
|
-
/// Setting the alignment of a Text generally overrides the alignment of its
|
|
495
|
-
/// parent Widget, with the default alignment being inherited from the parent.
|
|
496
|
-
///
|
|
497
|
-
/// Alignment can be set individually on each line to override this text's alignment.
|
|
498
|
-
///
|
|
499
|
-
/// # Examples
|
|
500
|
-
///
|
|
501
|
-
/// ```rust
|
|
502
|
-
/// use ratatui_core::text::Text;
|
|
503
|
-
///
|
|
504
|
-
/// let text = Text::from("Hi, what's up?").right_aligned();
|
|
505
|
-
/// ```
|
|
506
|
-
#[must_use = "method moves the value of self and returns the modified value"]
|
|
507
|
-
pub fn right_aligned(self) -> Self {
|
|
508
|
-
self.alignment(Alignment::Right)
|
|
509
|
-
}
|
|
510
|
-
|
|
511
|
-
/// Returns an iterator over the lines of the text.
|
|
512
|
-
pub fn iter(&self) -> core::slice::Iter<'_, Line<'a>> {
|
|
513
|
-
self.lines.iter()
|
|
514
|
-
}
|
|
515
|
-
|
|
516
|
-
/// Returns an iterator that allows modifying each line.
|
|
517
|
-
pub fn iter_mut(&mut self) -> core::slice::IterMut<'_, Line<'a>> {
|
|
518
|
-
self.lines.iter_mut()
|
|
519
|
-
}
|
|
520
|
-
|
|
521
|
-
/// Adds a line to the text.
|
|
522
|
-
///
|
|
523
|
-
/// `line` can be any type that can be converted into a `Line`. For example, you can pass a
|
|
524
|
-
/// `&str`, a `String`, a `Span`, or a `Line`.
|
|
525
|
-
///
|
|
526
|
-
/// # Examples
|
|
527
|
-
///
|
|
528
|
-
/// ```rust
|
|
529
|
-
/// use ratatui_core::text::{Line, Span, Text};
|
|
530
|
-
///
|
|
531
|
-
/// let mut text = Text::from("Hello, world!");
|
|
532
|
-
/// text.push_line(Line::from("How are you?"));
|
|
533
|
-
/// text.push_line(Span::from("How are you?"));
|
|
534
|
-
/// text.push_line("How are you?");
|
|
535
|
-
/// ```
|
|
536
|
-
pub fn push_line<T: Into<Line<'a>>>(&mut self, line: T) {
|
|
537
|
-
self.lines.push(line.into());
|
|
538
|
-
}
|
|
539
|
-
|
|
540
|
-
/// Adds a span to the last line of the text.
|
|
541
|
-
///
|
|
542
|
-
/// `span` can be any type that is convertible into a `Span`. For example, you can pass a
|
|
543
|
-
/// `&str`, a `String`, or a `Span`.
|
|
544
|
-
///
|
|
545
|
-
/// # Examples
|
|
546
|
-
///
|
|
547
|
-
/// ```rust
|
|
548
|
-
/// use ratatui_core::text::{Span, Text};
|
|
549
|
-
///
|
|
550
|
-
/// let mut text = Text::from("Hello, world!");
|
|
551
|
-
/// text.push_span(Span::from("How are you?"));
|
|
552
|
-
/// text.push_span("How are you?");
|
|
553
|
-
/// ```
|
|
554
|
-
pub fn push_span<T: Into<Span<'a>>>(&mut self, span: T) {
|
|
555
|
-
let span = span.into();
|
|
556
|
-
if let Some(last) = self.lines.last_mut() {
|
|
557
|
-
last.push_span(span);
|
|
558
|
-
} else {
|
|
559
|
-
self.lines.push(Line::from(span));
|
|
560
|
-
}
|
|
561
|
-
}
|
|
562
|
-
}
|
|
563
|
-
|
|
564
|
-
impl UnicodeWidthStr for Text<'_> {
|
|
565
|
-
/// Returns the max width of all the lines.
|
|
566
|
-
fn width(&self) -> usize {
|
|
567
|
-
self.lines
|
|
568
|
-
.iter()
|
|
569
|
-
.map(UnicodeWidthStr::width)
|
|
570
|
-
.max()
|
|
571
|
-
.unwrap_or_default()
|
|
572
|
-
}
|
|
573
|
-
|
|
574
|
-
fn width_cjk(&self) -> usize {
|
|
575
|
-
self.lines
|
|
576
|
-
.iter()
|
|
577
|
-
.map(UnicodeWidthStr::width_cjk)
|
|
578
|
-
.max()
|
|
579
|
-
.unwrap_or_default()
|
|
580
|
-
}
|
|
581
|
-
}
|
|
582
|
-
|
|
583
|
-
impl<'a> IntoIterator for Text<'a> {
|
|
584
|
-
type Item = Line<'a>;
|
|
585
|
-
type IntoIter = alloc::vec::IntoIter<Self::Item>;
|
|
586
|
-
|
|
587
|
-
fn into_iter(self) -> Self::IntoIter {
|
|
588
|
-
self.lines.into_iter()
|
|
589
|
-
}
|
|
590
|
-
}
|
|
591
|
-
|
|
592
|
-
impl<'a> IntoIterator for &'a Text<'a> {
|
|
593
|
-
type Item = &'a Line<'a>;
|
|
594
|
-
type IntoIter = core::slice::Iter<'a, Line<'a>>;
|
|
595
|
-
|
|
596
|
-
fn into_iter(self) -> Self::IntoIter {
|
|
597
|
-
self.iter()
|
|
598
|
-
}
|
|
599
|
-
}
|
|
600
|
-
|
|
601
|
-
impl<'a> IntoIterator for &'a mut Text<'a> {
|
|
602
|
-
type Item = &'a mut Line<'a>;
|
|
603
|
-
type IntoIter = core::slice::IterMut<'a, Line<'a>>;
|
|
604
|
-
|
|
605
|
-
fn into_iter(self) -> Self::IntoIter {
|
|
606
|
-
self.iter_mut()
|
|
607
|
-
}
|
|
608
|
-
}
|
|
609
|
-
|
|
610
|
-
impl From<String> for Text<'_> {
|
|
611
|
-
fn from(s: String) -> Self {
|
|
612
|
-
Self::raw(s)
|
|
613
|
-
}
|
|
614
|
-
}
|
|
615
|
-
|
|
616
|
-
impl<'a> From<&'a str> for Text<'a> {
|
|
617
|
-
fn from(s: &'a str) -> Self {
|
|
618
|
-
Self::raw(s)
|
|
619
|
-
}
|
|
620
|
-
}
|
|
621
|
-
|
|
622
|
-
impl<'a> From<Cow<'a, str>> for Text<'a> {
|
|
623
|
-
fn from(s: Cow<'a, str>) -> Self {
|
|
624
|
-
Self::raw(s)
|
|
625
|
-
}
|
|
626
|
-
}
|
|
627
|
-
|
|
628
|
-
impl<'a> From<Span<'a>> for Text<'a> {
|
|
629
|
-
fn from(span: Span<'a>) -> Self {
|
|
630
|
-
Self {
|
|
631
|
-
lines: vec![Line::from(span)],
|
|
632
|
-
..Default::default()
|
|
633
|
-
}
|
|
634
|
-
}
|
|
635
|
-
}
|
|
636
|
-
|
|
637
|
-
impl<'a> From<Line<'a>> for Text<'a> {
|
|
638
|
-
fn from(line: Line<'a>) -> Self {
|
|
639
|
-
Self {
|
|
640
|
-
lines: vec![line],
|
|
641
|
-
..Default::default()
|
|
642
|
-
}
|
|
643
|
-
}
|
|
644
|
-
}
|
|
645
|
-
|
|
646
|
-
impl<'a> From<Vec<Line<'a>>> for Text<'a> {
|
|
647
|
-
fn from(lines: Vec<Line<'a>>) -> Self {
|
|
648
|
-
Self {
|
|
649
|
-
lines,
|
|
650
|
-
..Default::default()
|
|
651
|
-
}
|
|
652
|
-
}
|
|
653
|
-
}
|
|
654
|
-
|
|
655
|
-
impl<'a, T> FromIterator<T> for Text<'a>
|
|
656
|
-
where
|
|
657
|
-
T: Into<Line<'a>>,
|
|
658
|
-
{
|
|
659
|
-
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
|
|
660
|
-
let lines = iter.into_iter().map(Into::into).collect();
|
|
661
|
-
Self {
|
|
662
|
-
lines,
|
|
663
|
-
..Default::default()
|
|
664
|
-
}
|
|
665
|
-
}
|
|
666
|
-
}
|
|
667
|
-
|
|
668
|
-
impl<'a> core::ops::Add<Line<'a>> for Text<'a> {
|
|
669
|
-
type Output = Self;
|
|
670
|
-
|
|
671
|
-
fn add(mut self, line: Line<'a>) -> Self::Output {
|
|
672
|
-
self.push_line(line);
|
|
673
|
-
self
|
|
674
|
-
}
|
|
675
|
-
}
|
|
676
|
-
|
|
677
|
-
/// Adds two `Text` together.
|
|
678
|
-
///
|
|
679
|
-
/// This ignores the style and alignment of the second `Text`.
|
|
680
|
-
impl core::ops::Add<Self> for Text<'_> {
|
|
681
|
-
type Output = Self;
|
|
682
|
-
|
|
683
|
-
fn add(mut self, text: Self) -> Self::Output {
|
|
684
|
-
self.lines.extend(text.lines);
|
|
685
|
-
self
|
|
686
|
-
}
|
|
687
|
-
}
|
|
688
|
-
|
|
689
|
-
/// Adds two `Text` together.
|
|
690
|
-
///
|
|
691
|
-
/// This ignores the style and alignment of the second `Text`.
|
|
692
|
-
impl core::ops::AddAssign for Text<'_> {
|
|
693
|
-
fn add_assign(&mut self, rhs: Self) {
|
|
694
|
-
self.lines.extend(rhs.lines);
|
|
695
|
-
}
|
|
696
|
-
}
|
|
697
|
-
|
|
698
|
-
impl<'a> core::ops::AddAssign<Line<'a>> for Text<'a> {
|
|
699
|
-
fn add_assign(&mut self, line: Line<'a>) {
|
|
700
|
-
self.push_line(line);
|
|
701
|
-
}
|
|
702
|
-
}
|
|
703
|
-
|
|
704
|
-
impl<'a, T> Extend<T> for Text<'a>
|
|
705
|
-
where
|
|
706
|
-
T: Into<Line<'a>>,
|
|
707
|
-
{
|
|
708
|
-
fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
|
|
709
|
-
let lines = iter.into_iter().map(Into::into);
|
|
710
|
-
self.lines.extend(lines);
|
|
711
|
-
}
|
|
712
|
-
}
|
|
713
|
-
|
|
714
|
-
/// A trait for converting a value to a [`Text`].
|
|
715
|
-
///
|
|
716
|
-
/// This trait is automatically implemented for any type that implements the [`Display`] trait. As
|
|
717
|
-
/// such, `ToText` shouldn't be implemented directly: [`Display`] should be implemented instead, and
|
|
718
|
-
/// you get the `ToText` implementation for free.
|
|
719
|
-
///
|
|
720
|
-
/// [`Display`]: std::fmt::Display
|
|
721
|
-
pub trait ToText {
|
|
722
|
-
/// Converts the value to a [`Text`].
|
|
723
|
-
fn to_text(&self) -> Text<'_>;
|
|
724
|
-
}
|
|
725
|
-
|
|
726
|
-
/// # Panics
|
|
727
|
-
///
|
|
728
|
-
/// In this implementation, the `to_text` method panics if the `Display` implementation returns an
|
|
729
|
-
/// error. This indicates an incorrect `Display` implementation since `fmt::Write for String` never
|
|
730
|
-
/// returns an error itself.
|
|
731
|
-
impl<T: fmt::Display> ToText for T {
|
|
732
|
-
fn to_text(&self) -> Text<'_> {
|
|
733
|
-
Text::raw(self.to_string())
|
|
734
|
-
}
|
|
735
|
-
}
|
|
736
|
-
|
|
737
|
-
impl fmt::Display for Text<'_> {
|
|
738
|
-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
739
|
-
if let Some((last, rest)) = self.lines.split_last() {
|
|
740
|
-
for line in rest {
|
|
741
|
-
writeln!(f, "{line}")?;
|
|
742
|
-
}
|
|
743
|
-
write!(f, "{last}")?;
|
|
744
|
-
}
|
|
745
|
-
Ok(())
|
|
746
|
-
}
|
|
747
|
-
}
|
|
748
|
-
|
|
749
|
-
impl Widget for Text<'_> {
|
|
750
|
-
fn render(self, area: Rect, buf: &mut Buffer) {
|
|
751
|
-
Widget::render(&self, area, buf);
|
|
752
|
-
}
|
|
753
|
-
}
|
|
754
|
-
|
|
755
|
-
impl Widget for &Text<'_> {
|
|
756
|
-
fn render(self, area: Rect, buf: &mut Buffer) {
|
|
757
|
-
let area = area.intersection(buf.area);
|
|
758
|
-
buf.set_style(area, self.style);
|
|
759
|
-
for (line, line_area) in self.iter().zip(area.rows()) {
|
|
760
|
-
line.render_with_alignment(line_area, buf, self.alignment);
|
|
761
|
-
}
|
|
762
|
-
}
|
|
763
|
-
}
|
|
764
|
-
|
|
765
|
-
impl Styled for Text<'_> {
|
|
766
|
-
type Item = Self;
|
|
767
|
-
|
|
768
|
-
fn style(&self) -> Style {
|
|
769
|
-
self.style
|
|
770
|
-
}
|
|
771
|
-
|
|
772
|
-
fn set_style<S: Into<Style>>(self, style: S) -> Self::Item {
|
|
773
|
-
self.style(style)
|
|
774
|
-
}
|
|
775
|
-
}
|
|
776
|
-
|
|
777
|
-
#[cfg(test)]
|
|
778
|
-
mod tests {
|
|
779
|
-
use alloc::format;
|
|
780
|
-
use core::iter;
|
|
781
|
-
|
|
782
|
-
use rstest::{fixture, rstest};
|
|
783
|
-
|
|
784
|
-
use super::*;
|
|
785
|
-
use crate::style::{Color, Modifier, Stylize};
|
|
786
|
-
|
|
787
|
-
#[fixture]
|
|
788
|
-
fn small_buf() -> Buffer {
|
|
789
|
-
Buffer::empty(Rect::new(0, 0, 10, 1))
|
|
790
|
-
}
|
|
791
|
-
|
|
792
|
-
#[test]
|
|
793
|
-
fn raw() {
|
|
794
|
-
let text = Text::raw("The first line\nThe second line");
|
|
795
|
-
assert_eq!(
|
|
796
|
-
text.lines,
|
|
797
|
-
vec![Line::from("The first line"), Line::from("The second line")]
|
|
798
|
-
);
|
|
799
|
-
}
|
|
800
|
-
|
|
801
|
-
#[test]
|
|
802
|
-
fn styled() {
|
|
803
|
-
let style = Style::new().yellow().italic();
|
|
804
|
-
let styled_text = Text::styled("The first line\nThe second line", style);
|
|
805
|
-
|
|
806
|
-
let mut text = Text::raw("The first line\nThe second line");
|
|
807
|
-
text.style = style;
|
|
808
|
-
|
|
809
|
-
assert_eq!(styled_text, text);
|
|
810
|
-
}
|
|
811
|
-
|
|
812
|
-
#[test]
|
|
813
|
-
fn width() {
|
|
814
|
-
let text = Text::from("The first line\nThe second line");
|
|
815
|
-
assert_eq!(15, text.width());
|
|
816
|
-
}
|
|
817
|
-
|
|
818
|
-
#[test]
|
|
819
|
-
fn height() {
|
|
820
|
-
let text = Text::from("The first line\nThe second line");
|
|
821
|
-
assert_eq!(2, text.height());
|
|
822
|
-
}
|
|
823
|
-
|
|
824
|
-
#[test]
|
|
825
|
-
fn patch_style() {
|
|
826
|
-
let style = Style::new().yellow().italic();
|
|
827
|
-
let style2 = Style::new().red().underlined();
|
|
828
|
-
let text = Text::styled("The first line\nThe second line", style).patch_style(style2);
|
|
829
|
-
|
|
830
|
-
let expected_style = Style::new().red().italic().underlined();
|
|
831
|
-
let expected_text = Text::styled("The first line\nThe second line", expected_style);
|
|
832
|
-
|
|
833
|
-
assert_eq!(text, expected_text);
|
|
834
|
-
}
|
|
835
|
-
|
|
836
|
-
#[test]
|
|
837
|
-
fn reset_style() {
|
|
838
|
-
let style = Style::new().yellow().italic();
|
|
839
|
-
let text = Text::styled("The first line\nThe second line", style).reset_style();
|
|
840
|
-
|
|
841
|
-
assert_eq!(text.style, Style::reset());
|
|
842
|
-
}
|
|
843
|
-
|
|
844
|
-
#[test]
|
|
845
|
-
fn from_string() {
|
|
846
|
-
let text = Text::from(String::from("The first line\nThe second line"));
|
|
847
|
-
assert_eq!(
|
|
848
|
-
text.lines,
|
|
849
|
-
vec![Line::from("The first line"), Line::from("The second line")]
|
|
850
|
-
);
|
|
851
|
-
}
|
|
852
|
-
|
|
853
|
-
#[test]
|
|
854
|
-
fn from_str() {
|
|
855
|
-
let text = Text::from("The first line\nThe second line");
|
|
856
|
-
assert_eq!(
|
|
857
|
-
text.lines,
|
|
858
|
-
vec![Line::from("The first line"), Line::from("The second line")]
|
|
859
|
-
);
|
|
860
|
-
}
|
|
861
|
-
|
|
862
|
-
#[test]
|
|
863
|
-
fn from_cow() {
|
|
864
|
-
let text = Text::from(Cow::Borrowed("The first line\nThe second line"));
|
|
865
|
-
assert_eq!(
|
|
866
|
-
text.lines,
|
|
867
|
-
vec![Line::from("The first line"), Line::from("The second line")]
|
|
868
|
-
);
|
|
869
|
-
}
|
|
870
|
-
|
|
871
|
-
#[test]
|
|
872
|
-
fn from_span() {
|
|
873
|
-
let style = Style::new().yellow().italic();
|
|
874
|
-
let text = Text::from(Span::styled("The first line\nThe second line", style));
|
|
875
|
-
assert_eq!(
|
|
876
|
-
text.lines,
|
|
877
|
-
vec![Line::from(Span::styled(
|
|
878
|
-
"The first line\nThe second line",
|
|
879
|
-
style
|
|
880
|
-
))]
|
|
881
|
-
);
|
|
882
|
-
}
|
|
883
|
-
|
|
884
|
-
#[test]
|
|
885
|
-
fn from_line() {
|
|
886
|
-
let text = Text::from(Line::from("The first line"));
|
|
887
|
-
assert_eq!(text.lines, [Line::from("The first line")]);
|
|
888
|
-
}
|
|
889
|
-
|
|
890
|
-
#[rstest]
|
|
891
|
-
#[case(42, Text::from("42"))]
|
|
892
|
-
#[case("just\ntesting", Text::from("just\ntesting"))]
|
|
893
|
-
#[case(true, Text::from("true"))]
|
|
894
|
-
#[case(6.66, Text::from("6.66"))]
|
|
895
|
-
#[case('a', Text::from("a"))]
|
|
896
|
-
#[case(String::from("hello"), Text::from("hello"))]
|
|
897
|
-
#[case(-1, Text::from("-1"))]
|
|
898
|
-
#[case("line1\nline2", Text::from("line1\nline2"))]
|
|
899
|
-
#[case(
|
|
900
|
-
"first line\nsecond line\nthird line",
|
|
901
|
-
Text::from("first line\nsecond line\nthird line")
|
|
902
|
-
)]
|
|
903
|
-
#[case("trailing newline\n", Text::from("trailing newline\n"))]
|
|
904
|
-
fn to_text(#[case] value: impl fmt::Display, #[case] expected: Text) {
|
|
905
|
-
assert_eq!(value.to_text(), expected);
|
|
906
|
-
}
|
|
907
|
-
|
|
908
|
-
#[test]
|
|
909
|
-
fn from_vec_line() {
|
|
910
|
-
let text = Text::from(vec![
|
|
911
|
-
Line::from("The first line"),
|
|
912
|
-
Line::from("The second line"),
|
|
913
|
-
]);
|
|
914
|
-
assert_eq!(
|
|
915
|
-
text.lines,
|
|
916
|
-
vec![Line::from("The first line"), Line::from("The second line")]
|
|
917
|
-
);
|
|
918
|
-
}
|
|
919
|
-
|
|
920
|
-
#[test]
|
|
921
|
-
fn from_iterator() {
|
|
922
|
-
let text = Text::from_iter(vec!["The first line", "The second line"]);
|
|
923
|
-
assert_eq!(
|
|
924
|
-
text.lines,
|
|
925
|
-
vec![Line::from("The first line"), Line::from("The second line")]
|
|
926
|
-
);
|
|
927
|
-
}
|
|
928
|
-
|
|
929
|
-
#[test]
|
|
930
|
-
fn collect() {
|
|
931
|
-
let text: Text = iter::once("The first line")
|
|
932
|
-
.chain(iter::once("The second line"))
|
|
933
|
-
.collect();
|
|
934
|
-
assert_eq!(
|
|
935
|
-
text.lines,
|
|
936
|
-
vec![Line::from("The first line"), Line::from("The second line")]
|
|
937
|
-
);
|
|
938
|
-
}
|
|
939
|
-
|
|
940
|
-
#[test]
|
|
941
|
-
fn into_iter() {
|
|
942
|
-
let text = Text::from("The first line\nThe second line");
|
|
943
|
-
let mut iter = text.into_iter();
|
|
944
|
-
assert_eq!(iter.next(), Some(Line::from("The first line")));
|
|
945
|
-
assert_eq!(iter.next(), Some(Line::from("The second line")));
|
|
946
|
-
assert_eq!(iter.next(), None);
|
|
947
|
-
}
|
|
948
|
-
|
|
949
|
-
#[test]
|
|
950
|
-
fn add_line() {
|
|
951
|
-
assert_eq!(
|
|
952
|
-
Text::raw("Red").red() + Line::raw("Blue").blue(),
|
|
953
|
-
Text {
|
|
954
|
-
lines: vec![Line::raw("Red"), Line::raw("Blue").blue()],
|
|
955
|
-
style: Style::new().red(),
|
|
956
|
-
alignment: None,
|
|
957
|
-
}
|
|
958
|
-
);
|
|
959
|
-
}
|
|
960
|
-
|
|
961
|
-
#[test]
|
|
962
|
-
fn add_text() {
|
|
963
|
-
assert_eq!(
|
|
964
|
-
Text::raw("Red").red() + Text::raw("Blue").blue(),
|
|
965
|
-
Text {
|
|
966
|
-
lines: vec![Line::raw("Red"), Line::raw("Blue")],
|
|
967
|
-
style: Style::new().red(),
|
|
968
|
-
alignment: None,
|
|
969
|
-
}
|
|
970
|
-
);
|
|
971
|
-
}
|
|
972
|
-
|
|
973
|
-
#[test]
|
|
974
|
-
fn add_assign_text() {
|
|
975
|
-
let mut text = Text::raw("Red").red();
|
|
976
|
-
text += Text::raw("Blue").blue();
|
|
977
|
-
assert_eq!(
|
|
978
|
-
text,
|
|
979
|
-
Text {
|
|
980
|
-
lines: vec![Line::raw("Red"), Line::raw("Blue")],
|
|
981
|
-
style: Style::new().red(),
|
|
982
|
-
alignment: None,
|
|
983
|
-
}
|
|
984
|
-
);
|
|
985
|
-
}
|
|
986
|
-
|
|
987
|
-
#[test]
|
|
988
|
-
fn add_assign_line() {
|
|
989
|
-
let mut text = Text::raw("Red").red();
|
|
990
|
-
text += Line::raw("Blue").blue();
|
|
991
|
-
assert_eq!(
|
|
992
|
-
text,
|
|
993
|
-
Text {
|
|
994
|
-
lines: vec![Line::raw("Red"), Line::raw("Blue").blue()],
|
|
995
|
-
style: Style::new().red(),
|
|
996
|
-
alignment: None,
|
|
997
|
-
}
|
|
998
|
-
);
|
|
999
|
-
}
|
|
1000
|
-
|
|
1001
|
-
#[test]
|
|
1002
|
-
fn extend() {
|
|
1003
|
-
let mut text = Text::from("The first line\nThe second line");
|
|
1004
|
-
text.extend(vec![
|
|
1005
|
-
Line::from("The third line"),
|
|
1006
|
-
Line::from("The fourth line"),
|
|
1007
|
-
]);
|
|
1008
|
-
assert_eq!(
|
|
1009
|
-
text.lines,
|
|
1010
|
-
vec![
|
|
1011
|
-
Line::from("The first line"),
|
|
1012
|
-
Line::from("The second line"),
|
|
1013
|
-
Line::from("The third line"),
|
|
1014
|
-
Line::from("The fourth line"),
|
|
1015
|
-
]
|
|
1016
|
-
);
|
|
1017
|
-
}
|
|
1018
|
-
|
|
1019
|
-
#[test]
|
|
1020
|
-
fn extend_from_iter() {
|
|
1021
|
-
let mut text = Text::from("The first line\nThe second line");
|
|
1022
|
-
text.extend(vec![
|
|
1023
|
-
Line::from("The third line"),
|
|
1024
|
-
Line::from("The fourth line"),
|
|
1025
|
-
]);
|
|
1026
|
-
assert_eq!(
|
|
1027
|
-
text.lines,
|
|
1028
|
-
vec![
|
|
1029
|
-
Line::from("The first line"),
|
|
1030
|
-
Line::from("The second line"),
|
|
1031
|
-
Line::from("The third line"),
|
|
1032
|
-
Line::from("The fourth line"),
|
|
1033
|
-
]
|
|
1034
|
-
);
|
|
1035
|
-
}
|
|
1036
|
-
|
|
1037
|
-
#[test]
|
|
1038
|
-
fn extend_from_iter_str() {
|
|
1039
|
-
let mut text = Text::from("The first line\nThe second line");
|
|
1040
|
-
text.extend(vec!["The third line", "The fourth line"]);
|
|
1041
|
-
assert_eq!(
|
|
1042
|
-
text.lines,
|
|
1043
|
-
vec![
|
|
1044
|
-
Line::from("The first line"),
|
|
1045
|
-
Line::from("The second line"),
|
|
1046
|
-
Line::from("The third line"),
|
|
1047
|
-
Line::from("The fourth line"),
|
|
1048
|
-
]
|
|
1049
|
-
);
|
|
1050
|
-
}
|
|
1051
|
-
|
|
1052
|
-
#[rstest]
|
|
1053
|
-
#[case::one_line("The first line")]
|
|
1054
|
-
#[case::multiple_lines("The first line\nThe second line")]
|
|
1055
|
-
fn display_raw_text(#[case] value: &str) {
|
|
1056
|
-
let text = Text::raw(value);
|
|
1057
|
-
assert_eq!(format!("{text}"), value);
|
|
1058
|
-
}
|
|
1059
|
-
|
|
1060
|
-
#[test]
|
|
1061
|
-
fn display_styled_text() {
|
|
1062
|
-
let styled_text = Text::styled(
|
|
1063
|
-
"The first line\nThe second line",
|
|
1064
|
-
Style::new().yellow().italic(),
|
|
1065
|
-
);
|
|
1066
|
-
|
|
1067
|
-
assert_eq!(format!("{styled_text}"), "The first line\nThe second line");
|
|
1068
|
-
}
|
|
1069
|
-
|
|
1070
|
-
#[test]
|
|
1071
|
-
fn display_text_from_vec() {
|
|
1072
|
-
let text_from_vec = Text::from(vec![
|
|
1073
|
-
Line::from("The first line"),
|
|
1074
|
-
Line::from("The second line"),
|
|
1075
|
-
]);
|
|
1076
|
-
|
|
1077
|
-
assert_eq!(
|
|
1078
|
-
format!("{text_from_vec}"),
|
|
1079
|
-
"The first line\nThe second line"
|
|
1080
|
-
);
|
|
1081
|
-
}
|
|
1082
|
-
|
|
1083
|
-
#[test]
|
|
1084
|
-
fn display_extended_text() {
|
|
1085
|
-
let mut text = Text::from("The first line\nThe second line");
|
|
1086
|
-
|
|
1087
|
-
assert_eq!(format!("{text}"), "The first line\nThe second line");
|
|
1088
|
-
|
|
1089
|
-
text.extend(vec![
|
|
1090
|
-
Line::from("The third line"),
|
|
1091
|
-
Line::from("The fourth line"),
|
|
1092
|
-
]);
|
|
1093
|
-
|
|
1094
|
-
assert_eq!(
|
|
1095
|
-
format!("{text}"),
|
|
1096
|
-
"The first line\nThe second line\nThe third line\nThe fourth line"
|
|
1097
|
-
);
|
|
1098
|
-
}
|
|
1099
|
-
|
|
1100
|
-
#[test]
|
|
1101
|
-
fn stylize() {
|
|
1102
|
-
assert_eq!(Text::default().green().style, Color::Green.into());
|
|
1103
|
-
assert_eq!(
|
|
1104
|
-
Text::default().on_green().style,
|
|
1105
|
-
Style::new().bg(Color::Green)
|
|
1106
|
-
);
|
|
1107
|
-
assert_eq!(Text::default().italic().style, Modifier::ITALIC.into());
|
|
1108
|
-
}
|
|
1109
|
-
|
|
1110
|
-
#[test]
|
|
1111
|
-
fn left_aligned() {
|
|
1112
|
-
let text = Text::from("Hello, world!").left_aligned();
|
|
1113
|
-
assert_eq!(text.alignment, Some(Alignment::Left));
|
|
1114
|
-
}
|
|
1115
|
-
|
|
1116
|
-
#[test]
|
|
1117
|
-
fn centered() {
|
|
1118
|
-
let text = Text::from("Hello, world!").centered();
|
|
1119
|
-
assert_eq!(text.alignment, Some(Alignment::Center));
|
|
1120
|
-
}
|
|
1121
|
-
|
|
1122
|
-
#[test]
|
|
1123
|
-
fn right_aligned() {
|
|
1124
|
-
let text = Text::from("Hello, world!").right_aligned();
|
|
1125
|
-
assert_eq!(text.alignment, Some(Alignment::Right));
|
|
1126
|
-
}
|
|
1127
|
-
|
|
1128
|
-
#[test]
|
|
1129
|
-
fn push_line() {
|
|
1130
|
-
let mut text = Text::from("A");
|
|
1131
|
-
text.push_line(Line::from("B"));
|
|
1132
|
-
text.push_line(Span::from("C"));
|
|
1133
|
-
text.push_line("D");
|
|
1134
|
-
assert_eq!(
|
|
1135
|
-
text.lines,
|
|
1136
|
-
vec![
|
|
1137
|
-
Line::raw("A"),
|
|
1138
|
-
Line::raw("B"),
|
|
1139
|
-
Line::raw("C"),
|
|
1140
|
-
Line::raw("D")
|
|
1141
|
-
]
|
|
1142
|
-
);
|
|
1143
|
-
}
|
|
1144
|
-
|
|
1145
|
-
#[test]
|
|
1146
|
-
fn push_line_empty() {
|
|
1147
|
-
let mut text = Text::default();
|
|
1148
|
-
text.push_line(Line::from("Hello, world!"));
|
|
1149
|
-
assert_eq!(text.lines, [Line::from("Hello, world!")]);
|
|
1150
|
-
}
|
|
1151
|
-
|
|
1152
|
-
#[test]
|
|
1153
|
-
fn push_span() {
|
|
1154
|
-
let mut text = Text::from("A");
|
|
1155
|
-
text.push_span(Span::raw("B"));
|
|
1156
|
-
text.push_span("C");
|
|
1157
|
-
assert_eq!(
|
|
1158
|
-
text.lines,
|
|
1159
|
-
vec![Line::from(vec![
|
|
1160
|
-
Span::raw("A"),
|
|
1161
|
-
Span::raw("B"),
|
|
1162
|
-
Span::raw("C")
|
|
1163
|
-
])],
|
|
1164
|
-
);
|
|
1165
|
-
}
|
|
1166
|
-
|
|
1167
|
-
#[test]
|
|
1168
|
-
fn push_span_empty() {
|
|
1169
|
-
let mut text = Text::default();
|
|
1170
|
-
text.push_span(Span::raw("Hello, world!"));
|
|
1171
|
-
assert_eq!(text.lines, [Line::from(Span::raw("Hello, world!"))]);
|
|
1172
|
-
}
|
|
1173
|
-
|
|
1174
|
-
mod widget {
|
|
1175
|
-
use super::*;
|
|
1176
|
-
|
|
1177
|
-
#[test]
|
|
1178
|
-
fn render() {
|
|
1179
|
-
let text = Text::from("foo");
|
|
1180
|
-
let area = Rect::new(0, 0, 5, 1);
|
|
1181
|
-
let mut buf = Buffer::empty(area);
|
|
1182
|
-
text.render(area, &mut buf);
|
|
1183
|
-
assert_eq!(buf, Buffer::with_lines(["foo "]));
|
|
1184
|
-
}
|
|
1185
|
-
|
|
1186
|
-
#[rstest]
|
|
1187
|
-
fn render_out_of_bounds(mut small_buf: Buffer) {
|
|
1188
|
-
let out_of_bounds_area = Rect::new(20, 20, 10, 1);
|
|
1189
|
-
Text::from("Hello, world!").render(out_of_bounds_area, &mut small_buf);
|
|
1190
|
-
assert_eq!(small_buf, Buffer::empty(small_buf.area));
|
|
1191
|
-
}
|
|
1192
|
-
|
|
1193
|
-
#[test]
|
|
1194
|
-
fn render_right_aligned() {
|
|
1195
|
-
let text = Text::from("foo").alignment(Alignment::Right);
|
|
1196
|
-
let area = Rect::new(0, 0, 5, 1);
|
|
1197
|
-
let mut buf = Buffer::empty(area);
|
|
1198
|
-
text.render(area, &mut buf);
|
|
1199
|
-
assert_eq!(buf, Buffer::with_lines([" foo"]));
|
|
1200
|
-
}
|
|
1201
|
-
|
|
1202
|
-
#[test]
|
|
1203
|
-
fn render_centered_odd() {
|
|
1204
|
-
let text = Text::from("foo").alignment(Alignment::Center);
|
|
1205
|
-
let area = Rect::new(0, 0, 5, 1);
|
|
1206
|
-
let mut buf = Buffer::empty(area);
|
|
1207
|
-
text.render(area, &mut buf);
|
|
1208
|
-
assert_eq!(buf, Buffer::with_lines([" foo "]));
|
|
1209
|
-
}
|
|
1210
|
-
|
|
1211
|
-
#[test]
|
|
1212
|
-
fn render_centered_even() {
|
|
1213
|
-
let text = Text::from("foo").alignment(Alignment::Center);
|
|
1214
|
-
let area = Rect::new(0, 0, 6, 1);
|
|
1215
|
-
let mut buf = Buffer::empty(area);
|
|
1216
|
-
text.render(area, &mut buf);
|
|
1217
|
-
assert_eq!(buf, Buffer::with_lines([" foo "]));
|
|
1218
|
-
}
|
|
1219
|
-
|
|
1220
|
-
#[test]
|
|
1221
|
-
fn render_right_aligned_with_truncation() {
|
|
1222
|
-
let text = Text::from("123456789").alignment(Alignment::Right);
|
|
1223
|
-
let area = Rect::new(0, 0, 5, 1);
|
|
1224
|
-
let mut buf = Buffer::empty(area);
|
|
1225
|
-
text.render(area, &mut buf);
|
|
1226
|
-
assert_eq!(buf, Buffer::with_lines(["56789"]));
|
|
1227
|
-
}
|
|
1228
|
-
|
|
1229
|
-
#[test]
|
|
1230
|
-
fn render_centered_odd_with_truncation() {
|
|
1231
|
-
let text = Text::from("123456789").alignment(Alignment::Center);
|
|
1232
|
-
let area = Rect::new(0, 0, 5, 1);
|
|
1233
|
-
let mut buf = Buffer::empty(area);
|
|
1234
|
-
text.render(area, &mut buf);
|
|
1235
|
-
assert_eq!(buf, Buffer::with_lines(["34567"]));
|
|
1236
|
-
}
|
|
1237
|
-
|
|
1238
|
-
#[test]
|
|
1239
|
-
fn render_centered_even_with_truncation() {
|
|
1240
|
-
let text = Text::from("123456789").alignment(Alignment::Center);
|
|
1241
|
-
let area = Rect::new(0, 0, 6, 1);
|
|
1242
|
-
let mut buf = Buffer::empty(area);
|
|
1243
|
-
text.render(area, &mut buf);
|
|
1244
|
-
assert_eq!(buf, Buffer::with_lines(["234567"]));
|
|
1245
|
-
}
|
|
1246
|
-
|
|
1247
|
-
#[test]
|
|
1248
|
-
fn render_one_line_right() {
|
|
1249
|
-
let text = Text::from(vec![
|
|
1250
|
-
"foo".into(),
|
|
1251
|
-
Line::from("bar").alignment(Alignment::Center),
|
|
1252
|
-
])
|
|
1253
|
-
.alignment(Alignment::Right);
|
|
1254
|
-
let area = Rect::new(0, 0, 5, 2);
|
|
1255
|
-
let mut buf = Buffer::empty(area);
|
|
1256
|
-
text.render(area, &mut buf);
|
|
1257
|
-
assert_eq!(buf, Buffer::with_lines([" foo", " bar "]));
|
|
1258
|
-
}
|
|
1259
|
-
|
|
1260
|
-
#[test]
|
|
1261
|
-
fn render_only_styles_line_area() {
|
|
1262
|
-
let area = Rect::new(0, 0, 5, 1);
|
|
1263
|
-
let mut buf = Buffer::empty(area);
|
|
1264
|
-
Text::from("foo".on_blue()).render(area, &mut buf);
|
|
1265
|
-
|
|
1266
|
-
let mut expected = Buffer::with_lines(["foo "]);
|
|
1267
|
-
expected.set_style(Rect::new(0, 0, 3, 1), Style::new().bg(Color::Blue));
|
|
1268
|
-
assert_eq!(buf, expected);
|
|
1269
|
-
}
|
|
1270
|
-
|
|
1271
|
-
#[test]
|
|
1272
|
-
fn render_truncates() {
|
|
1273
|
-
let mut buf = Buffer::empty(Rect::new(0, 0, 6, 1));
|
|
1274
|
-
Text::from("foobar".on_blue()).render(Rect::new(0, 0, 3, 1), &mut buf);
|
|
1275
|
-
|
|
1276
|
-
let mut expected = Buffer::with_lines(["foo "]);
|
|
1277
|
-
expected.set_style(Rect::new(0, 0, 3, 1), Style::new().bg(Color::Blue));
|
|
1278
|
-
assert_eq!(buf, expected);
|
|
1279
|
-
}
|
|
1280
|
-
}
|
|
1281
|
-
|
|
1282
|
-
mod iterators {
|
|
1283
|
-
use super::*;
|
|
1284
|
-
|
|
1285
|
-
/// a fixture used in the tests below to avoid repeating the same setup
|
|
1286
|
-
#[fixture]
|
|
1287
|
-
fn hello_world() -> Text<'static> {
|
|
1288
|
-
Text::from(vec![
|
|
1289
|
-
Line::styled("Hello ", Color::Blue),
|
|
1290
|
-
Line::styled("world!", Color::Green),
|
|
1291
|
-
])
|
|
1292
|
-
}
|
|
1293
|
-
|
|
1294
|
-
#[rstest]
|
|
1295
|
-
fn iter(hello_world: Text<'_>) {
|
|
1296
|
-
let mut iter = hello_world.iter();
|
|
1297
|
-
assert_eq!(iter.next(), Some(&Line::styled("Hello ", Color::Blue)));
|
|
1298
|
-
assert_eq!(iter.next(), Some(&Line::styled("world!", Color::Green)));
|
|
1299
|
-
assert_eq!(iter.next(), None);
|
|
1300
|
-
}
|
|
1301
|
-
|
|
1302
|
-
#[rstest]
|
|
1303
|
-
fn iter_mut(mut hello_world: Text<'_>) {
|
|
1304
|
-
let mut iter = hello_world.iter_mut();
|
|
1305
|
-
assert_eq!(iter.next(), Some(&mut Line::styled("Hello ", Color::Blue)));
|
|
1306
|
-
assert_eq!(iter.next(), Some(&mut Line::styled("world!", Color::Green)));
|
|
1307
|
-
assert_eq!(iter.next(), None);
|
|
1308
|
-
}
|
|
1309
|
-
|
|
1310
|
-
#[rstest]
|
|
1311
|
-
fn into_iter(hello_world: Text<'_>) {
|
|
1312
|
-
let mut iter = hello_world.into_iter();
|
|
1313
|
-
assert_eq!(iter.next(), Some(Line::styled("Hello ", Color::Blue)));
|
|
1314
|
-
assert_eq!(iter.next(), Some(Line::styled("world!", Color::Green)));
|
|
1315
|
-
assert_eq!(iter.next(), None);
|
|
1316
|
-
}
|
|
1317
|
-
|
|
1318
|
-
#[rstest]
|
|
1319
|
-
fn into_iter_ref(hello_world: Text<'_>) {
|
|
1320
|
-
let mut iter = (&hello_world).into_iter();
|
|
1321
|
-
assert_eq!(iter.next(), Some(&Line::styled("Hello ", Color::Blue)));
|
|
1322
|
-
assert_eq!(iter.next(), Some(&Line::styled("world!", Color::Green)));
|
|
1323
|
-
assert_eq!(iter.next(), None);
|
|
1324
|
-
}
|
|
1325
|
-
|
|
1326
|
-
#[test]
|
|
1327
|
-
fn into_iter_mut_ref() {
|
|
1328
|
-
let mut hello_world = Text::from(vec![
|
|
1329
|
-
Line::styled("Hello ", Color::Blue),
|
|
1330
|
-
Line::styled("world!", Color::Green),
|
|
1331
|
-
]);
|
|
1332
|
-
let mut iter = (&mut hello_world).into_iter();
|
|
1333
|
-
assert_eq!(iter.next(), Some(&mut Line::styled("Hello ", Color::Blue)));
|
|
1334
|
-
assert_eq!(iter.next(), Some(&mut Line::styled("world!", Color::Green)));
|
|
1335
|
-
assert_eq!(iter.next(), None);
|
|
1336
|
-
}
|
|
1337
|
-
|
|
1338
|
-
#[rstest]
|
|
1339
|
-
fn for_loop_ref(hello_world: Text<'_>) {
|
|
1340
|
-
let mut result = String::new();
|
|
1341
|
-
for line in &hello_world {
|
|
1342
|
-
result.push_str(line.to_string().as_ref());
|
|
1343
|
-
}
|
|
1344
|
-
assert_eq!(result, "Hello world!");
|
|
1345
|
-
}
|
|
1346
|
-
|
|
1347
|
-
#[rstest]
|
|
1348
|
-
fn for_loop_mut_ref() {
|
|
1349
|
-
let mut hello_world = Text::from(vec![
|
|
1350
|
-
Line::styled("Hello ", Color::Blue),
|
|
1351
|
-
Line::styled("world!", Color::Green),
|
|
1352
|
-
]);
|
|
1353
|
-
let mut result = String::new();
|
|
1354
|
-
for line in &mut hello_world {
|
|
1355
|
-
result.push_str(line.to_string().as_ref());
|
|
1356
|
-
}
|
|
1357
|
-
assert_eq!(result, "Hello world!");
|
|
1358
|
-
}
|
|
1359
|
-
|
|
1360
|
-
#[rstest]
|
|
1361
|
-
fn for_loop_into(hello_world: Text<'_>) {
|
|
1362
|
-
let mut result = String::new();
|
|
1363
|
-
for line in hello_world {
|
|
1364
|
-
result.push_str(line.to_string().as_ref());
|
|
1365
|
-
}
|
|
1366
|
-
assert_eq!(result, "Hello world!");
|
|
1367
|
-
}
|
|
1368
|
-
}
|
|
1369
|
-
|
|
1370
|
-
#[rstest]
|
|
1371
|
-
#[case::default(Text::default(), "Text::default()")]
|
|
1372
|
-
// TODO jm: these could be improved to inspect the line / span if there's only one. e.g.
|
|
1373
|
-
// Text::from("Hello, world!") and Text::from("Hello, world!".blue()) but the current
|
|
1374
|
-
// implementation is good enough for now.
|
|
1375
|
-
#[case::raw(
|
|
1376
|
-
Text::raw("Hello, world!"),
|
|
1377
|
-
r#"Text::from(Line::from("Hello, world!"))"#
|
|
1378
|
-
)]
|
|
1379
|
-
#[case::styled(
|
|
1380
|
-
Text::styled("Hello, world!", Color::Yellow),
|
|
1381
|
-
r#"Text::from(Line::from("Hello, world!")).yellow()"#
|
|
1382
|
-
)]
|
|
1383
|
-
#[case::complex_styled(
|
|
1384
|
-
Text::from("Hello, world!").yellow().on_blue().bold().italic().not_dim().not_hidden(),
|
|
1385
|
-
r#"Text::from(Line::from("Hello, world!")).yellow().on_blue().bold().italic().not_dim().not_hidden()"#
|
|
1386
|
-
)]
|
|
1387
|
-
#[case::alignment(
|
|
1388
|
-
Text::from("Hello, world!").centered(),
|
|
1389
|
-
r#"Text::from(Line::from("Hello, world!")).centered()"#
|
|
1390
|
-
)]
|
|
1391
|
-
#[case::styled_alignment(
|
|
1392
|
-
Text::styled("Hello, world!", Color::Yellow).centered(),
|
|
1393
|
-
r#"Text::from(Line::from("Hello, world!")).yellow().centered()"#
|
|
1394
|
-
)]
|
|
1395
|
-
#[case::multiple_lines(
|
|
1396
|
-
Text::from(vec![
|
|
1397
|
-
Line::from("Hello, world!"),
|
|
1398
|
-
Line::from("How are you?")
|
|
1399
|
-
]),
|
|
1400
|
-
r#"Text::from_iter([Line::from("Hello, world!"), Line::from("How are you?")])"#
|
|
1401
|
-
)]
|
|
1402
|
-
fn debug(#[case] text: Text, #[case] expected: &str) {
|
|
1403
|
-
assert_eq!(format!("{text:?}"), expected);
|
|
1404
|
-
}
|
|
1405
|
-
|
|
1406
|
-
#[test]
|
|
1407
|
-
fn debug_alternate() {
|
|
1408
|
-
let text = Text::from_iter([
|
|
1409
|
-
Line::from("Hello, world!"),
|
|
1410
|
-
Line::from("How are you?").bold().left_aligned(),
|
|
1411
|
-
Line::from_iter([
|
|
1412
|
-
Span::from("I'm "),
|
|
1413
|
-
Span::from("doing ").italic(),
|
|
1414
|
-
Span::from("great!").bold(),
|
|
1415
|
-
]),
|
|
1416
|
-
])
|
|
1417
|
-
.on_blue()
|
|
1418
|
-
.italic()
|
|
1419
|
-
.centered();
|
|
1420
|
-
assert_eq!(
|
|
1421
|
-
format!("{text:#?}"),
|
|
1422
|
-
indoc::indoc! {r#"
|
|
1423
|
-
Text::from_iter([
|
|
1424
|
-
Line::from("Hello, world!"),
|
|
1425
|
-
Line::from("How are you?").bold().left_aligned(),
|
|
1426
|
-
Line::from_iter([
|
|
1427
|
-
Span::from("I'm "),
|
|
1428
|
-
Span::from("doing ").italic(),
|
|
1429
|
-
Span::from("great!").bold(),
|
|
1430
|
-
]),
|
|
1431
|
-
]).on_blue().italic().centered()"#}
|
|
1432
|
-
);
|
|
1433
|
-
}
|
|
1434
|
-
}
|