@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,1069 +0,0 @@
|
|
|
1
|
-
//! `style` contains the primitives used to control how your user interface will look.
|
|
2
|
-
//!
|
|
3
|
-
//! There are two ways to set styles:
|
|
4
|
-
//! - Creating and using the [`Style`] struct. (e.g. `Style::new().fg(Color::Red)`).
|
|
5
|
-
//! - Using style shorthands. (e.g. `"hello".red()`).
|
|
6
|
-
//!
|
|
7
|
-
//! # Using the `Style` struct
|
|
8
|
-
//!
|
|
9
|
-
//! This is the original approach to styling and likely the most common. This is useful when
|
|
10
|
-
//! creating style variables to reuse, however the shorthands are often more convenient and
|
|
11
|
-
//! readable for most use cases.
|
|
12
|
-
//!
|
|
13
|
-
//! ## Example
|
|
14
|
-
//!
|
|
15
|
-
//! ```
|
|
16
|
-
//! use ratatui_core::style::{Color, Modifier, Style};
|
|
17
|
-
//! use ratatui_core::text::Span;
|
|
18
|
-
//!
|
|
19
|
-
//! let heading_style = Style::new()
|
|
20
|
-
//! .fg(Color::Black)
|
|
21
|
-
//! .bg(Color::Green)
|
|
22
|
-
//! .add_modifier(Modifier::ITALIC | Modifier::BOLD);
|
|
23
|
-
//! let span = Span::styled("hello", heading_style);
|
|
24
|
-
//! ```
|
|
25
|
-
//!
|
|
26
|
-
//! # Using style shorthands
|
|
27
|
-
//!
|
|
28
|
-
//! Originally Ratatui only had the ability to set styles using the `Style` struct. This is still
|
|
29
|
-
//! supported, but there are now shorthands for all the styles that can be set. These save you from
|
|
30
|
-
//! having to create a `Style` struct every time you want to set a style.
|
|
31
|
-
//!
|
|
32
|
-
//! The shorthands are implemented in the [`Stylize`] trait which is automatically implemented for
|
|
33
|
-
//! many types via the [`Styled`] trait. This means that you can use the shorthands on any type
|
|
34
|
-
//! that implements [`Styled`]. E.g.:
|
|
35
|
-
//! - Strings and string slices when styled return a [`Span`]
|
|
36
|
-
//! - [`Span`]s can be styled again, which will merge the styles.
|
|
37
|
-
//! - Many widget types can be styled directly rather than calling their `style()` method.
|
|
38
|
-
//!
|
|
39
|
-
//! See the [`Stylize`] and [`Styled`] traits for more information.
|
|
40
|
-
//!
|
|
41
|
-
//! ## Example
|
|
42
|
-
//!
|
|
43
|
-
//! ```
|
|
44
|
-
//! use ratatui_core::style::{Color, Modifier, Style, Stylize};
|
|
45
|
-
//! use ratatui_core::text::{Span, Text};
|
|
46
|
-
//!
|
|
47
|
-
//! assert_eq!(
|
|
48
|
-
//! "hello".red().on_blue().bold(),
|
|
49
|
-
//! Span::styled(
|
|
50
|
-
//! "hello",
|
|
51
|
-
//! Style::default()
|
|
52
|
-
//! .fg(Color::Red)
|
|
53
|
-
//! .bg(Color::Blue)
|
|
54
|
-
//! .add_modifier(Modifier::BOLD)
|
|
55
|
-
//! )
|
|
56
|
-
//! );
|
|
57
|
-
//!
|
|
58
|
-
//! assert_eq!(
|
|
59
|
-
//! Text::from("hello").red().on_blue().bold(),
|
|
60
|
-
//! Text::from("hello").style(
|
|
61
|
-
//! Style::default()
|
|
62
|
-
//! .fg(Color::Red)
|
|
63
|
-
//! .bg(Color::Blue)
|
|
64
|
-
//! .add_modifier(Modifier::BOLD)
|
|
65
|
-
//! )
|
|
66
|
-
//! );
|
|
67
|
-
//! ```
|
|
68
|
-
//!
|
|
69
|
-
//! [`Span`]: crate::text::Span
|
|
70
|
-
|
|
71
|
-
use core::fmt;
|
|
72
|
-
|
|
73
|
-
use bitflags::bitflags;
|
|
74
|
-
pub use color::{Color, ParseColorError};
|
|
75
|
-
use stylize::ColorDebugKind;
|
|
76
|
-
pub use stylize::{Styled, Stylize};
|
|
77
|
-
|
|
78
|
-
#[cfg(feature = "anstyle")]
|
|
79
|
-
mod anstyle;
|
|
80
|
-
mod color;
|
|
81
|
-
pub mod palette;
|
|
82
|
-
#[cfg(feature = "palette")]
|
|
83
|
-
mod palette_conversion;
|
|
84
|
-
#[macro_use]
|
|
85
|
-
mod stylize;
|
|
86
|
-
|
|
87
|
-
bitflags! {
|
|
88
|
-
/// Modifier changes the way a piece of text is displayed.
|
|
89
|
-
///
|
|
90
|
-
/// They are bitflags so they can easily be composed.
|
|
91
|
-
///
|
|
92
|
-
/// `From<Modifier> for Style` is implemented so you can use `Modifier` anywhere that accepts
|
|
93
|
-
/// `Into<Style>`.
|
|
94
|
-
///
|
|
95
|
-
/// ## Examples
|
|
96
|
-
///
|
|
97
|
-
/// ```rust
|
|
98
|
-
/// use ratatui_core::style::Modifier;
|
|
99
|
-
///
|
|
100
|
-
/// let m = Modifier::BOLD | Modifier::ITALIC;
|
|
101
|
-
/// ```
|
|
102
|
-
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
|
103
|
-
#[derive(Default, Clone, Copy, Eq, PartialEq, Hash)]
|
|
104
|
-
pub struct Modifier: u16 {
|
|
105
|
-
const BOLD = 0b0000_0000_0001;
|
|
106
|
-
const DIM = 0b0000_0000_0010;
|
|
107
|
-
const ITALIC = 0b0000_0000_0100;
|
|
108
|
-
const UNDERLINED = 0b0000_0000_1000;
|
|
109
|
-
const SLOW_BLINK = 0b0000_0001_0000;
|
|
110
|
-
const RAPID_BLINK = 0b0000_0010_0000;
|
|
111
|
-
const REVERSED = 0b0000_0100_0000;
|
|
112
|
-
const HIDDEN = 0b0000_1000_0000;
|
|
113
|
-
const CROSSED_OUT = 0b0001_0000_0000;
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
/// Implement the `Debug` trait for `Modifier` manually.
|
|
118
|
-
///
|
|
119
|
-
/// This will avoid printing the empty modifier as 'Borders(0x0)' and instead print it as 'NONE'.
|
|
120
|
-
impl fmt::Debug for Modifier {
|
|
121
|
-
/// Format the modifier as `NONE` if the modifier is empty or as a list of flags separated by
|
|
122
|
-
/// `|` otherwise.
|
|
123
|
-
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
124
|
-
if self.is_empty() {
|
|
125
|
-
return write!(f, "NONE");
|
|
126
|
-
}
|
|
127
|
-
write!(f, "{}", self.0)
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
/// Style lets you control the main characteristics of the displayed elements.
|
|
132
|
-
///
|
|
133
|
-
/// ```rust
|
|
134
|
-
/// use ratatui_core::style::{Color, Modifier, Style};
|
|
135
|
-
///
|
|
136
|
-
/// Style::default()
|
|
137
|
-
/// .fg(Color::Black)
|
|
138
|
-
/// .bg(Color::Green)
|
|
139
|
-
/// .add_modifier(Modifier::ITALIC | Modifier::BOLD);
|
|
140
|
-
/// ```
|
|
141
|
-
///
|
|
142
|
-
/// Styles can also be created with a [shorthand notation](crate::style#using-style-shorthands).
|
|
143
|
-
///
|
|
144
|
-
/// ```rust
|
|
145
|
-
/// use ratatui_core::style::{Style, Stylize};
|
|
146
|
-
///
|
|
147
|
-
/// Style::new().black().on_green().italic().bold();
|
|
148
|
-
/// ```
|
|
149
|
-
///
|
|
150
|
-
/// For more information about the style shorthands, see the [`Stylize`] trait.
|
|
151
|
-
///
|
|
152
|
-
/// We implement conversions from [`Color`] and [`Modifier`] to [`Style`] so you can use them
|
|
153
|
-
/// anywhere that accepts `Into<Style>`.
|
|
154
|
-
///
|
|
155
|
-
/// ```rust
|
|
156
|
-
/// use ratatui_core::style::{Color, Modifier, Style};
|
|
157
|
-
/// use ratatui_core::text::Line;
|
|
158
|
-
///
|
|
159
|
-
/// Line::styled("hello", Style::new().fg(Color::Red));
|
|
160
|
-
/// // simplifies to
|
|
161
|
-
/// Line::styled("hello", Color::Red);
|
|
162
|
-
///
|
|
163
|
-
/// Line::styled("hello", Style::new().add_modifier(Modifier::BOLD));
|
|
164
|
-
/// // simplifies to
|
|
165
|
-
/// Line::styled("hello", Modifier::BOLD);
|
|
166
|
-
/// ```
|
|
167
|
-
///
|
|
168
|
-
/// Styles represents an incremental change. If you apply the styles S1, S2, S3 to a cell of the
|
|
169
|
-
/// terminal buffer, the style of this cell will be the result of the merge of S1, S2 and S3, not
|
|
170
|
-
/// just S3.
|
|
171
|
-
///
|
|
172
|
-
/// ```rust
|
|
173
|
-
/// use ratatui_core::buffer::Buffer;
|
|
174
|
-
/// use ratatui_core::layout::Rect;
|
|
175
|
-
/// use ratatui_core::style::{Color, Modifier, Style};
|
|
176
|
-
///
|
|
177
|
-
/// let styles = [
|
|
178
|
-
/// Style::default()
|
|
179
|
-
/// .fg(Color::Blue)
|
|
180
|
-
/// .add_modifier(Modifier::BOLD | Modifier::ITALIC),
|
|
181
|
-
/// Style::default()
|
|
182
|
-
/// .bg(Color::Red)
|
|
183
|
-
/// .add_modifier(Modifier::UNDERLINED),
|
|
184
|
-
/// #[cfg(feature = "underline-color")]
|
|
185
|
-
/// Style::default().underline_color(Color::Green),
|
|
186
|
-
/// Style::default()
|
|
187
|
-
/// .fg(Color::Yellow)
|
|
188
|
-
/// .remove_modifier(Modifier::ITALIC),
|
|
189
|
-
/// ];
|
|
190
|
-
/// let mut buffer = Buffer::empty(Rect::new(0, 0, 1, 1));
|
|
191
|
-
/// for style in &styles {
|
|
192
|
-
/// buffer[(0, 0)].set_style(*style);
|
|
193
|
-
/// }
|
|
194
|
-
/// assert_eq!(
|
|
195
|
-
/// Style {
|
|
196
|
-
/// fg: Some(Color::Yellow),
|
|
197
|
-
/// bg: Some(Color::Red),
|
|
198
|
-
/// #[cfg(feature = "underline-color")]
|
|
199
|
-
/// underline_color: Some(Color::Green),
|
|
200
|
-
/// add_modifier: Modifier::BOLD | Modifier::UNDERLINED,
|
|
201
|
-
/// sub_modifier: Modifier::empty(),
|
|
202
|
-
/// },
|
|
203
|
-
/// buffer[(0, 0)].style(),
|
|
204
|
-
/// );
|
|
205
|
-
/// ```
|
|
206
|
-
///
|
|
207
|
-
/// The default implementation returns a `Style` that does not modify anything. If you wish to
|
|
208
|
-
/// reset all properties until that point use [`Style::reset`].
|
|
209
|
-
///
|
|
210
|
-
/// ```
|
|
211
|
-
/// use ratatui_core::buffer::Buffer;
|
|
212
|
-
/// use ratatui_core::layout::Rect;
|
|
213
|
-
/// use ratatui_core::style::{Color, Modifier, Style};
|
|
214
|
-
///
|
|
215
|
-
/// let styles = [
|
|
216
|
-
/// Style::default()
|
|
217
|
-
/// .fg(Color::Blue)
|
|
218
|
-
/// .add_modifier(Modifier::BOLD | Modifier::ITALIC),
|
|
219
|
-
/// Style::reset().fg(Color::Yellow),
|
|
220
|
-
/// ];
|
|
221
|
-
/// let mut buffer = Buffer::empty(Rect::new(0, 0, 1, 1));
|
|
222
|
-
/// for style in &styles {
|
|
223
|
-
/// buffer[(0, 0)].set_style(*style);
|
|
224
|
-
/// }
|
|
225
|
-
/// assert_eq!(
|
|
226
|
-
/// Style {
|
|
227
|
-
/// fg: Some(Color::Yellow),
|
|
228
|
-
/// bg: Some(Color::Reset),
|
|
229
|
-
/// #[cfg(feature = "underline-color")]
|
|
230
|
-
/// underline_color: Some(Color::Reset),
|
|
231
|
-
/// add_modifier: Modifier::empty(),
|
|
232
|
-
/// sub_modifier: Modifier::empty(),
|
|
233
|
-
/// },
|
|
234
|
-
/// buffer[(0, 0)].style(),
|
|
235
|
-
/// );
|
|
236
|
-
/// ```
|
|
237
|
-
#[derive(Default, Clone, Copy, Eq, PartialEq, Hash)]
|
|
238
|
-
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
|
239
|
-
pub struct Style {
|
|
240
|
-
/// The foreground color.
|
|
241
|
-
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
|
|
242
|
-
pub fg: Option<Color>,
|
|
243
|
-
/// The background color.
|
|
244
|
-
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
|
|
245
|
-
pub bg: Option<Color>,
|
|
246
|
-
/// The underline color.
|
|
247
|
-
#[cfg(feature = "underline-color")]
|
|
248
|
-
#[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
|
|
249
|
-
pub underline_color: Option<Color>,
|
|
250
|
-
/// The modifiers to add.
|
|
251
|
-
#[cfg_attr(
|
|
252
|
-
feature = "serde",
|
|
253
|
-
serde(
|
|
254
|
-
default,
|
|
255
|
-
skip_serializing_if = "Modifier::is_empty",
|
|
256
|
-
deserialize_with = "deserialize_modifier"
|
|
257
|
-
)
|
|
258
|
-
)]
|
|
259
|
-
pub add_modifier: Modifier,
|
|
260
|
-
/// The modifiers to remove.
|
|
261
|
-
#[cfg_attr(
|
|
262
|
-
feature = "serde",
|
|
263
|
-
serde(
|
|
264
|
-
default,
|
|
265
|
-
skip_serializing_if = "Modifier::is_empty",
|
|
266
|
-
deserialize_with = "deserialize_modifier"
|
|
267
|
-
)
|
|
268
|
-
)]
|
|
269
|
-
pub sub_modifier: Modifier,
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
#[cfg(feature = "serde")]
|
|
273
|
-
/// Deserialize a [`Modifier`] while treating missing or `null` values as empty.
|
|
274
|
-
///
|
|
275
|
-
/// This helper is used with serde to coerce absent or `null` modifier fields to
|
|
276
|
-
/// [`Modifier::empty`], allowing configuration files to omit these fields
|
|
277
|
-
/// without triggering deserialization errors.
|
|
278
|
-
fn deserialize_modifier<'de, D>(deserializer: D) -> Result<Modifier, D::Error>
|
|
279
|
-
where
|
|
280
|
-
D: serde::Deserializer<'de>,
|
|
281
|
-
{
|
|
282
|
-
use serde::Deserialize;
|
|
283
|
-
|
|
284
|
-
Option::<Modifier>::deserialize(deserializer)
|
|
285
|
-
.map(|modifier| modifier.unwrap_or_else(Modifier::empty))
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
/// A custom debug implementation that prints only the fields that are not the default, and unwraps
|
|
289
|
-
/// the `Option`s.
|
|
290
|
-
impl fmt::Debug for Style {
|
|
291
|
-
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
292
|
-
f.write_str("Style::new()")?;
|
|
293
|
-
self.fmt_stylize(f)?;
|
|
294
|
-
Ok(())
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
impl Style {
|
|
299
|
-
/// Returns a `Style` with default properties.
|
|
300
|
-
pub const fn new() -> Self {
|
|
301
|
-
Self {
|
|
302
|
-
fg: None,
|
|
303
|
-
bg: None,
|
|
304
|
-
#[cfg(feature = "underline-color")]
|
|
305
|
-
underline_color: None,
|
|
306
|
-
add_modifier: Modifier::empty(),
|
|
307
|
-
sub_modifier: Modifier::empty(),
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
/// Returns a `Style` resetting all properties.
|
|
312
|
-
pub const fn reset() -> Self {
|
|
313
|
-
Self {
|
|
314
|
-
fg: Some(Color::Reset),
|
|
315
|
-
bg: Some(Color::Reset),
|
|
316
|
-
#[cfg(feature = "underline-color")]
|
|
317
|
-
underline_color: Some(Color::Reset),
|
|
318
|
-
add_modifier: Modifier::empty(),
|
|
319
|
-
sub_modifier: Modifier::all(),
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
/// Changes the foreground color.
|
|
324
|
-
///
|
|
325
|
-
/// ## Examples
|
|
326
|
-
///
|
|
327
|
-
/// ```rust
|
|
328
|
-
/// use ratatui_core::style::{Color, Style};
|
|
329
|
-
///
|
|
330
|
-
/// let style = Style::default().fg(Color::Blue);
|
|
331
|
-
/// let diff = Style::default().fg(Color::Red);
|
|
332
|
-
/// assert_eq!(style.patch(diff), Style::default().fg(Color::Red));
|
|
333
|
-
/// ```
|
|
334
|
-
#[must_use = "`fg` returns the modified style without modifying the original"]
|
|
335
|
-
pub const fn fg(mut self, color: Color) -> Self {
|
|
336
|
-
self.fg = Some(color);
|
|
337
|
-
self
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
/// Changes the background color.
|
|
341
|
-
///
|
|
342
|
-
/// ## Examples
|
|
343
|
-
///
|
|
344
|
-
/// ```rust
|
|
345
|
-
/// use ratatui_core::style::{Color, Style};
|
|
346
|
-
///
|
|
347
|
-
/// let style = Style::default().bg(Color::Blue);
|
|
348
|
-
/// let diff = Style::default().bg(Color::Red);
|
|
349
|
-
/// assert_eq!(style.patch(diff), Style::default().bg(Color::Red));
|
|
350
|
-
/// ```
|
|
351
|
-
#[must_use = "`bg` returns the modified style without modifying the original"]
|
|
352
|
-
pub const fn bg(mut self, color: Color) -> Self {
|
|
353
|
-
self.bg = Some(color);
|
|
354
|
-
self
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
/// Changes the underline color. The text must be underlined with a modifier for this to work.
|
|
358
|
-
///
|
|
359
|
-
/// This uses a non-standard ANSI escape sequence. It is supported by most terminal emulators,
|
|
360
|
-
/// but is only implemented in the crossterm backend and enabled by the `underline-color`
|
|
361
|
-
/// feature flag.
|
|
362
|
-
///
|
|
363
|
-
/// See
|
|
364
|
-
/// [Wikipedia](https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_(Select_Graphic_Rendition)_parameters)
|
|
365
|
-
/// code `58` and `59` for more information.
|
|
366
|
-
///
|
|
367
|
-
/// ## Examples
|
|
368
|
-
///
|
|
369
|
-
/// ```rust
|
|
370
|
-
/// use ratatui_core::style::{Color, Modifier, Style};
|
|
371
|
-
///
|
|
372
|
-
/// let style = Style::default()
|
|
373
|
-
/// .underline_color(Color::Blue)
|
|
374
|
-
/// .add_modifier(Modifier::UNDERLINED);
|
|
375
|
-
/// let diff = Style::default()
|
|
376
|
-
/// .underline_color(Color::Red)
|
|
377
|
-
/// .add_modifier(Modifier::UNDERLINED);
|
|
378
|
-
/// assert_eq!(
|
|
379
|
-
/// style.patch(diff),
|
|
380
|
-
/// Style::default()
|
|
381
|
-
/// .underline_color(Color::Red)
|
|
382
|
-
/// .add_modifier(Modifier::UNDERLINED)
|
|
383
|
-
/// );
|
|
384
|
-
/// ```
|
|
385
|
-
#[cfg(feature = "underline-color")]
|
|
386
|
-
#[must_use = "`underline_color` returns the modified style without modifying the original"]
|
|
387
|
-
pub const fn underline_color(mut self, color: Color) -> Self {
|
|
388
|
-
self.underline_color = Some(color);
|
|
389
|
-
self
|
|
390
|
-
}
|
|
391
|
-
|
|
392
|
-
/// Changes the text emphasis.
|
|
393
|
-
///
|
|
394
|
-
/// When applied, it adds the given modifier to the `Style` modifiers.
|
|
395
|
-
///
|
|
396
|
-
/// ## Examples
|
|
397
|
-
///
|
|
398
|
-
/// ```rust
|
|
399
|
-
/// use ratatui_core::style::{Modifier, Style};
|
|
400
|
-
///
|
|
401
|
-
/// let style = Style::default().add_modifier(Modifier::BOLD);
|
|
402
|
-
/// let diff = Style::default().add_modifier(Modifier::ITALIC);
|
|
403
|
-
/// let patched = style.patch(diff);
|
|
404
|
-
/// assert_eq!(patched.add_modifier, Modifier::BOLD | Modifier::ITALIC);
|
|
405
|
-
/// assert_eq!(patched.sub_modifier, Modifier::empty());
|
|
406
|
-
/// ```
|
|
407
|
-
#[must_use = "`add_modifier` returns the modified style without modifying the original"]
|
|
408
|
-
pub const fn add_modifier(mut self, modifier: Modifier) -> Self {
|
|
409
|
-
self.sub_modifier = self.sub_modifier.difference(modifier);
|
|
410
|
-
self.add_modifier = self.add_modifier.union(modifier);
|
|
411
|
-
self
|
|
412
|
-
}
|
|
413
|
-
|
|
414
|
-
/// Changes the text emphasis.
|
|
415
|
-
///
|
|
416
|
-
/// When applied, it removes the given modifier from the `Style` modifiers.
|
|
417
|
-
///
|
|
418
|
-
/// ## Examples
|
|
419
|
-
///
|
|
420
|
-
/// ```rust
|
|
421
|
-
/// use ratatui_core::style::{Modifier, Style};
|
|
422
|
-
///
|
|
423
|
-
/// let style = Style::default().add_modifier(Modifier::BOLD | Modifier::ITALIC);
|
|
424
|
-
/// let diff = Style::default().remove_modifier(Modifier::ITALIC);
|
|
425
|
-
/// let patched = style.patch(diff);
|
|
426
|
-
/// assert_eq!(patched.add_modifier, Modifier::BOLD);
|
|
427
|
-
/// assert_eq!(patched.sub_modifier, Modifier::ITALIC);
|
|
428
|
-
/// ```
|
|
429
|
-
#[must_use = "`remove_modifier` returns the modified style without modifying the original"]
|
|
430
|
-
pub const fn remove_modifier(mut self, modifier: Modifier) -> Self {
|
|
431
|
-
self.add_modifier = self.add_modifier.difference(modifier);
|
|
432
|
-
self.sub_modifier = self.sub_modifier.union(modifier);
|
|
433
|
-
self
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
/// Returns `true` if the style has the given modifier set.
|
|
437
|
-
///
|
|
438
|
-
/// ## Examples
|
|
439
|
-
///
|
|
440
|
-
/// ```rust
|
|
441
|
-
/// use ratatui_core::style::{Modifier, Style};
|
|
442
|
-
///
|
|
443
|
-
/// let style = Style::default().add_modifier(Modifier::BOLD | Modifier::ITALIC);
|
|
444
|
-
/// assert!(style.has_modifier(Modifier::BOLD));
|
|
445
|
-
/// assert!(style.has_modifier(Modifier::ITALIC));
|
|
446
|
-
/// assert!(!style.has_modifier(Modifier::UNDERLINED));
|
|
447
|
-
/// ```
|
|
448
|
-
pub const fn has_modifier(self, modifier: Modifier) -> bool {
|
|
449
|
-
self.add_modifier.contains(modifier) && !self.sub_modifier.contains(modifier)
|
|
450
|
-
}
|
|
451
|
-
|
|
452
|
-
/// Results in a combined style that is equivalent to applying the two individual styles to
|
|
453
|
-
/// a style one after the other.
|
|
454
|
-
///
|
|
455
|
-
/// `style` accepts any type that is convertible to [`Style`] (e.g. [`Style`], [`Color`], or
|
|
456
|
-
/// your own type that implements [`Into<Style>`]).
|
|
457
|
-
///
|
|
458
|
-
/// ## Examples
|
|
459
|
-
/// ```
|
|
460
|
-
/// use ratatui_core::style::{Color, Modifier, Style};
|
|
461
|
-
///
|
|
462
|
-
/// let style_1 = Style::default().fg(Color::Yellow);
|
|
463
|
-
/// let style_2 = Style::default().bg(Color::Red);
|
|
464
|
-
/// let combined = style_1.patch(style_2);
|
|
465
|
-
/// assert_eq!(
|
|
466
|
-
/// Style::default().patch(style_1).patch(style_2),
|
|
467
|
-
/// Style::default().patch(combined)
|
|
468
|
-
/// );
|
|
469
|
-
/// ```
|
|
470
|
-
#[must_use = "`patch` returns the modified style without modifying the original"]
|
|
471
|
-
pub fn patch<S: Into<Self>>(mut self, other: S) -> Self {
|
|
472
|
-
let other = other.into();
|
|
473
|
-
self.fg = other.fg.or(self.fg);
|
|
474
|
-
self.bg = other.bg.or(self.bg);
|
|
475
|
-
|
|
476
|
-
#[cfg(feature = "underline-color")]
|
|
477
|
-
{
|
|
478
|
-
self.underline_color = other.underline_color.or(self.underline_color);
|
|
479
|
-
}
|
|
480
|
-
|
|
481
|
-
self.add_modifier.remove(other.sub_modifier);
|
|
482
|
-
self.add_modifier.insert(other.add_modifier);
|
|
483
|
-
self.sub_modifier.remove(other.add_modifier);
|
|
484
|
-
self.sub_modifier.insert(other.sub_modifier);
|
|
485
|
-
|
|
486
|
-
self
|
|
487
|
-
}
|
|
488
|
-
|
|
489
|
-
/// Formats the style in a way that can be copy-pasted into code using the style shorthands.
|
|
490
|
-
///
|
|
491
|
-
/// This is useful for debugging and for generating code snippets.
|
|
492
|
-
pub(crate) fn fmt_stylize(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
493
|
-
use fmt::Debug;
|
|
494
|
-
if let Some(fg) = self.fg {
|
|
495
|
-
fg.stylize_debug(ColorDebugKind::Foreground).fmt(f)?;
|
|
496
|
-
}
|
|
497
|
-
if let Some(bg) = self.bg {
|
|
498
|
-
bg.stylize_debug(ColorDebugKind::Background).fmt(f)?;
|
|
499
|
-
}
|
|
500
|
-
#[cfg(feature = "underline-color")]
|
|
501
|
-
if let Some(underline_color) = self.underline_color {
|
|
502
|
-
underline_color
|
|
503
|
-
.stylize_debug(ColorDebugKind::Underline)
|
|
504
|
-
.fmt(f)?;
|
|
505
|
-
}
|
|
506
|
-
for modifier in self.add_modifier.iter() {
|
|
507
|
-
match modifier {
|
|
508
|
-
Modifier::BOLD => f.write_str(".bold()")?,
|
|
509
|
-
Modifier::DIM => f.write_str(".dim()")?,
|
|
510
|
-
Modifier::ITALIC => f.write_str(".italic()")?,
|
|
511
|
-
Modifier::UNDERLINED => f.write_str(".underlined()")?,
|
|
512
|
-
Modifier::SLOW_BLINK => f.write_str(".slow_blink()")?,
|
|
513
|
-
Modifier::RAPID_BLINK => f.write_str(".rapid_blink()")?,
|
|
514
|
-
Modifier::REVERSED => f.write_str(".reversed()")?,
|
|
515
|
-
Modifier::HIDDEN => f.write_str(".hidden()")?,
|
|
516
|
-
Modifier::CROSSED_OUT => f.write_str(".crossed_out()")?,
|
|
517
|
-
_ => f.write_fmt(format_args!(".add_modifier(Modifier::{modifier:?})"))?,
|
|
518
|
-
}
|
|
519
|
-
}
|
|
520
|
-
for modifier in self.sub_modifier.iter() {
|
|
521
|
-
match modifier {
|
|
522
|
-
Modifier::BOLD => f.write_str(".not_bold()")?,
|
|
523
|
-
Modifier::DIM => f.write_str(".not_dim()")?,
|
|
524
|
-
Modifier::ITALIC => f.write_str(".not_italic()")?,
|
|
525
|
-
Modifier::UNDERLINED => f.write_str(".not_underlined()")?,
|
|
526
|
-
Modifier::SLOW_BLINK => f.write_str(".not_slow_blink()")?,
|
|
527
|
-
Modifier::RAPID_BLINK => f.write_str(".not_rapid_blink()")?,
|
|
528
|
-
Modifier::REVERSED => f.write_str(".not_reversed()")?,
|
|
529
|
-
Modifier::HIDDEN => f.write_str(".not_hidden()")?,
|
|
530
|
-
Modifier::CROSSED_OUT => f.write_str(".not_crossed_out()")?,
|
|
531
|
-
_ => f.write_fmt(format_args!(".remove_modifier(Modifier::{modifier:?})"))?,
|
|
532
|
-
}
|
|
533
|
-
}
|
|
534
|
-
Ok(())
|
|
535
|
-
}
|
|
536
|
-
|
|
537
|
-
color!(pub const Color::Black, black(), on_black() -> Self);
|
|
538
|
-
color!(pub const Color::Red, red(), on_red() -> Self);
|
|
539
|
-
color!(pub const Color::Green, green(), on_green() -> Self);
|
|
540
|
-
color!(pub const Color::Yellow, yellow(), on_yellow() -> Self);
|
|
541
|
-
color!(pub const Color::Blue, blue(), on_blue() -> Self);
|
|
542
|
-
color!(pub const Color::Magenta, magenta(), on_magenta() -> Self);
|
|
543
|
-
color!(pub const Color::Cyan, cyan(), on_cyan() -> Self);
|
|
544
|
-
color!(pub const Color::Gray, gray(), on_gray() -> Self);
|
|
545
|
-
color!(pub const Color::DarkGray, dark_gray(), on_dark_gray() -> Self);
|
|
546
|
-
color!(pub const Color::LightRed, light_red(), on_light_red() -> Self);
|
|
547
|
-
color!(pub const Color::LightGreen, light_green(), on_light_green() -> Self);
|
|
548
|
-
color!(pub const Color::LightYellow, light_yellow(), on_light_yellow() -> Self);
|
|
549
|
-
color!(pub const Color::LightBlue, light_blue(), on_light_blue() -> Self);
|
|
550
|
-
color!(pub const Color::LightMagenta, light_magenta(), on_light_magenta() -> Self);
|
|
551
|
-
color!(pub const Color::LightCyan, light_cyan(), on_light_cyan() -> Self);
|
|
552
|
-
color!(pub const Color::White, white(), on_white() -> Self);
|
|
553
|
-
|
|
554
|
-
modifier!(pub const Modifier::BOLD, bold(), not_bold() -> Self);
|
|
555
|
-
modifier!(pub const Modifier::DIM, dim(), not_dim() -> Self);
|
|
556
|
-
modifier!(pub const Modifier::ITALIC, italic(), not_italic() -> Self);
|
|
557
|
-
modifier!(pub const Modifier::UNDERLINED, underlined(), not_underlined() -> Self);
|
|
558
|
-
modifier!(pub const Modifier::SLOW_BLINK, slow_blink(), not_slow_blink() -> Self);
|
|
559
|
-
modifier!(pub const Modifier::RAPID_BLINK, rapid_blink(), not_rapid_blink() -> Self);
|
|
560
|
-
modifier!(pub const Modifier::REVERSED, reversed(), not_reversed() -> Self);
|
|
561
|
-
modifier!(pub const Modifier::HIDDEN, hidden(), not_hidden() -> Self);
|
|
562
|
-
modifier!(pub const Modifier::CROSSED_OUT, crossed_out(), not_crossed_out() -> Self);
|
|
563
|
-
}
|
|
564
|
-
|
|
565
|
-
impl From<Color> for Style {
|
|
566
|
-
/// Creates a new `Style` with the given foreground color.
|
|
567
|
-
///
|
|
568
|
-
/// To specify a foreground and background color, use the `from((fg, bg))` constructor.
|
|
569
|
-
///
|
|
570
|
-
/// # Example
|
|
571
|
-
///
|
|
572
|
-
/// ```rust
|
|
573
|
-
/// use ratatui_core::style::{Color, Style};
|
|
574
|
-
///
|
|
575
|
-
/// let style = Style::from(Color::Red);
|
|
576
|
-
/// ```
|
|
577
|
-
fn from(color: Color) -> Self {
|
|
578
|
-
Self::new().fg(color)
|
|
579
|
-
}
|
|
580
|
-
}
|
|
581
|
-
|
|
582
|
-
impl From<(Color, Color)> for Style {
|
|
583
|
-
/// Creates a new `Style` with the given foreground and background colors.
|
|
584
|
-
///
|
|
585
|
-
/// # Example
|
|
586
|
-
///
|
|
587
|
-
/// ```rust
|
|
588
|
-
/// use ratatui_core::style::{Color, Style};
|
|
589
|
-
///
|
|
590
|
-
/// // red foreground, blue background
|
|
591
|
-
/// let style = Style::from((Color::Red, Color::Blue));
|
|
592
|
-
/// // default foreground, blue background
|
|
593
|
-
/// let style = Style::from((Color::Reset, Color::Blue));
|
|
594
|
-
/// ```
|
|
595
|
-
fn from((fg, bg): (Color, Color)) -> Self {
|
|
596
|
-
Self::new().fg(fg).bg(bg)
|
|
597
|
-
}
|
|
598
|
-
}
|
|
599
|
-
|
|
600
|
-
impl From<Modifier> for Style {
|
|
601
|
-
/// Creates a new `Style` with the given modifier added.
|
|
602
|
-
///
|
|
603
|
-
/// To specify multiple modifiers, use the `|` operator.
|
|
604
|
-
///
|
|
605
|
-
/// To specify modifiers to add and remove, use the `from((add_modifier, sub_modifier))`
|
|
606
|
-
/// constructor.
|
|
607
|
-
///
|
|
608
|
-
/// # Example
|
|
609
|
-
///
|
|
610
|
-
/// ```rust
|
|
611
|
-
/// use ratatui_core::style::{Style, Modifier};
|
|
612
|
-
///
|
|
613
|
-
/// // add bold and italic
|
|
614
|
-
/// let style = Style::from(Modifier::BOLD|Modifier::ITALIC);
|
|
615
|
-
fn from(modifier: Modifier) -> Self {
|
|
616
|
-
Self::new().add_modifier(modifier)
|
|
617
|
-
}
|
|
618
|
-
}
|
|
619
|
-
|
|
620
|
-
impl From<(Modifier, Modifier)> for Style {
|
|
621
|
-
/// Creates a new `Style` with the given modifiers added and removed.
|
|
622
|
-
///
|
|
623
|
-
/// # Example
|
|
624
|
-
///
|
|
625
|
-
/// ```rust
|
|
626
|
-
/// use ratatui_core::style::{Modifier, Style};
|
|
627
|
-
///
|
|
628
|
-
/// // add bold and italic, remove dim
|
|
629
|
-
/// let style = Style::from((Modifier::BOLD | Modifier::ITALIC, Modifier::DIM));
|
|
630
|
-
/// ```
|
|
631
|
-
fn from((add_modifier, sub_modifier): (Modifier, Modifier)) -> Self {
|
|
632
|
-
Self::new()
|
|
633
|
-
.add_modifier(add_modifier)
|
|
634
|
-
.remove_modifier(sub_modifier)
|
|
635
|
-
}
|
|
636
|
-
}
|
|
637
|
-
|
|
638
|
-
impl From<(Color, Modifier)> for Style {
|
|
639
|
-
/// Creates a new `Style` with the given foreground color and modifier added.
|
|
640
|
-
///
|
|
641
|
-
/// To specify multiple modifiers, use the `|` operator.
|
|
642
|
-
///
|
|
643
|
-
/// # Example
|
|
644
|
-
///
|
|
645
|
-
/// ```rust
|
|
646
|
-
/// use ratatui_core::style::{Color, Modifier, Style};
|
|
647
|
-
///
|
|
648
|
-
/// // red foreground, add bold and italic
|
|
649
|
-
/// let style = Style::from((Color::Red, Modifier::BOLD | Modifier::ITALIC));
|
|
650
|
-
/// ```
|
|
651
|
-
fn from((fg, modifier): (Color, Modifier)) -> Self {
|
|
652
|
-
Self::new().fg(fg).add_modifier(modifier)
|
|
653
|
-
}
|
|
654
|
-
}
|
|
655
|
-
|
|
656
|
-
impl From<(Color, Color, Modifier)> for Style {
|
|
657
|
-
/// Creates a new `Style` with the given foreground and background colors and modifier added.
|
|
658
|
-
///
|
|
659
|
-
/// To specify multiple modifiers, use the `|` operator.
|
|
660
|
-
///
|
|
661
|
-
/// # Example
|
|
662
|
-
///
|
|
663
|
-
/// ```rust
|
|
664
|
-
/// use ratatui_core::style::{Color, Modifier, Style};
|
|
665
|
-
///
|
|
666
|
-
/// // red foreground, blue background, add bold and italic
|
|
667
|
-
/// let style = Style::from((Color::Red, Color::Blue, Modifier::BOLD | Modifier::ITALIC));
|
|
668
|
-
/// ```
|
|
669
|
-
fn from((fg, bg, modifier): (Color, Color, Modifier)) -> Self {
|
|
670
|
-
Self::new().fg(fg).bg(bg).add_modifier(modifier)
|
|
671
|
-
}
|
|
672
|
-
}
|
|
673
|
-
|
|
674
|
-
impl From<(Color, Color, Modifier, Modifier)> for Style {
|
|
675
|
-
/// Creates a new `Style` with the given foreground and background colors and modifiers added
|
|
676
|
-
/// and removed.
|
|
677
|
-
///
|
|
678
|
-
/// # Example
|
|
679
|
-
///
|
|
680
|
-
/// ```rust
|
|
681
|
-
/// use ratatui_core::style::{Color, Modifier, Style};
|
|
682
|
-
///
|
|
683
|
-
/// // red foreground, blue background, add bold and italic, remove dim
|
|
684
|
-
/// let style = Style::from((
|
|
685
|
-
/// Color::Red,
|
|
686
|
-
/// Color::Blue,
|
|
687
|
-
/// Modifier::BOLD | Modifier::ITALIC,
|
|
688
|
-
/// Modifier::DIM,
|
|
689
|
-
/// ));
|
|
690
|
-
/// ```
|
|
691
|
-
fn from((fg, bg, add_modifier, sub_modifier): (Color, Color, Modifier, Modifier)) -> Self {
|
|
692
|
-
Self::new()
|
|
693
|
-
.fg(fg)
|
|
694
|
-
.bg(bg)
|
|
695
|
-
.add_modifier(add_modifier)
|
|
696
|
-
.remove_modifier(sub_modifier)
|
|
697
|
-
}
|
|
698
|
-
}
|
|
699
|
-
|
|
700
|
-
#[cfg(test)]
|
|
701
|
-
mod tests {
|
|
702
|
-
use alloc::format;
|
|
703
|
-
|
|
704
|
-
use rstest::rstest;
|
|
705
|
-
|
|
706
|
-
use super::*;
|
|
707
|
-
|
|
708
|
-
#[rstest]
|
|
709
|
-
#[case(Style::new(), "Style::new()")]
|
|
710
|
-
#[case(Style::default(), "Style::new()")]
|
|
711
|
-
#[case(Style::new().red(), "Style::new().red()")]
|
|
712
|
-
#[case(Style::new().on_blue(), "Style::new().on_blue()")]
|
|
713
|
-
#[case(Style::new().bold(), "Style::new().bold()")]
|
|
714
|
-
#[case(Style::new().not_italic(), "Style::new().not_italic()")]
|
|
715
|
-
#[case(
|
|
716
|
-
Style::new().red().on_blue().bold().italic().not_dim().not_hidden(),
|
|
717
|
-
"Style::new().red().on_blue().bold().italic().not_dim().not_hidden()"
|
|
718
|
-
)]
|
|
719
|
-
fn debug(#[case] style: Style, #[case] expected: &'static str) {
|
|
720
|
-
assert_eq!(format!("{style:?}"), expected);
|
|
721
|
-
}
|
|
722
|
-
|
|
723
|
-
#[test]
|
|
724
|
-
fn combined_patch_gives_same_result_as_individual_patch() {
|
|
725
|
-
let styles = [
|
|
726
|
-
Style::new(),
|
|
727
|
-
Style::new().fg(Color::Yellow),
|
|
728
|
-
Style::new().bg(Color::Yellow),
|
|
729
|
-
Style::new().add_modifier(Modifier::BOLD),
|
|
730
|
-
Style::new().remove_modifier(Modifier::BOLD),
|
|
731
|
-
Style::new().add_modifier(Modifier::ITALIC),
|
|
732
|
-
Style::new().remove_modifier(Modifier::ITALIC),
|
|
733
|
-
Style::new().add_modifier(Modifier::ITALIC | Modifier::BOLD),
|
|
734
|
-
Style::new().remove_modifier(Modifier::ITALIC | Modifier::BOLD),
|
|
735
|
-
];
|
|
736
|
-
for &a in &styles {
|
|
737
|
-
for &b in &styles {
|
|
738
|
-
for &c in &styles {
|
|
739
|
-
for &d in &styles {
|
|
740
|
-
assert_eq!(
|
|
741
|
-
Style::new().patch(a).patch(b).patch(c).patch(d),
|
|
742
|
-
Style::new().patch(a.patch(b.patch(c.patch(d))))
|
|
743
|
-
);
|
|
744
|
-
}
|
|
745
|
-
}
|
|
746
|
-
}
|
|
747
|
-
}
|
|
748
|
-
}
|
|
749
|
-
|
|
750
|
-
#[test]
|
|
751
|
-
fn combine_individual_modifiers() {
|
|
752
|
-
use crate::buffer::Buffer;
|
|
753
|
-
use crate::layout::Rect;
|
|
754
|
-
|
|
755
|
-
let mods = [
|
|
756
|
-
Modifier::BOLD,
|
|
757
|
-
Modifier::DIM,
|
|
758
|
-
Modifier::ITALIC,
|
|
759
|
-
Modifier::UNDERLINED,
|
|
760
|
-
Modifier::SLOW_BLINK,
|
|
761
|
-
Modifier::RAPID_BLINK,
|
|
762
|
-
Modifier::REVERSED,
|
|
763
|
-
Modifier::HIDDEN,
|
|
764
|
-
Modifier::CROSSED_OUT,
|
|
765
|
-
];
|
|
766
|
-
|
|
767
|
-
let mut buffer = Buffer::empty(Rect::new(0, 0, 1, 1));
|
|
768
|
-
|
|
769
|
-
for m in mods {
|
|
770
|
-
buffer[(0, 0)].set_style(Style::reset());
|
|
771
|
-
buffer[(0, 0)].set_style(Style::new().add_modifier(m));
|
|
772
|
-
let style = buffer[(0, 0)].style();
|
|
773
|
-
assert!(style.add_modifier.contains(m));
|
|
774
|
-
assert!(!style.sub_modifier.contains(m));
|
|
775
|
-
}
|
|
776
|
-
}
|
|
777
|
-
|
|
778
|
-
#[rstest]
|
|
779
|
-
#[case(Modifier::empty(), "NONE")]
|
|
780
|
-
#[case(Modifier::BOLD, "BOLD")]
|
|
781
|
-
#[case(Modifier::DIM, "DIM")]
|
|
782
|
-
#[case(Modifier::ITALIC, "ITALIC")]
|
|
783
|
-
#[case(Modifier::UNDERLINED, "UNDERLINED")]
|
|
784
|
-
#[case(Modifier::SLOW_BLINK, "SLOW_BLINK")]
|
|
785
|
-
#[case(Modifier::RAPID_BLINK, "RAPID_BLINK")]
|
|
786
|
-
#[case(Modifier::REVERSED, "REVERSED")]
|
|
787
|
-
#[case(Modifier::HIDDEN, "HIDDEN")]
|
|
788
|
-
#[case(Modifier::CROSSED_OUT, "CROSSED_OUT")]
|
|
789
|
-
#[case(Modifier::BOLD | Modifier::DIM, "BOLD | DIM")]
|
|
790
|
-
#[case(
|
|
791
|
-
Modifier::all(),
|
|
792
|
-
"BOLD | DIM | ITALIC | UNDERLINED | SLOW_BLINK | RAPID_BLINK | REVERSED | HIDDEN | CROSSED_OUT"
|
|
793
|
-
)]
|
|
794
|
-
fn modifier_debug(#[case] modifier: Modifier, #[case] expected: &str) {
|
|
795
|
-
assert_eq!(format!("{modifier:?}"), expected);
|
|
796
|
-
}
|
|
797
|
-
|
|
798
|
-
#[test]
|
|
799
|
-
fn style_can_be_const() {
|
|
800
|
-
const RED: Color = Color::Red;
|
|
801
|
-
const BLACK: Color = Color::Black;
|
|
802
|
-
const BOLD: Modifier = Modifier::BOLD;
|
|
803
|
-
const ITALIC: Modifier = Modifier::ITALIC;
|
|
804
|
-
|
|
805
|
-
const _RESET: Style = Style::reset();
|
|
806
|
-
const _RED_FG: Style = Style::new().fg(RED);
|
|
807
|
-
const _RED_FG_SHORT: Style = Style::new().red();
|
|
808
|
-
const _BLACK_BG: Style = Style::new().bg(BLACK);
|
|
809
|
-
const _BLACK_BG_SHORT: Style = Style::new().on_black();
|
|
810
|
-
const _ADD_BOLD: Style = Style::new().add_modifier(BOLD);
|
|
811
|
-
const _ADD_BOLD_SHORT: Style = Style::new().bold();
|
|
812
|
-
const _REMOVE_ITALIC: Style = Style::new().remove_modifier(ITALIC);
|
|
813
|
-
const _REMOVE_ITALIC_SHORT: Style = Style::new().not_italic();
|
|
814
|
-
const ALL: Style = Style::new()
|
|
815
|
-
.fg(RED)
|
|
816
|
-
.bg(BLACK)
|
|
817
|
-
.add_modifier(BOLD)
|
|
818
|
-
.remove_modifier(ITALIC);
|
|
819
|
-
const ALL_SHORT: Style = Style::new().red().on_black().bold().not_italic();
|
|
820
|
-
assert_eq!(
|
|
821
|
-
ALL,
|
|
822
|
-
Style::new()
|
|
823
|
-
.fg(Color::Red)
|
|
824
|
-
.bg(Color::Black)
|
|
825
|
-
.add_modifier(Modifier::BOLD)
|
|
826
|
-
.remove_modifier(Modifier::ITALIC)
|
|
827
|
-
);
|
|
828
|
-
assert_eq!(ALL, ALL_SHORT);
|
|
829
|
-
}
|
|
830
|
-
|
|
831
|
-
#[test]
|
|
832
|
-
fn has_modifier_checks() {
|
|
833
|
-
// basic presence
|
|
834
|
-
let style = Style::new().add_modifier(Modifier::BOLD | Modifier::ITALIC);
|
|
835
|
-
assert!(style.has_modifier(Modifier::BOLD));
|
|
836
|
-
assert!(style.has_modifier(Modifier::ITALIC));
|
|
837
|
-
assert!(!style.has_modifier(Modifier::UNDERLINED));
|
|
838
|
-
|
|
839
|
-
// removal prevents the modifier from being reported as present
|
|
840
|
-
let style = Style::new()
|
|
841
|
-
.add_modifier(Modifier::BOLD | Modifier::ITALIC)
|
|
842
|
-
.remove_modifier(Modifier::ITALIC);
|
|
843
|
-
assert!(style.has_modifier(Modifier::BOLD));
|
|
844
|
-
assert!(!style.has_modifier(Modifier::ITALIC));
|
|
845
|
-
|
|
846
|
-
// patching with a style that removes a modifier clears it
|
|
847
|
-
let style = Style::new().add_modifier(Modifier::BOLD | Modifier::ITALIC);
|
|
848
|
-
let patched = style.patch(Style::new().remove_modifier(Modifier::ITALIC));
|
|
849
|
-
assert!(patched.has_modifier(Modifier::BOLD));
|
|
850
|
-
assert!(!patched.has_modifier(Modifier::ITALIC));
|
|
851
|
-
}
|
|
852
|
-
|
|
853
|
-
#[rstest]
|
|
854
|
-
#[case(Style::new().black(), Color::Black)]
|
|
855
|
-
#[case(Style::new().red(), Color::Red)]
|
|
856
|
-
#[case(Style::new().green(), Color::Green)]
|
|
857
|
-
#[case(Style::new().yellow(), Color::Yellow)]
|
|
858
|
-
#[case(Style::new().blue(), Color::Blue)]
|
|
859
|
-
#[case(Style::new().magenta(), Color::Magenta)]
|
|
860
|
-
#[case(Style::new().cyan(), Color::Cyan)]
|
|
861
|
-
#[case(Style::new().white(), Color::White)]
|
|
862
|
-
#[case(Style::new().gray(), Color::Gray)]
|
|
863
|
-
#[case(Style::new().dark_gray(), Color::DarkGray)]
|
|
864
|
-
#[case(Style::new().light_red(), Color::LightRed)]
|
|
865
|
-
#[case(Style::new().light_green(), Color::LightGreen)]
|
|
866
|
-
#[case(Style::new().light_yellow(), Color::LightYellow)]
|
|
867
|
-
#[case(Style::new().light_blue(), Color::LightBlue)]
|
|
868
|
-
#[case(Style::new().light_magenta(), Color::LightMagenta)]
|
|
869
|
-
#[case(Style::new().light_cyan(), Color::LightCyan)]
|
|
870
|
-
#[case(Style::new().white(), Color::White)]
|
|
871
|
-
fn fg_can_be_stylized(#[case] stylized: Style, #[case] expected: Color) {
|
|
872
|
-
assert_eq!(stylized, Style::new().fg(expected));
|
|
873
|
-
}
|
|
874
|
-
|
|
875
|
-
#[rstest]
|
|
876
|
-
#[case(Style::new().on_black(), Color::Black)]
|
|
877
|
-
#[case(Style::new().on_red(), Color::Red)]
|
|
878
|
-
#[case(Style::new().on_green(), Color::Green)]
|
|
879
|
-
#[case(Style::new().on_yellow(), Color::Yellow)]
|
|
880
|
-
#[case(Style::new().on_blue(), Color::Blue)]
|
|
881
|
-
#[case(Style::new().on_magenta(), Color::Magenta)]
|
|
882
|
-
#[case(Style::new().on_cyan(), Color::Cyan)]
|
|
883
|
-
#[case(Style::new().on_white(), Color::White)]
|
|
884
|
-
#[case(Style::new().on_gray(), Color::Gray)]
|
|
885
|
-
#[case(Style::new().on_dark_gray(), Color::DarkGray)]
|
|
886
|
-
#[case(Style::new().on_light_red(), Color::LightRed)]
|
|
887
|
-
#[case(Style::new().on_light_green(), Color::LightGreen)]
|
|
888
|
-
#[case(Style::new().on_light_yellow(), Color::LightYellow)]
|
|
889
|
-
#[case(Style::new().on_light_blue(), Color::LightBlue)]
|
|
890
|
-
#[case(Style::new().on_light_magenta(), Color::LightMagenta)]
|
|
891
|
-
#[case(Style::new().on_light_cyan(), Color::LightCyan)]
|
|
892
|
-
#[case(Style::new().on_white(), Color::White)]
|
|
893
|
-
fn bg_can_be_stylized(#[case] stylized: Style, #[case] expected: Color) {
|
|
894
|
-
assert_eq!(stylized, Style::new().bg(expected));
|
|
895
|
-
}
|
|
896
|
-
|
|
897
|
-
#[rstest]
|
|
898
|
-
#[case(Style::new().bold(), Modifier::BOLD)]
|
|
899
|
-
#[case(Style::new().dim(), Modifier::DIM)]
|
|
900
|
-
#[case(Style::new().italic(), Modifier::ITALIC)]
|
|
901
|
-
#[case(Style::new().underlined(), Modifier::UNDERLINED)]
|
|
902
|
-
#[case(Style::new().slow_blink(), Modifier::SLOW_BLINK)]
|
|
903
|
-
#[case(Style::new().rapid_blink(), Modifier::RAPID_BLINK)]
|
|
904
|
-
#[case(Style::new().reversed(), Modifier::REVERSED)]
|
|
905
|
-
#[case(Style::new().hidden(), Modifier::HIDDEN)]
|
|
906
|
-
#[case(Style::new().crossed_out(), Modifier::CROSSED_OUT)]
|
|
907
|
-
fn add_modifier_can_be_stylized(#[case] stylized: Style, #[case] expected: Modifier) {
|
|
908
|
-
assert_eq!(stylized, Style::new().add_modifier(expected));
|
|
909
|
-
}
|
|
910
|
-
|
|
911
|
-
#[rstest]
|
|
912
|
-
#[case(Style::new().not_bold(), Modifier::BOLD)]
|
|
913
|
-
#[case(Style::new().not_dim(), Modifier::DIM)]
|
|
914
|
-
#[case(Style::new().not_italic(), Modifier::ITALIC)]
|
|
915
|
-
#[case(Style::new().not_underlined(), Modifier::UNDERLINED)]
|
|
916
|
-
#[case(Style::new().not_slow_blink(), Modifier::SLOW_BLINK)]
|
|
917
|
-
#[case(Style::new().not_rapid_blink(), Modifier::RAPID_BLINK)]
|
|
918
|
-
#[case(Style::new().not_reversed(), Modifier::REVERSED)]
|
|
919
|
-
#[case(Style::new().not_hidden(), Modifier::HIDDEN)]
|
|
920
|
-
#[case(Style::new().not_crossed_out(), Modifier::CROSSED_OUT)]
|
|
921
|
-
fn remove_modifier_can_be_stylized(#[case] stylized: Style, #[case] expected: Modifier) {
|
|
922
|
-
assert_eq!(stylized, Style::new().remove_modifier(expected));
|
|
923
|
-
}
|
|
924
|
-
|
|
925
|
-
#[test]
|
|
926
|
-
fn from_color() {
|
|
927
|
-
assert_eq!(Style::from(Color::Red), Style::new().fg(Color::Red));
|
|
928
|
-
}
|
|
929
|
-
|
|
930
|
-
#[test]
|
|
931
|
-
fn from_color_color() {
|
|
932
|
-
assert_eq!(
|
|
933
|
-
Style::from((Color::Red, Color::Blue)),
|
|
934
|
-
Style::new().fg(Color::Red).bg(Color::Blue)
|
|
935
|
-
);
|
|
936
|
-
}
|
|
937
|
-
|
|
938
|
-
#[test]
|
|
939
|
-
fn from_modifier() {
|
|
940
|
-
assert_eq!(
|
|
941
|
-
Style::from(Modifier::BOLD | Modifier::ITALIC),
|
|
942
|
-
Style::new()
|
|
943
|
-
.add_modifier(Modifier::BOLD)
|
|
944
|
-
.add_modifier(Modifier::ITALIC)
|
|
945
|
-
);
|
|
946
|
-
}
|
|
947
|
-
|
|
948
|
-
#[test]
|
|
949
|
-
fn from_modifier_modifier() {
|
|
950
|
-
assert_eq!(
|
|
951
|
-
Style::from((Modifier::BOLD | Modifier::ITALIC, Modifier::DIM)),
|
|
952
|
-
Style::new()
|
|
953
|
-
.add_modifier(Modifier::BOLD)
|
|
954
|
-
.add_modifier(Modifier::ITALIC)
|
|
955
|
-
.remove_modifier(Modifier::DIM)
|
|
956
|
-
);
|
|
957
|
-
}
|
|
958
|
-
|
|
959
|
-
#[test]
|
|
960
|
-
fn from_color_modifier() {
|
|
961
|
-
assert_eq!(
|
|
962
|
-
Style::from((Color::Red, Modifier::BOLD | Modifier::ITALIC)),
|
|
963
|
-
Style::new()
|
|
964
|
-
.fg(Color::Red)
|
|
965
|
-
.add_modifier(Modifier::BOLD)
|
|
966
|
-
.add_modifier(Modifier::ITALIC)
|
|
967
|
-
);
|
|
968
|
-
}
|
|
969
|
-
|
|
970
|
-
#[test]
|
|
971
|
-
fn from_color_color_modifier() {
|
|
972
|
-
assert_eq!(
|
|
973
|
-
Style::from((Color::Red, Color::Blue, Modifier::BOLD | Modifier::ITALIC)),
|
|
974
|
-
Style::new()
|
|
975
|
-
.fg(Color::Red)
|
|
976
|
-
.bg(Color::Blue)
|
|
977
|
-
.add_modifier(Modifier::BOLD)
|
|
978
|
-
.add_modifier(Modifier::ITALIC)
|
|
979
|
-
);
|
|
980
|
-
}
|
|
981
|
-
|
|
982
|
-
#[test]
|
|
983
|
-
fn from_color_color_modifier_modifier() {
|
|
984
|
-
assert_eq!(
|
|
985
|
-
Style::from((
|
|
986
|
-
Color::Red,
|
|
987
|
-
Color::Blue,
|
|
988
|
-
Modifier::BOLD | Modifier::ITALIC,
|
|
989
|
-
Modifier::DIM
|
|
990
|
-
)),
|
|
991
|
-
Style::new()
|
|
992
|
-
.fg(Color::Red)
|
|
993
|
-
.bg(Color::Blue)
|
|
994
|
-
.add_modifier(Modifier::BOLD)
|
|
995
|
-
.add_modifier(Modifier::ITALIC)
|
|
996
|
-
.remove_modifier(Modifier::DIM)
|
|
997
|
-
);
|
|
998
|
-
}
|
|
999
|
-
|
|
1000
|
-
#[cfg(feature = "serde")]
|
|
1001
|
-
#[test]
|
|
1002
|
-
fn serialize_then_deserialize() {
|
|
1003
|
-
let style = Style {
|
|
1004
|
-
fg: Some(Color::Rgb(255, 0, 255)),
|
|
1005
|
-
bg: Some(Color::White),
|
|
1006
|
-
#[cfg(feature = "underline-color")]
|
|
1007
|
-
underline_color: Some(Color::Indexed(3)),
|
|
1008
|
-
add_modifier: Modifier::UNDERLINED,
|
|
1009
|
-
sub_modifier: Modifier::CROSSED_OUT,
|
|
1010
|
-
};
|
|
1011
|
-
|
|
1012
|
-
let json_str = serde_json::to_string(&style).unwrap();
|
|
1013
|
-
let json_value: serde_json::Value = serde_json::from_str(&json_str).unwrap();
|
|
1014
|
-
|
|
1015
|
-
let mut expected_json = serde_json::json!({
|
|
1016
|
-
"fg": "#FF00FF",
|
|
1017
|
-
"bg": "White",
|
|
1018
|
-
"add_modifier": "UNDERLINED",
|
|
1019
|
-
"sub_modifier": "CROSSED_OUT"
|
|
1020
|
-
});
|
|
1021
|
-
|
|
1022
|
-
#[cfg(feature = "underline-color")]
|
|
1023
|
-
{
|
|
1024
|
-
expected_json
|
|
1025
|
-
.as_object_mut()
|
|
1026
|
-
.unwrap()
|
|
1027
|
-
.insert("underline_color".into(), "3".into());
|
|
1028
|
-
}
|
|
1029
|
-
|
|
1030
|
-
assert_eq!(json_value, expected_json);
|
|
1031
|
-
|
|
1032
|
-
let deserialized: Style = serde_json::from_str(&json_str).unwrap();
|
|
1033
|
-
assert_eq!(deserialized, style);
|
|
1034
|
-
}
|
|
1035
|
-
|
|
1036
|
-
#[cfg(feature = "serde")]
|
|
1037
|
-
#[test]
|
|
1038
|
-
fn deserialize_defaults() {
|
|
1039
|
-
let style = Style {
|
|
1040
|
-
fg: None,
|
|
1041
|
-
bg: None,
|
|
1042
|
-
#[cfg(feature = "underline-color")]
|
|
1043
|
-
underline_color: None,
|
|
1044
|
-
add_modifier: Modifier::empty(),
|
|
1045
|
-
sub_modifier: Modifier::empty(),
|
|
1046
|
-
};
|
|
1047
|
-
|
|
1048
|
-
let json_str = serde_json::to_string(&style).unwrap();
|
|
1049
|
-
assert_eq!(json_str, "{}");
|
|
1050
|
-
|
|
1051
|
-
let deserialized: Style = serde_json::from_str(&json_str).unwrap();
|
|
1052
|
-
assert_eq!(deserialized, style);
|
|
1053
|
-
}
|
|
1054
|
-
|
|
1055
|
-
#[cfg(feature = "serde")]
|
|
1056
|
-
#[test]
|
|
1057
|
-
fn deserialize_null_modifiers() {
|
|
1058
|
-
let json_value = serde_json::json!({
|
|
1059
|
-
"add_modifier": serde_json::Value::Null,
|
|
1060
|
-
"sub_modifier": serde_json::Value::Null
|
|
1061
|
-
});
|
|
1062
|
-
let json_str = serde_json::to_string(&json_value).unwrap();
|
|
1063
|
-
|
|
1064
|
-
let style: Style = serde_json::from_str(&json_str).unwrap();
|
|
1065
|
-
|
|
1066
|
-
assert!(style.add_modifier.is_empty());
|
|
1067
|
-
assert!(style.sub_modifier.is_empty());
|
|
1068
|
-
}
|
|
1069
|
-
}
|