chore(backend): change From<T> impls to new backend specific IntoBackend and FromBackend traits (#1464)
Adds two traits `IntoCrossterm` and `FromCrossterm` for converting
between ratatui and crossterm types. This is necessary in order to avoid
the orphan rule when implementing `From` for crossterm types once the
crossterm types are moved to a separate crate.
Similarly Termwiz and Termwiz gain FromTermion, IntoTermion, FromTermwiz
and IntoTermwiz traits.
BREAKING CHANGE: The `From` and `Into` impls for backend types are now
replaced
with specific backend traits.
```diff
+ use ratatui::backend::{FromCrossterm, IntoCrossterm};
let crossterm_color = crossterm::style::Color::Black;
- let ratatui_color = crossterm_color.into();
- let ratatui_color = ratatui::style::Color::from(crossterm_color);
+ let ratatui_color = ratatui::style::Color::from_crossterm(crossterm_color);
- let crossterm_color = ratatui_color.into();
- let crossterm_color = crossterm::style::Color::from(ratatui_color);
+ let crossterm_color = ratatui_color.into_crossterm();
let crossterm_attribute = crossterm::style::types::Attribute::Bold;
- let ratatui_modifier = crossterm_attribute.into();
- let ratatui_modifier = ratatui::style::Modifier::from(crossterm_attribute);
+ let ratatui_modifier = ratatui::style::Modifier::from_crossterm(crossterm_attribute);
- let crossterm_attribute = ratatui_modifier.into();
- let crossterm_attribute = crossterm::style::types::Attribute::from(ratatui_modifier);
+ let crossterm_attribute = ratatui_modifier.into_crossterm();
```
Similar conversions for `ContentStyle` -> `Style` and `Attributes` ->
`Modifier` exist for Crossterm,
and all the Termion and Termwiz types.
---------
Co-authored-by: Orhun Parmaksız <orhun@archlinux.org>
This commit is contained in:
@@ -72,6 +72,41 @@ This is a quick summary of the sections below:
|
||||
- MSRV is now 1.63.0
|
||||
- `List` no longer ignores empty strings
|
||||
|
||||
## Unreleased (0.30.0)
|
||||
|
||||
### The `From` impls for backend types are now replaced with more specific traits [#1464]
|
||||
|
||||
[#1464]: https://github.com/ratatui/ratatui/pull/1464
|
||||
|
||||
Crossterm gains `ratatui::backend::crossterm::{FromCrossterm, IntoCrossterm}`
|
||||
Termwiz gains `ratatui::backend::termwiz::{FromTermwiz, IntoTermwiz}`
|
||||
|
||||
This is necessary in order to avoid the orphan rule when implementing `From` for crossterm types
|
||||
once the crossterm types are moved to a separate crate.
|
||||
|
||||
```diff
|
||||
+ use ratatui::backend::crossterm::{FromCrossterm, IntoCrossterm};
|
||||
|
||||
let crossterm_color = crossterm::style::Color::Black;
|
||||
- let ratatui_color = crossterm_color.into();
|
||||
- let ratatui_color = ratatui::style::Color::from(crossterm_color);
|
||||
+ let ratatui_color = ratatui::style::Color::from_crossterm(crossterm_color);
|
||||
- let crossterm_color = ratatui_color.into();
|
||||
- let crossterm_color = crossterm::style::Color::from(ratatui_color);
|
||||
+ let crossterm_color = ratatui_color.into_crossterm();
|
||||
|
||||
let crossterm_attribute = crossterm::style::types::Attribute::Bold;
|
||||
- let ratatui_modifier = crossterm_attribute.into();
|
||||
- let ratatui_modifier = ratatui::style::Modifier::from(crossterm_attribute);
|
||||
+ let ratatui_modifier = ratatui::style::Modifier::from_crossterm(crossterm_attribute);
|
||||
- let crossterm_attribute = ratatui_modifier.into();
|
||||
- let crossterm_attribute = crossterm::style::types::Attribute::from(ratatui_modifier);
|
||||
+ let crossterm_attribute = ratatui_modifier.into_crossterm();
|
||||
```
|
||||
|
||||
Similar conversions for `ContentStyle` -> `Style` and `Attributes` -> `Modifier` exist for
|
||||
Crossterm and the various Termion and Termwiz types as well.
|
||||
|
||||
## [v0.29.0](https://github.com/ratatui/ratatui/releases/tag/v0.29.0)
|
||||
|
||||
### `Sparkline::data` takes `IntoIterator<Item = SparklineBar>` instead of `&[u64]` and is no longer const ([#1326])
|
||||
|
||||
@@ -109,20 +109,20 @@ use crate::{
|
||||
layout::{Position, Size},
|
||||
};
|
||||
|
||||
#[cfg(all(not(windows), feature = "termion"))]
|
||||
mod termion;
|
||||
#[cfg(all(not(windows), feature = "termion"))]
|
||||
pub use self::termion::TermionBackend;
|
||||
|
||||
#[cfg(feature = "crossterm")]
|
||||
mod crossterm;
|
||||
#[cfg(feature = "crossterm")]
|
||||
pub use self::crossterm::CrosstermBackend;
|
||||
pub use self::crossterm::{CrosstermBackend, FromCrossterm, IntoCrossterm};
|
||||
|
||||
#[cfg(all(not(windows), feature = "termion"))]
|
||||
mod termion;
|
||||
#[cfg(all(not(windows), feature = "termion"))]
|
||||
pub use self::termion::{FromTermion, IntoTermion, TermionBackend};
|
||||
|
||||
#[cfg(feature = "termwiz")]
|
||||
mod termwiz;
|
||||
#[cfg(feature = "termwiz")]
|
||||
pub use self::termwiz::TermwizBackend;
|
||||
pub use self::termwiz::{FromTermwiz, IntoTermwiz, TermwizBackend};
|
||||
|
||||
mod test;
|
||||
pub use self::test::TestBackend;
|
||||
|
||||
@@ -6,19 +6,20 @@ use std::io::{self, Write};
|
||||
|
||||
#[cfg(feature = "underline-color")]
|
||||
use crossterm::style::SetUnderlineColor;
|
||||
use crossterm::{
|
||||
cursor::{Hide, MoveTo, Show},
|
||||
execute, queue,
|
||||
style::{
|
||||
Attribute as CrosstermAttribute, Attributes as CrosstermAttributes,
|
||||
Color as CrosstermColor, Colors as CrosstermColors, ContentStyle, Print, SetAttribute,
|
||||
SetBackgroundColor, SetColors, SetForegroundColor,
|
||||
},
|
||||
terminal::{self, Clear},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
backend::{Backend, ClearType, WindowSize},
|
||||
buffer::Cell,
|
||||
crossterm::{
|
||||
cursor::{Hide, MoveTo, Show},
|
||||
execute, queue,
|
||||
style::{
|
||||
Attribute as CAttribute, Attributes as CAttributes, Color as CColor, Colors,
|
||||
ContentStyle, Print, SetAttribute, SetBackgroundColor, SetColors, SetForegroundColor,
|
||||
},
|
||||
terminal::{self, Clear},
|
||||
},
|
||||
layout::{Position, Size},
|
||||
style::{Color, Modifier, Style},
|
||||
};
|
||||
@@ -175,14 +176,17 @@ where
|
||||
if cell.fg != fg || cell.bg != bg {
|
||||
queue!(
|
||||
self.writer,
|
||||
SetColors(Colors::new(cell.fg.into(), cell.bg.into()))
|
||||
SetColors(CrosstermColors::new(
|
||||
cell.fg.into_crossterm(),
|
||||
cell.bg.into_crossterm(),
|
||||
))
|
||||
)?;
|
||||
fg = cell.fg;
|
||||
bg = cell.bg;
|
||||
}
|
||||
#[cfg(feature = "underline-color")]
|
||||
if cell.underline_color != underline_color {
|
||||
let color = CColor::from(cell.underline_color);
|
||||
let color = cell.underline_color.into_crossterm();
|
||||
queue!(self.writer, SetUnderlineColor(color))?;
|
||||
underline_color = cell.underline_color;
|
||||
}
|
||||
@@ -193,17 +197,17 @@ where
|
||||
#[cfg(feature = "underline-color")]
|
||||
return queue!(
|
||||
self.writer,
|
||||
SetForegroundColor(CColor::Reset),
|
||||
SetBackgroundColor(CColor::Reset),
|
||||
SetUnderlineColor(CColor::Reset),
|
||||
SetAttribute(CAttribute::Reset),
|
||||
SetForegroundColor(CrosstermColor::Reset),
|
||||
SetBackgroundColor(CrosstermColor::Reset),
|
||||
SetUnderlineColor(CrosstermColor::Reset),
|
||||
SetAttribute(CrosstermAttribute::Reset),
|
||||
);
|
||||
#[cfg(not(feature = "underline-color"))]
|
||||
return queue!(
|
||||
self.writer,
|
||||
SetForegroundColor(CColor::Reset),
|
||||
SetBackgroundColor(CColor::Reset),
|
||||
SetAttribute(CAttribute::Reset),
|
||||
SetForegroundColor(CrosstermColor::Reset),
|
||||
SetBackgroundColor(CrosstermColor::Reset),
|
||||
SetAttribute(CrosstermAttribute::Reset),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -302,54 +306,72 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Color> for CColor {
|
||||
fn from(color: Color) -> Self {
|
||||
match color {
|
||||
Color::Reset => Self::Reset,
|
||||
Color::Black => Self::Black,
|
||||
Color::Red => Self::DarkRed,
|
||||
Color::Green => Self::DarkGreen,
|
||||
Color::Yellow => Self::DarkYellow,
|
||||
Color::Blue => Self::DarkBlue,
|
||||
Color::Magenta => Self::DarkMagenta,
|
||||
Color::Cyan => Self::DarkCyan,
|
||||
Color::Gray => Self::Grey,
|
||||
Color::DarkGray => Self::DarkGrey,
|
||||
Color::LightRed => Self::Red,
|
||||
Color::LightGreen => Self::Green,
|
||||
Color::LightBlue => Self::Blue,
|
||||
Color::LightYellow => Self::Yellow,
|
||||
Color::LightMagenta => Self::Magenta,
|
||||
Color::LightCyan => Self::Cyan,
|
||||
Color::White => Self::White,
|
||||
Color::Indexed(i) => Self::AnsiValue(i),
|
||||
Color::Rgb(r, g, b) => Self::Rgb { r, g, b },
|
||||
/// A trait for converting a Ratatui type to a Crossterm type.
|
||||
///
|
||||
/// This trait is needed for avoiding the orphan rule when implementing `From` for crossterm types
|
||||
/// once these are moved to a separate crate.
|
||||
pub trait IntoCrossterm<C> {
|
||||
/// Converts the ratatui type to a crossterm type.
|
||||
fn into_crossterm(self) -> C;
|
||||
}
|
||||
|
||||
/// A trait for converting a Crossterm type to a Ratatui type.
|
||||
///
|
||||
/// This trait is needed for avoiding the orphan rule when implementing `From` for crossterm types
|
||||
/// once these are moved to a separate crate.
|
||||
pub trait FromCrossterm<C> {
|
||||
/// Converts the crossterm type to a ratatui type.
|
||||
fn from_crossterm(value: C) -> Self;
|
||||
}
|
||||
|
||||
impl IntoCrossterm<CrosstermColor> for Color {
|
||||
fn into_crossterm(self) -> CrosstermColor {
|
||||
match self {
|
||||
Self::Reset => CrosstermColor::Reset,
|
||||
Self::Black => CrosstermColor::Black,
|
||||
Self::Red => CrosstermColor::DarkRed,
|
||||
Self::Green => CrosstermColor::DarkGreen,
|
||||
Self::Yellow => CrosstermColor::DarkYellow,
|
||||
Self::Blue => CrosstermColor::DarkBlue,
|
||||
Self::Magenta => CrosstermColor::DarkMagenta,
|
||||
Self::Cyan => CrosstermColor::DarkCyan,
|
||||
Self::Gray => CrosstermColor::Grey,
|
||||
Self::DarkGray => CrosstermColor::DarkGrey,
|
||||
Self::LightRed => CrosstermColor::Red,
|
||||
Self::LightGreen => CrosstermColor::Green,
|
||||
Self::LightBlue => CrosstermColor::Blue,
|
||||
Self::LightYellow => CrosstermColor::Yellow,
|
||||
Self::LightMagenta => CrosstermColor::Magenta,
|
||||
Self::LightCyan => CrosstermColor::Cyan,
|
||||
Self::White => CrosstermColor::White,
|
||||
Self::Indexed(i) => CrosstermColor::AnsiValue(i),
|
||||
Self::Rgb(r, g, b) => CrosstermColor::Rgb { r, g, b },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CColor> for Color {
|
||||
fn from(value: CColor) -> Self {
|
||||
impl FromCrossterm<CrosstermColor> for Color {
|
||||
fn from_crossterm(value: CrosstermColor) -> Self {
|
||||
match value {
|
||||
CColor::Reset => Self::Reset,
|
||||
CColor::Black => Self::Black,
|
||||
CColor::DarkRed => Self::Red,
|
||||
CColor::DarkGreen => Self::Green,
|
||||
CColor::DarkYellow => Self::Yellow,
|
||||
CColor::DarkBlue => Self::Blue,
|
||||
CColor::DarkMagenta => Self::Magenta,
|
||||
CColor::DarkCyan => Self::Cyan,
|
||||
CColor::Grey => Self::Gray,
|
||||
CColor::DarkGrey => Self::DarkGray,
|
||||
CColor::Red => Self::LightRed,
|
||||
CColor::Green => Self::LightGreen,
|
||||
CColor::Blue => Self::LightBlue,
|
||||
CColor::Yellow => Self::LightYellow,
|
||||
CColor::Magenta => Self::LightMagenta,
|
||||
CColor::Cyan => Self::LightCyan,
|
||||
CColor::White => Self::White,
|
||||
CColor::Rgb { r, g, b } => Self::Rgb(r, g, b),
|
||||
CColor::AnsiValue(v) => Self::Indexed(v),
|
||||
CrosstermColor::Reset => Self::Reset,
|
||||
CrosstermColor::Black => Self::Black,
|
||||
CrosstermColor::DarkRed => Self::Red,
|
||||
CrosstermColor::DarkGreen => Self::Green,
|
||||
CrosstermColor::DarkYellow => Self::Yellow,
|
||||
CrosstermColor::DarkBlue => Self::Blue,
|
||||
CrosstermColor::DarkMagenta => Self::Magenta,
|
||||
CrosstermColor::DarkCyan => Self::Cyan,
|
||||
CrosstermColor::Grey => Self::Gray,
|
||||
CrosstermColor::DarkGrey => Self::DarkGray,
|
||||
CrosstermColor::Red => Self::LightRed,
|
||||
CrosstermColor::Green => Self::LightGreen,
|
||||
CrosstermColor::Blue => Self::LightBlue,
|
||||
CrosstermColor::Yellow => Self::LightYellow,
|
||||
CrosstermColor::Magenta => Self::LightMagenta,
|
||||
CrosstermColor::Cyan => Self::LightCyan,
|
||||
CrosstermColor::White => Self::White,
|
||||
CrosstermColor::Rgb { r, g, b } => Self::Rgb(r, g, b),
|
||||
CrosstermColor::AnsiValue(v) => Self::Indexed(v),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -370,142 +392,138 @@ impl ModifierDiff {
|
||||
//use crossterm::Attribute;
|
||||
let removed = self.from - self.to;
|
||||
if removed.contains(Modifier::REVERSED) {
|
||||
queue!(w, SetAttribute(CAttribute::NoReverse))?;
|
||||
queue!(w, SetAttribute(CrosstermAttribute::NoReverse))?;
|
||||
}
|
||||
if removed.contains(Modifier::BOLD) {
|
||||
queue!(w, SetAttribute(CAttribute::NormalIntensity))?;
|
||||
queue!(w, SetAttribute(CrosstermAttribute::NormalIntensity))?;
|
||||
if self.to.contains(Modifier::DIM) {
|
||||
queue!(w, SetAttribute(CAttribute::Dim))?;
|
||||
queue!(w, SetAttribute(CrosstermAttribute::Dim))?;
|
||||
}
|
||||
}
|
||||
if removed.contains(Modifier::ITALIC) {
|
||||
queue!(w, SetAttribute(CAttribute::NoItalic))?;
|
||||
queue!(w, SetAttribute(CrosstermAttribute::NoItalic))?;
|
||||
}
|
||||
if removed.contains(Modifier::UNDERLINED) {
|
||||
queue!(w, SetAttribute(CAttribute::NoUnderline))?;
|
||||
queue!(w, SetAttribute(CrosstermAttribute::NoUnderline))?;
|
||||
}
|
||||
if removed.contains(Modifier::DIM) {
|
||||
queue!(w, SetAttribute(CAttribute::NormalIntensity))?;
|
||||
queue!(w, SetAttribute(CrosstermAttribute::NormalIntensity))?;
|
||||
}
|
||||
if removed.contains(Modifier::CROSSED_OUT) {
|
||||
queue!(w, SetAttribute(CAttribute::NotCrossedOut))?;
|
||||
queue!(w, SetAttribute(CrosstermAttribute::NotCrossedOut))?;
|
||||
}
|
||||
if removed.contains(Modifier::SLOW_BLINK) || removed.contains(Modifier::RAPID_BLINK) {
|
||||
queue!(w, SetAttribute(CAttribute::NoBlink))?;
|
||||
queue!(w, SetAttribute(CrosstermAttribute::NoBlink))?;
|
||||
}
|
||||
|
||||
let added = self.to - self.from;
|
||||
if added.contains(Modifier::REVERSED) {
|
||||
queue!(w, SetAttribute(CAttribute::Reverse))?;
|
||||
queue!(w, SetAttribute(CrosstermAttribute::Reverse))?;
|
||||
}
|
||||
if added.contains(Modifier::BOLD) {
|
||||
queue!(w, SetAttribute(CAttribute::Bold))?;
|
||||
queue!(w, SetAttribute(CrosstermAttribute::Bold))?;
|
||||
}
|
||||
if added.contains(Modifier::ITALIC) {
|
||||
queue!(w, SetAttribute(CAttribute::Italic))?;
|
||||
queue!(w, SetAttribute(CrosstermAttribute::Italic))?;
|
||||
}
|
||||
if added.contains(Modifier::UNDERLINED) {
|
||||
queue!(w, SetAttribute(CAttribute::Underlined))?;
|
||||
queue!(w, SetAttribute(CrosstermAttribute::Underlined))?;
|
||||
}
|
||||
if added.contains(Modifier::DIM) {
|
||||
queue!(w, SetAttribute(CAttribute::Dim))?;
|
||||
queue!(w, SetAttribute(CrosstermAttribute::Dim))?;
|
||||
}
|
||||
if added.contains(Modifier::CROSSED_OUT) {
|
||||
queue!(w, SetAttribute(CAttribute::CrossedOut))?;
|
||||
queue!(w, SetAttribute(CrosstermAttribute::CrossedOut))?;
|
||||
}
|
||||
if added.contains(Modifier::SLOW_BLINK) {
|
||||
queue!(w, SetAttribute(CAttribute::SlowBlink))?;
|
||||
queue!(w, SetAttribute(CrosstermAttribute::SlowBlink))?;
|
||||
}
|
||||
if added.contains(Modifier::RAPID_BLINK) {
|
||||
queue!(w, SetAttribute(CAttribute::RapidBlink))?;
|
||||
queue!(w, SetAttribute(CrosstermAttribute::RapidBlink))?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CAttribute> for Modifier {
|
||||
fn from(value: CAttribute) -> Self {
|
||||
// `Attribute*s*` (note the *s*) contains multiple `Attribute`
|
||||
// We convert `Attribute` to `Attribute*s*` (containing only 1 value) to avoid implementing
|
||||
// the conversion again
|
||||
Self::from(CAttributes::from(value))
|
||||
impl FromCrossterm<CrosstermAttribute> for Modifier {
|
||||
fn from_crossterm(value: CrosstermAttribute) -> Self {
|
||||
// `Attribute*s*` (note the *s*) contains multiple `Attribute` We convert `Attribute` to
|
||||
// `Attribute*s*` (containing only 1 value) to avoid implementing the conversion again
|
||||
Self::from_crossterm(CrosstermAttributes::from(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CAttributes> for Modifier {
|
||||
fn from(value: CAttributes) -> Self {
|
||||
impl FromCrossterm<CrosstermAttributes> for Modifier {
|
||||
fn from_crossterm(value: CrosstermAttributes) -> Self {
|
||||
let mut res = Self::empty();
|
||||
|
||||
if value.has(CAttribute::Bold) {
|
||||
if value.has(CrosstermAttribute::Bold) {
|
||||
res |= Self::BOLD;
|
||||
}
|
||||
if value.has(CAttribute::Dim) {
|
||||
if value.has(CrosstermAttribute::Dim) {
|
||||
res |= Self::DIM;
|
||||
}
|
||||
if value.has(CAttribute::Italic) {
|
||||
if value.has(CrosstermAttribute::Italic) {
|
||||
res |= Self::ITALIC;
|
||||
}
|
||||
if value.has(CAttribute::Underlined)
|
||||
|| value.has(CAttribute::DoubleUnderlined)
|
||||
|| value.has(CAttribute::Undercurled)
|
||||
|| value.has(CAttribute::Underdotted)
|
||||
|| value.has(CAttribute::Underdashed)
|
||||
if value.has(CrosstermAttribute::Underlined)
|
||||
|| value.has(CrosstermAttribute::DoubleUnderlined)
|
||||
|| value.has(CrosstermAttribute::Undercurled)
|
||||
|| value.has(CrosstermAttribute::Underdotted)
|
||||
|| value.has(CrosstermAttribute::Underdashed)
|
||||
{
|
||||
res |= Self::UNDERLINED;
|
||||
}
|
||||
if value.has(CAttribute::SlowBlink) {
|
||||
if value.has(CrosstermAttribute::SlowBlink) {
|
||||
res |= Self::SLOW_BLINK;
|
||||
}
|
||||
if value.has(CAttribute::RapidBlink) {
|
||||
if value.has(CrosstermAttribute::RapidBlink) {
|
||||
res |= Self::RAPID_BLINK;
|
||||
}
|
||||
if value.has(CAttribute::Reverse) {
|
||||
if value.has(CrosstermAttribute::Reverse) {
|
||||
res |= Self::REVERSED;
|
||||
}
|
||||
if value.has(CAttribute::Hidden) {
|
||||
if value.has(CrosstermAttribute::Hidden) {
|
||||
res |= Self::HIDDEN;
|
||||
}
|
||||
if value.has(CAttribute::CrossedOut) {
|
||||
if value.has(CrosstermAttribute::CrossedOut) {
|
||||
res |= Self::CROSSED_OUT;
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ContentStyle> for Style {
|
||||
fn from(value: ContentStyle) -> Self {
|
||||
impl FromCrossterm<ContentStyle> for Style {
|
||||
fn from_crossterm(value: ContentStyle) -> Self {
|
||||
let mut sub_modifier = Modifier::empty();
|
||||
|
||||
if value.attributes.has(CAttribute::NoBold) {
|
||||
if value.attributes.has(CrosstermAttribute::NoBold) {
|
||||
sub_modifier |= Modifier::BOLD;
|
||||
}
|
||||
if value.attributes.has(CAttribute::NoItalic) {
|
||||
if value.attributes.has(CrosstermAttribute::NoItalic) {
|
||||
sub_modifier |= Modifier::ITALIC;
|
||||
}
|
||||
if value.attributes.has(CAttribute::NotCrossedOut) {
|
||||
if value.attributes.has(CrosstermAttribute::NotCrossedOut) {
|
||||
sub_modifier |= Modifier::CROSSED_OUT;
|
||||
}
|
||||
if value.attributes.has(CAttribute::NoUnderline) {
|
||||
if value.attributes.has(CrosstermAttribute::NoUnderline) {
|
||||
sub_modifier |= Modifier::UNDERLINED;
|
||||
}
|
||||
if value.attributes.has(CAttribute::NoHidden) {
|
||||
if value.attributes.has(CrosstermAttribute::NoHidden) {
|
||||
sub_modifier |= Modifier::HIDDEN;
|
||||
}
|
||||
if value.attributes.has(CAttribute::NoBlink) {
|
||||
if value.attributes.has(CrosstermAttribute::NoBlink) {
|
||||
sub_modifier |= Modifier::RAPID_BLINK | Modifier::SLOW_BLINK;
|
||||
}
|
||||
if value.attributes.has(CAttribute::NoReverse) {
|
||||
if value.attributes.has(CrosstermAttribute::NoReverse) {
|
||||
sub_modifier |= Modifier::REVERSED;
|
||||
}
|
||||
|
||||
Self {
|
||||
fg: value.foreground_color.map(Into::into),
|
||||
bg: value.background_color.map(Into::into),
|
||||
fg: value.foreground_color.map(FromCrossterm::from_crossterm),
|
||||
bg: value.background_color.map(FromCrossterm::from_crossterm),
|
||||
#[cfg(feature = "underline-color")]
|
||||
underline_color: value.underline_color.map(Into::into),
|
||||
add_modifier: value.attributes.into(),
|
||||
underline_color: value.underline_color.map(FromCrossterm::from_crossterm),
|
||||
add_modifier: Modifier::from_crossterm(value.attributes),
|
||||
sub_modifier,
|
||||
}
|
||||
}
|
||||
@@ -609,212 +627,174 @@ impl crate::crossterm::Command for ScrollDownInRegion {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use rstest::rstest;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn from_crossterm_color() {
|
||||
assert_eq!(Color::from(CColor::Reset), Color::Reset);
|
||||
assert_eq!(Color::from(CColor::Black), Color::Black);
|
||||
assert_eq!(Color::from(CColor::DarkGrey), Color::DarkGray);
|
||||
assert_eq!(Color::from(CColor::Red), Color::LightRed);
|
||||
assert_eq!(Color::from(CColor::DarkRed), Color::Red);
|
||||
assert_eq!(Color::from(CColor::Green), Color::LightGreen);
|
||||
assert_eq!(Color::from(CColor::DarkGreen), Color::Green);
|
||||
assert_eq!(Color::from(CColor::Yellow), Color::LightYellow);
|
||||
assert_eq!(Color::from(CColor::DarkYellow), Color::Yellow);
|
||||
assert_eq!(Color::from(CColor::Blue), Color::LightBlue);
|
||||
assert_eq!(Color::from(CColor::DarkBlue), Color::Blue);
|
||||
assert_eq!(Color::from(CColor::Magenta), Color::LightMagenta);
|
||||
assert_eq!(Color::from(CColor::DarkMagenta), Color::Magenta);
|
||||
assert_eq!(Color::from(CColor::Cyan), Color::LightCyan);
|
||||
assert_eq!(Color::from(CColor::DarkCyan), Color::Cyan);
|
||||
assert_eq!(Color::from(CColor::White), Color::White);
|
||||
assert_eq!(Color::from(CColor::Grey), Color::Gray);
|
||||
assert_eq!(
|
||||
Color::from(CColor::Rgb { r: 0, g: 0, b: 0 }),
|
||||
Color::Rgb(0, 0, 0)
|
||||
);
|
||||
assert_eq!(
|
||||
Color::from(CColor::Rgb {
|
||||
r: 10,
|
||||
g: 20,
|
||||
b: 30
|
||||
}),
|
||||
Color::Rgb(10, 20, 30)
|
||||
);
|
||||
assert_eq!(Color::from(CColor::AnsiValue(32)), Color::Indexed(32));
|
||||
assert_eq!(Color::from(CColor::AnsiValue(37)), Color::Indexed(37));
|
||||
#[rstest]
|
||||
#[case(CrosstermColor::Reset, Color::Reset)]
|
||||
#[case(CrosstermColor::Black, Color::Black)]
|
||||
#[case(CrosstermColor::DarkGrey, Color::DarkGray)]
|
||||
#[case(CrosstermColor::Red, Color::LightRed)]
|
||||
#[case(CrosstermColor::DarkRed, Color::Red)]
|
||||
#[case(CrosstermColor::Green, Color::LightGreen)]
|
||||
#[case(CrosstermColor::DarkGreen, Color::Green)]
|
||||
#[case(CrosstermColor::Yellow, Color::LightYellow)]
|
||||
#[case(CrosstermColor::DarkYellow, Color::Yellow)]
|
||||
#[case(CrosstermColor::Blue, Color::LightBlue)]
|
||||
#[case(CrosstermColor::DarkBlue, Color::Blue)]
|
||||
#[case(CrosstermColor::Magenta, Color::LightMagenta)]
|
||||
#[case(CrosstermColor::DarkMagenta, Color::Magenta)]
|
||||
#[case(CrosstermColor::Cyan, Color::LightCyan)]
|
||||
#[case(CrosstermColor::DarkCyan, Color::Cyan)]
|
||||
#[case(CrosstermColor::White, Color::White)]
|
||||
#[case(CrosstermColor::Grey, Color::Gray)]
|
||||
#[case(CrosstermColor::Rgb { r: 0, g: 0, b: 0 }, Color::Rgb(0, 0, 0) )]
|
||||
#[case(CrosstermColor::Rgb { r: 10, g: 20, b: 30 }, Color::Rgb(10, 20, 30) )]
|
||||
#[case(CrosstermColor::AnsiValue(32), Color::Indexed(32))]
|
||||
#[case(CrosstermColor::AnsiValue(37), Color::Indexed(37))]
|
||||
fn from_crossterm_color(#[case] crossterm_color: CrosstermColor, #[case] color: Color) {
|
||||
assert_eq!(Color::from_crossterm(crossterm_color), color);
|
||||
}
|
||||
|
||||
mod modifier {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn from_crossterm_attribute() {
|
||||
assert_eq!(Modifier::from(CAttribute::Reset), Modifier::empty());
|
||||
assert_eq!(Modifier::from(CAttribute::Bold), Modifier::BOLD);
|
||||
assert_eq!(Modifier::from(CAttribute::Italic), Modifier::ITALIC);
|
||||
assert_eq!(Modifier::from(CAttribute::Underlined), Modifier::UNDERLINED);
|
||||
#[rstest]
|
||||
#[case(CrosstermAttribute::Reset, Modifier::empty())]
|
||||
#[case(CrosstermAttribute::Bold, Modifier::BOLD)]
|
||||
#[case(CrosstermAttribute::NoBold, Modifier::empty())]
|
||||
#[case(CrosstermAttribute::Italic, Modifier::ITALIC)]
|
||||
#[case(CrosstermAttribute::NoItalic, Modifier::empty())]
|
||||
#[case(CrosstermAttribute::Underlined, Modifier::UNDERLINED)]
|
||||
#[case(CrosstermAttribute::NoUnderline, Modifier::empty())]
|
||||
#[case(CrosstermAttribute::OverLined, Modifier::empty())]
|
||||
#[case(CrosstermAttribute::NotOverLined, Modifier::empty())]
|
||||
#[case(CrosstermAttribute::DoubleUnderlined, Modifier::UNDERLINED)]
|
||||
#[case(CrosstermAttribute::Undercurled, Modifier::UNDERLINED)]
|
||||
#[case(CrosstermAttribute::Underdotted, Modifier::UNDERLINED)]
|
||||
#[case(CrosstermAttribute::Underdashed, Modifier::UNDERLINED)]
|
||||
#[case(CrosstermAttribute::Dim, Modifier::DIM)]
|
||||
#[case(CrosstermAttribute::NormalIntensity, Modifier::empty())]
|
||||
#[case(CrosstermAttribute::CrossedOut, Modifier::CROSSED_OUT)]
|
||||
#[case(CrosstermAttribute::NotCrossedOut, Modifier::empty())]
|
||||
#[case(CrosstermAttribute::NoUnderline, Modifier::empty())]
|
||||
#[case(CrosstermAttribute::SlowBlink, Modifier::SLOW_BLINK)]
|
||||
#[case(CrosstermAttribute::RapidBlink, Modifier::RAPID_BLINK)]
|
||||
#[case(CrosstermAttribute::Hidden, Modifier::HIDDEN)]
|
||||
#[case(CrosstermAttribute::NoHidden, Modifier::empty())]
|
||||
#[case(CrosstermAttribute::Reverse, Modifier::REVERSED)]
|
||||
#[case(CrosstermAttribute::NoReverse, Modifier::empty())]
|
||||
fn from_crossterm_attribute(
|
||||
#[case] crossterm_attribute: CrosstermAttribute,
|
||||
#[case] ratatui_modifier: Modifier,
|
||||
) {
|
||||
assert_eq!(
|
||||
Modifier::from(CAttribute::DoubleUnderlined),
|
||||
Modifier::UNDERLINED
|
||||
Modifier::from_crossterm(crossterm_attribute),
|
||||
ratatui_modifier
|
||||
);
|
||||
assert_eq!(
|
||||
Modifier::from(CAttribute::Underdotted),
|
||||
Modifier::UNDERLINED
|
||||
);
|
||||
assert_eq!(Modifier::from(CAttribute::Dim), Modifier::DIM);
|
||||
assert_eq!(
|
||||
Modifier::from(CAttribute::NormalIntensity),
|
||||
Modifier::empty()
|
||||
);
|
||||
assert_eq!(
|
||||
Modifier::from(CAttribute::CrossedOut),
|
||||
Modifier::CROSSED_OUT
|
||||
);
|
||||
assert_eq!(Modifier::from(CAttribute::NoUnderline), Modifier::empty());
|
||||
assert_eq!(Modifier::from(CAttribute::OverLined), Modifier::empty());
|
||||
assert_eq!(Modifier::from(CAttribute::SlowBlink), Modifier::SLOW_BLINK);
|
||||
assert_eq!(
|
||||
Modifier::from(CAttribute::RapidBlink),
|
||||
Modifier::RAPID_BLINK
|
||||
);
|
||||
assert_eq!(Modifier::from(CAttribute::Hidden), Modifier::HIDDEN);
|
||||
assert_eq!(Modifier::from(CAttribute::NoHidden), Modifier::empty());
|
||||
assert_eq!(Modifier::from(CAttribute::Reverse), Modifier::REVERSED);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_crossterm_attributes() {
|
||||
#[rstest]
|
||||
#[case(&[CrosstermAttribute::Bold], Modifier::BOLD)]
|
||||
#[case(&[CrosstermAttribute::Bold, CrosstermAttribute::Italic], Modifier::BOLD | Modifier::ITALIC)]
|
||||
#[case(&[CrosstermAttribute::Bold, CrosstermAttribute::NotCrossedOut], Modifier::BOLD)]
|
||||
#[case(&[CrosstermAttribute::Dim, CrosstermAttribute::Underdotted], Modifier::DIM | Modifier::UNDERLINED)]
|
||||
#[case(&[CrosstermAttribute::Dim, CrosstermAttribute::SlowBlink, CrosstermAttribute::Italic], Modifier::DIM | Modifier::SLOW_BLINK | Modifier::ITALIC)]
|
||||
#[case(&[CrosstermAttribute::Hidden, CrosstermAttribute::NoUnderline, CrosstermAttribute::NotCrossedOut], Modifier::HIDDEN)]
|
||||
#[case(&[CrosstermAttribute::Reverse], Modifier::REVERSED)]
|
||||
#[case(&[CrosstermAttribute::Reset], Modifier::empty())]
|
||||
#[case(&[CrosstermAttribute::RapidBlink, CrosstermAttribute::CrossedOut], Modifier::RAPID_BLINK | Modifier::CROSSED_OUT)]
|
||||
fn from_crossterm_attributes(
|
||||
#[case] crossterm_attributes: &[CrosstermAttribute],
|
||||
#[case] ratatui_modifier: Modifier,
|
||||
) {
|
||||
assert_eq!(
|
||||
Modifier::from(CAttributes::from(CAttribute::Bold)),
|
||||
Modifier::BOLD
|
||||
);
|
||||
assert_eq!(
|
||||
Modifier::from(CAttributes::from(
|
||||
[CAttribute::Bold, CAttribute::Italic].as_ref()
|
||||
)),
|
||||
Modifier::BOLD | Modifier::ITALIC
|
||||
);
|
||||
assert_eq!(
|
||||
Modifier::from(CAttributes::from(
|
||||
[CAttribute::Bold, CAttribute::NotCrossedOut].as_ref()
|
||||
)),
|
||||
Modifier::BOLD
|
||||
);
|
||||
assert_eq!(
|
||||
Modifier::from(CAttributes::from(
|
||||
[CAttribute::Dim, CAttribute::Underdotted].as_ref()
|
||||
)),
|
||||
Modifier::DIM | Modifier::UNDERLINED
|
||||
);
|
||||
assert_eq!(
|
||||
Modifier::from(CAttributes::from(
|
||||
[CAttribute::Dim, CAttribute::SlowBlink, CAttribute::Italic].as_ref()
|
||||
)),
|
||||
Modifier::DIM | Modifier::SLOW_BLINK | Modifier::ITALIC
|
||||
);
|
||||
assert_eq!(
|
||||
Modifier::from(CAttributes::from(
|
||||
[
|
||||
CAttribute::Hidden,
|
||||
CAttribute::NoUnderline,
|
||||
CAttribute::NotCrossedOut
|
||||
]
|
||||
.as_ref()
|
||||
)),
|
||||
Modifier::HIDDEN
|
||||
);
|
||||
assert_eq!(
|
||||
Modifier::from(CAttributes::from(CAttribute::Reverse)),
|
||||
Modifier::REVERSED
|
||||
);
|
||||
assert_eq!(
|
||||
Modifier::from(CAttributes::from(CAttribute::Reset)),
|
||||
Modifier::empty()
|
||||
);
|
||||
assert_eq!(
|
||||
Modifier::from(CAttributes::from(
|
||||
[CAttribute::RapidBlink, CAttribute::CrossedOut].as_ref()
|
||||
)),
|
||||
Modifier::RAPID_BLINK | Modifier::CROSSED_OUT
|
||||
Modifier::from_crossterm(CrosstermAttributes::from(crossterm_attributes)),
|
||||
ratatui_modifier
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_crossterm_content_style() {
|
||||
assert_eq!(Style::from(ContentStyle::default()), Style::default());
|
||||
assert_eq!(
|
||||
Style::from(ContentStyle {
|
||||
foreground_color: Some(CColor::DarkYellow),
|
||||
..Default::default()
|
||||
}),
|
||||
Style::default().fg(Color::Yellow)
|
||||
);
|
||||
assert_eq!(
|
||||
Style::from(ContentStyle {
|
||||
background_color: Some(CColor::DarkYellow),
|
||||
..Default::default()
|
||||
}),
|
||||
Style::default().bg(Color::Yellow)
|
||||
);
|
||||
assert_eq!(
|
||||
Style::from(ContentStyle {
|
||||
attributes: CAttributes::from(CAttribute::Bold),
|
||||
..Default::default()
|
||||
}),
|
||||
Style::default().add_modifier(Modifier::BOLD)
|
||||
);
|
||||
assert_eq!(
|
||||
Style::from(ContentStyle {
|
||||
attributes: CAttributes::from(CAttribute::NoBold),
|
||||
..Default::default()
|
||||
}),
|
||||
Style::default().remove_modifier(Modifier::BOLD)
|
||||
);
|
||||
assert_eq!(
|
||||
Style::from(ContentStyle {
|
||||
attributes: CAttributes::from(CAttribute::Italic),
|
||||
..Default::default()
|
||||
}),
|
||||
Style::default().add_modifier(Modifier::ITALIC)
|
||||
);
|
||||
assert_eq!(
|
||||
Style::from(ContentStyle {
|
||||
attributes: CAttributes::from(CAttribute::NoItalic),
|
||||
..Default::default()
|
||||
}),
|
||||
Style::default().remove_modifier(Modifier::ITALIC)
|
||||
);
|
||||
assert_eq!(
|
||||
Style::from(ContentStyle {
|
||||
attributes: CAttributes::from([CAttribute::Bold, CAttribute::Italic].as_ref()),
|
||||
..Default::default()
|
||||
}),
|
||||
Style::default()
|
||||
.add_modifier(Modifier::BOLD)
|
||||
.add_modifier(Modifier::ITALIC)
|
||||
);
|
||||
assert_eq!(
|
||||
Style::from(ContentStyle {
|
||||
attributes: CAttributes::from([CAttribute::NoBold, CAttribute::NoItalic].as_ref()),
|
||||
..Default::default()
|
||||
}),
|
||||
Style::default()
|
||||
.remove_modifier(Modifier::BOLD)
|
||||
.remove_modifier(Modifier::ITALIC)
|
||||
);
|
||||
#[rstest]
|
||||
#[case(ContentStyle::default(), Style::default())]
|
||||
#[case(
|
||||
ContentStyle {
|
||||
foreground_color: Some(CrosstermColor::DarkYellow),
|
||||
..Default::default()
|
||||
},
|
||||
Style::default().fg(Color::Yellow)
|
||||
)]
|
||||
#[case(
|
||||
ContentStyle {
|
||||
background_color: Some(CrosstermColor::DarkYellow),
|
||||
..Default::default()
|
||||
},
|
||||
Style::default().bg(Color::Yellow)
|
||||
)]
|
||||
#[case(
|
||||
ContentStyle {
|
||||
attributes: CrosstermAttributes::from(CrosstermAttribute::Bold),
|
||||
..Default::default()
|
||||
},
|
||||
Style::default().add_modifier(Modifier::BOLD)
|
||||
)]
|
||||
#[case(
|
||||
ContentStyle {
|
||||
attributes: CrosstermAttributes::from(CrosstermAttribute::NoBold),
|
||||
..Default::default()
|
||||
},
|
||||
Style::default().remove_modifier(Modifier::BOLD)
|
||||
)]
|
||||
#[case(
|
||||
ContentStyle {
|
||||
attributes: CrosstermAttributes::from(CrosstermAttribute::Italic),
|
||||
..Default::default()
|
||||
},
|
||||
Style::default().add_modifier(Modifier::ITALIC)
|
||||
)]
|
||||
#[case(
|
||||
ContentStyle {
|
||||
attributes: CrosstermAttributes::from(CrosstermAttribute::NoItalic),
|
||||
..Default::default()
|
||||
},
|
||||
Style::default().remove_modifier(Modifier::ITALIC)
|
||||
)]
|
||||
#[case(
|
||||
ContentStyle {
|
||||
attributes: CrosstermAttributes::from(
|
||||
[CrosstermAttribute::Bold, CrosstermAttribute::Italic].as_ref()
|
||||
),
|
||||
..Default::default()
|
||||
},
|
||||
Style::default()
|
||||
.add_modifier(Modifier::BOLD)
|
||||
.add_modifier(Modifier::ITALIC)
|
||||
)]
|
||||
#[case(
|
||||
ContentStyle {
|
||||
attributes: CrosstermAttributes::from(
|
||||
[CrosstermAttribute::NoBold, CrosstermAttribute::NoItalic].as_ref()
|
||||
),
|
||||
..Default::default()
|
||||
},
|
||||
Style::default()
|
||||
.remove_modifier(Modifier::BOLD)
|
||||
.remove_modifier(Modifier::ITALIC)
|
||||
)]
|
||||
fn from_crossterm_content_style(#[case] content_style: ContentStyle, #[case] style: Style) {
|
||||
assert_eq!(Style::from_crossterm(content_style), style);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "underline-color")]
|
||||
fn from_crossterm_content_style_underline() {
|
||||
let content_style = ContentStyle {
|
||||
underline_color: Some(CrosstermColor::DarkRed),
|
||||
..Default::default()
|
||||
};
|
||||
assert_eq!(
|
||||
Style::from(ContentStyle {
|
||||
underline_color: Some(CColor::DarkRed),
|
||||
..Default::default()
|
||||
}),
|
||||
Style::from_crossterm(content_style),
|
||||
Style::default().underline_color(Color::Red)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -327,22 +327,40 @@ impl fmt::Display for Bg {
|
||||
}
|
||||
}
|
||||
|
||||
/// A trait for converting a Termion type to a Ratatui type.
|
||||
///
|
||||
/// This trait is necessary to avoid the orphan rule, as we cannot implement a trait for a type
|
||||
/// defined in another crate.
|
||||
pub trait FromTermion<T> {
|
||||
/// Convert the Termion type to the Ratatui type.
|
||||
fn from_termion(termion: T) -> Self;
|
||||
}
|
||||
|
||||
/// A trait for converting a Ratatui type to a Termion type.
|
||||
///
|
||||
/// This trait is necessary to avoid the orphan rule, as we cannot implement a trait for a type
|
||||
/// defined in another crate.
|
||||
pub trait IntoTermion<T> {
|
||||
/// Convert the Ratatui type to the Termion type.
|
||||
fn into_termion(self) -> T;
|
||||
}
|
||||
|
||||
macro_rules! from_termion_for_color {
|
||||
($termion_color:ident, $color:ident) => {
|
||||
impl From<tcolor::$termion_color> for Color {
|
||||
fn from(_: tcolor::$termion_color) -> Self {
|
||||
impl FromTermion<tcolor::$termion_color> for Color {
|
||||
fn from_termion(_: tcolor::$termion_color) -> Self {
|
||||
Color::$color
|
||||
}
|
||||
}
|
||||
|
||||
impl From<tcolor::Bg<tcolor::$termion_color>> for Style {
|
||||
fn from(_: tcolor::Bg<tcolor::$termion_color>) -> Self {
|
||||
impl FromTermion<tcolor::Bg<tcolor::$termion_color>> for Style {
|
||||
fn from_termion(_: tcolor::Bg<tcolor::$termion_color>) -> Self {
|
||||
Style::default().bg(Color::$color)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<tcolor::Fg<tcolor::$termion_color>> for Style {
|
||||
fn from(_: tcolor::Fg<tcolor::$termion_color>) -> Self {
|
||||
impl FromTermion<tcolor::Fg<tcolor::$termion_color>> for Style {
|
||||
fn from_termion(_: tcolor::Fg<tcolor::$termion_color>) -> Self {
|
||||
Style::default().fg(Color::$color)
|
||||
}
|
||||
}
|
||||
@@ -367,38 +385,38 @@ from_termion_for_color!(LightMagenta, LightMagenta);
|
||||
from_termion_for_color!(LightCyan, LightCyan);
|
||||
from_termion_for_color!(LightWhite, White);
|
||||
|
||||
impl From<tcolor::AnsiValue> for Color {
|
||||
fn from(value: tcolor::AnsiValue) -> Self {
|
||||
impl FromTermion<tcolor::AnsiValue> for Color {
|
||||
fn from_termion(value: tcolor::AnsiValue) -> Self {
|
||||
Self::Indexed(value.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<tcolor::Bg<tcolor::AnsiValue>> for Style {
|
||||
fn from(value: tcolor::Bg<tcolor::AnsiValue>) -> Self {
|
||||
impl FromTermion<tcolor::Bg<tcolor::AnsiValue>> for Style {
|
||||
fn from_termion(value: tcolor::Bg<tcolor::AnsiValue>) -> Self {
|
||||
Self::default().bg(Color::Indexed(value.0 .0))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<tcolor::Fg<tcolor::AnsiValue>> for Style {
|
||||
fn from(value: tcolor::Fg<tcolor::AnsiValue>) -> Self {
|
||||
impl FromTermion<tcolor::Fg<tcolor::AnsiValue>> for Style {
|
||||
fn from_termion(value: tcolor::Fg<tcolor::AnsiValue>) -> Self {
|
||||
Self::default().fg(Color::Indexed(value.0 .0))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<tcolor::Rgb> for Color {
|
||||
fn from(value: tcolor::Rgb) -> Self {
|
||||
impl FromTermion<tcolor::Rgb> for Color {
|
||||
fn from_termion(value: tcolor::Rgb) -> Self {
|
||||
Self::Rgb(value.0, value.1, value.2)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<tcolor::Bg<tcolor::Rgb>> for Style {
|
||||
fn from(value: tcolor::Bg<tcolor::Rgb>) -> Self {
|
||||
impl FromTermion<tcolor::Bg<tcolor::Rgb>> for Style {
|
||||
fn from_termion(value: tcolor::Bg<tcolor::Rgb>) -> Self {
|
||||
Self::default().bg(Color::Rgb(value.0 .0, value.0 .1, value.0 .2))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<tcolor::Fg<tcolor::Rgb>> for Style {
|
||||
fn from(value: tcolor::Fg<tcolor::Rgb>) -> Self {
|
||||
impl FromTermion<tcolor::Fg<tcolor::Rgb>> for Style {
|
||||
fn from_termion(value: tcolor::Fg<tcolor::Rgb>) -> Self {
|
||||
Self::default().fg(Color::Rgb(value.0 .0, value.0 .1, value.0 .2))
|
||||
}
|
||||
}
|
||||
@@ -470,8 +488,8 @@ impl fmt::Display for ModifierDiff {
|
||||
|
||||
macro_rules! from_termion_for_modifier {
|
||||
($termion_modifier:ident, $modifier:ident) => {
|
||||
impl From<tstyle::$termion_modifier> for Modifier {
|
||||
fn from(_: tstyle::$termion_modifier) -> Self {
|
||||
impl FromTermion<tstyle::$termion_modifier> for Modifier {
|
||||
fn from_termion(_: tstyle::$termion_modifier) -> Self {
|
||||
Modifier::$modifier
|
||||
}
|
||||
}
|
||||
@@ -486,8 +504,8 @@ from_termion_for_modifier!(Faint, DIM);
|
||||
from_termion_for_modifier!(CrossedOut, CROSSED_OUT);
|
||||
from_termion_for_modifier!(Blink, SLOW_BLINK);
|
||||
|
||||
impl From<termion::style::Reset> for Modifier {
|
||||
fn from(_: termion::style::Reset) -> Self {
|
||||
impl FromTermion<termion::style::Reset> for Modifier {
|
||||
fn from_termion(_: termion::style::Reset) -> Self {
|
||||
Self::empty()
|
||||
}
|
||||
}
|
||||
@@ -519,25 +537,34 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn from_termion_color() {
|
||||
assert_eq!(Color::from(tcolor::Reset), Color::Reset);
|
||||
assert_eq!(Color::from(tcolor::Black), Color::Black);
|
||||
assert_eq!(Color::from(tcolor::Red), Color::Red);
|
||||
assert_eq!(Color::from(tcolor::Green), Color::Green);
|
||||
assert_eq!(Color::from(tcolor::Yellow), Color::Yellow);
|
||||
assert_eq!(Color::from(tcolor::Blue), Color::Blue);
|
||||
assert_eq!(Color::from(tcolor::Magenta), Color::Magenta);
|
||||
assert_eq!(Color::from(tcolor::Cyan), Color::Cyan);
|
||||
assert_eq!(Color::from(tcolor::White), Color::Gray);
|
||||
assert_eq!(Color::from(tcolor::LightBlack), Color::DarkGray);
|
||||
assert_eq!(Color::from(tcolor::LightRed), Color::LightRed);
|
||||
assert_eq!(Color::from(tcolor::LightGreen), Color::LightGreen);
|
||||
assert_eq!(Color::from(tcolor::LightBlue), Color::LightBlue);
|
||||
assert_eq!(Color::from(tcolor::LightYellow), Color::LightYellow);
|
||||
assert_eq!(Color::from(tcolor::LightMagenta), Color::LightMagenta);
|
||||
assert_eq!(Color::from(tcolor::LightCyan), Color::LightCyan);
|
||||
assert_eq!(Color::from(tcolor::LightWhite), Color::White);
|
||||
assert_eq!(Color::from(tcolor::AnsiValue(31)), Color::Indexed(31));
|
||||
assert_eq!(Color::from(tcolor::Rgb(1, 2, 3)), Color::Rgb(1, 2, 3));
|
||||
assert_eq!(Color::from_termion(tcolor::Reset), Color::Reset);
|
||||
assert_eq!(Color::from_termion(tcolor::Black), Color::Black);
|
||||
assert_eq!(Color::from_termion(tcolor::Red), Color::Red);
|
||||
assert_eq!(Color::from_termion(tcolor::Green), Color::Green);
|
||||
assert_eq!(Color::from_termion(tcolor::Yellow), Color::Yellow);
|
||||
assert_eq!(Color::from_termion(tcolor::Blue), Color::Blue);
|
||||
assert_eq!(Color::from_termion(tcolor::Magenta), Color::Magenta);
|
||||
assert_eq!(Color::from_termion(tcolor::Cyan), Color::Cyan);
|
||||
assert_eq!(Color::from_termion(tcolor::White), Color::Gray);
|
||||
assert_eq!(Color::from_termion(tcolor::LightBlack), Color::DarkGray);
|
||||
assert_eq!(Color::from_termion(tcolor::LightRed), Color::LightRed);
|
||||
assert_eq!(Color::from_termion(tcolor::LightGreen), Color::LightGreen);
|
||||
assert_eq!(Color::from_termion(tcolor::LightBlue), Color::LightBlue);
|
||||
assert_eq!(Color::from_termion(tcolor::LightYellow), Color::LightYellow);
|
||||
assert_eq!(
|
||||
Color::from_termion(tcolor::LightMagenta),
|
||||
Color::LightMagenta
|
||||
);
|
||||
assert_eq!(Color::from_termion(tcolor::LightCyan), Color::LightCyan);
|
||||
assert_eq!(Color::from_termion(tcolor::LightWhite), Color::White);
|
||||
assert_eq!(
|
||||
Color::from_termion(tcolor::AnsiValue(31)),
|
||||
Color::Indexed(31)
|
||||
);
|
||||
assert_eq!(
|
||||
Color::from_termion(tcolor::Rgb(1, 2, 3)),
|
||||
Color::Rgb(1, 2, 3)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -545,38 +572,62 @@ mod tests {
|
||||
use tc::Bg;
|
||||
use tcolor as tc;
|
||||
|
||||
assert_eq!(Style::from(Bg(tc::Reset)), Style::new().bg(Color::Reset));
|
||||
assert_eq!(Style::from(Bg(tc::Black)), Style::new().on_black());
|
||||
assert_eq!(Style::from(Bg(tc::Red)), Style::new().on_red());
|
||||
assert_eq!(Style::from(Bg(tc::Green)), Style::new().on_green());
|
||||
assert_eq!(Style::from(Bg(tc::Yellow)), Style::new().on_yellow());
|
||||
assert_eq!(Style::from(Bg(tc::Blue)), Style::new().on_blue());
|
||||
assert_eq!(Style::from(Bg(tc::Magenta)), Style::new().on_magenta());
|
||||
assert_eq!(Style::from(Bg(tc::Cyan)), Style::new().on_cyan());
|
||||
assert_eq!(Style::from(Bg(tc::White)), Style::new().on_gray());
|
||||
assert_eq!(Style::from(Bg(tc::LightBlack)), Style::new().on_dark_gray());
|
||||
assert_eq!(Style::from(Bg(tc::LightRed)), Style::new().on_light_red());
|
||||
assert_eq!(
|
||||
Style::from(Bg(tc::LightGreen)),
|
||||
Style::from_termion(Bg(tc::Reset)),
|
||||
Style::new().bg(Color::Reset)
|
||||
);
|
||||
assert_eq!(Style::from_termion(Bg(tc::Black)), Style::new().on_black());
|
||||
assert_eq!(Style::from_termion(Bg(tc::Red)), Style::new().on_red());
|
||||
assert_eq!(Style::from_termion(Bg(tc::Green)), Style::new().on_green());
|
||||
assert_eq!(
|
||||
Style::from_termion(Bg(tc::Yellow)),
|
||||
Style::new().on_yellow()
|
||||
);
|
||||
assert_eq!(Style::from_termion(Bg(tc::Blue)), Style::new().on_blue());
|
||||
assert_eq!(
|
||||
Style::from_termion(Bg(tc::Magenta)),
|
||||
Style::new().on_magenta()
|
||||
);
|
||||
assert_eq!(Style::from_termion(Bg(tc::Cyan)), Style::new().on_cyan());
|
||||
assert_eq!(Style::from_termion(Bg(tc::White)), Style::new().on_gray());
|
||||
assert_eq!(
|
||||
Style::from_termion(Bg(tc::LightBlack)),
|
||||
Style::new().on_dark_gray()
|
||||
);
|
||||
assert_eq!(
|
||||
Style::from_termion(Bg(tc::LightRed)),
|
||||
Style::new().on_light_red()
|
||||
);
|
||||
assert_eq!(
|
||||
Style::from_termion(Bg(tc::LightGreen)),
|
||||
Style::new().on_light_green()
|
||||
);
|
||||
assert_eq!(Style::from(Bg(tc::LightBlue)), Style::new().on_light_blue());
|
||||
assert_eq!(
|
||||
Style::from(Bg(tc::LightYellow)),
|
||||
Style::from_termion(Bg(tc::LightBlue)),
|
||||
Style::new().on_light_blue()
|
||||
);
|
||||
assert_eq!(
|
||||
Style::from_termion(Bg(tc::LightYellow)),
|
||||
Style::new().on_light_yellow()
|
||||
);
|
||||
assert_eq!(
|
||||
Style::from(Bg(tc::LightMagenta)),
|
||||
Style::from_termion(Bg(tc::LightMagenta)),
|
||||
Style::new().on_light_magenta()
|
||||
);
|
||||
assert_eq!(Style::from(Bg(tc::LightCyan)), Style::new().on_light_cyan());
|
||||
assert_eq!(Style::from(Bg(tc::LightWhite)), Style::new().on_white());
|
||||
assert_eq!(
|
||||
Style::from(Bg(tc::AnsiValue(31))),
|
||||
Style::from_termion(Bg(tc::LightCyan)),
|
||||
Style::new().on_light_cyan()
|
||||
);
|
||||
assert_eq!(
|
||||
Style::from_termion(Bg(tc::LightWhite)),
|
||||
Style::new().on_white()
|
||||
);
|
||||
assert_eq!(
|
||||
Style::from_termion(Bg(tc::AnsiValue(31))),
|
||||
Style::new().bg(Color::Indexed(31))
|
||||
);
|
||||
assert_eq!(
|
||||
Style::from(Bg(tc::Rgb(1, 2, 3))),
|
||||
Style::from_termion(Bg(tc::Rgb(1, 2, 3))),
|
||||
Style::new().bg(Color::Rgb(1, 2, 3))
|
||||
);
|
||||
}
|
||||
@@ -586,48 +637,78 @@ mod tests {
|
||||
use tc::Fg;
|
||||
use tcolor as tc;
|
||||
|
||||
assert_eq!(Style::from(Fg(tc::Reset)), Style::new().fg(Color::Reset));
|
||||
assert_eq!(Style::from(Fg(tc::Black)), Style::new().black());
|
||||
assert_eq!(Style::from(Fg(tc::Red)), Style::new().red());
|
||||
assert_eq!(Style::from(Fg(tc::Green)), Style::new().green());
|
||||
assert_eq!(Style::from(Fg(tc::Yellow)), Style::new().yellow());
|
||||
assert_eq!(Style::from(Fg(tc::Blue)), Style::default().blue());
|
||||
assert_eq!(Style::from(Fg(tc::Magenta)), Style::default().magenta());
|
||||
assert_eq!(Style::from(Fg(tc::Cyan)), Style::default().cyan());
|
||||
assert_eq!(Style::from(Fg(tc::White)), Style::default().gray());
|
||||
assert_eq!(Style::from(Fg(tc::LightBlack)), Style::new().dark_gray());
|
||||
assert_eq!(Style::from(Fg(tc::LightRed)), Style::new().light_red());
|
||||
assert_eq!(Style::from(Fg(tc::LightGreen)), Style::new().light_green());
|
||||
assert_eq!(Style::from(Fg(tc::LightBlue)), Style::new().light_blue());
|
||||
assert_eq!(
|
||||
Style::from(Fg(tc::LightYellow)),
|
||||
Style::from_termion(Fg(tc::Reset)),
|
||||
Style::new().fg(Color::Reset)
|
||||
);
|
||||
assert_eq!(Style::from_termion(Fg(tc::Black)), Style::new().black());
|
||||
assert_eq!(Style::from_termion(Fg(tc::Red)), Style::new().red());
|
||||
assert_eq!(Style::from_termion(Fg(tc::Green)), Style::new().green());
|
||||
assert_eq!(Style::from_termion(Fg(tc::Yellow)), Style::new().yellow());
|
||||
assert_eq!(Style::from_termion(Fg(tc::Blue)), Style::default().blue());
|
||||
assert_eq!(
|
||||
Style::from_termion(Fg(tc::Magenta)),
|
||||
Style::default().magenta()
|
||||
);
|
||||
assert_eq!(Style::from_termion(Fg(tc::Cyan)), Style::default().cyan());
|
||||
assert_eq!(Style::from_termion(Fg(tc::White)), Style::default().gray());
|
||||
assert_eq!(
|
||||
Style::from_termion(Fg(tc::LightBlack)),
|
||||
Style::new().dark_gray()
|
||||
);
|
||||
assert_eq!(
|
||||
Style::from_termion(Fg(tc::LightRed)),
|
||||
Style::new().light_red()
|
||||
);
|
||||
assert_eq!(
|
||||
Style::from_termion(Fg(tc::LightGreen)),
|
||||
Style::new().light_green()
|
||||
);
|
||||
assert_eq!(
|
||||
Style::from_termion(Fg(tc::LightBlue)),
|
||||
Style::new().light_blue()
|
||||
);
|
||||
assert_eq!(
|
||||
Style::from_termion(Fg(tc::LightYellow)),
|
||||
Style::new().light_yellow()
|
||||
);
|
||||
assert_eq!(
|
||||
Style::from(Fg(tc::LightMagenta)),
|
||||
Style::from_termion(Fg(tc::LightMagenta)),
|
||||
Style::new().light_magenta()
|
||||
);
|
||||
assert_eq!(Style::from(Fg(tc::LightCyan)), Style::new().light_cyan());
|
||||
assert_eq!(Style::from(Fg(tc::LightWhite)), Style::new().white());
|
||||
assert_eq!(
|
||||
Style::from(Fg(tc::AnsiValue(31))),
|
||||
Style::from_termion(Fg(tc::LightCyan)),
|
||||
Style::new().light_cyan()
|
||||
);
|
||||
assert_eq!(
|
||||
Style::from_termion(Fg(tc::LightWhite)),
|
||||
Style::new().white()
|
||||
);
|
||||
assert_eq!(
|
||||
Style::from_termion(Fg(tc::AnsiValue(31))),
|
||||
Style::default().fg(Color::Indexed(31))
|
||||
);
|
||||
assert_eq!(
|
||||
Style::from(Fg(tc::Rgb(1, 2, 3))),
|
||||
Style::from_termion(Fg(tc::Rgb(1, 2, 3))),
|
||||
Style::default().fg(Color::Rgb(1, 2, 3))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_termion_style() {
|
||||
assert_eq!(Modifier::from(tstyle::Invert), Modifier::REVERSED);
|
||||
assert_eq!(Modifier::from(tstyle::Bold), Modifier::BOLD);
|
||||
assert_eq!(Modifier::from(tstyle::Italic), Modifier::ITALIC);
|
||||
assert_eq!(Modifier::from(tstyle::Underline), Modifier::UNDERLINED);
|
||||
assert_eq!(Modifier::from(tstyle::Faint), Modifier::DIM);
|
||||
assert_eq!(Modifier::from(tstyle::CrossedOut), Modifier::CROSSED_OUT);
|
||||
assert_eq!(Modifier::from(tstyle::Blink), Modifier::SLOW_BLINK);
|
||||
assert_eq!(Modifier::from(tstyle::Reset), Modifier::empty());
|
||||
assert_eq!(Modifier::from_termion(tstyle::Invert), Modifier::REVERSED);
|
||||
assert_eq!(Modifier::from_termion(tstyle::Bold), Modifier::BOLD);
|
||||
assert_eq!(Modifier::from_termion(tstyle::Italic), Modifier::ITALIC);
|
||||
assert_eq!(
|
||||
Modifier::from_termion(tstyle::Underline),
|
||||
Modifier::UNDERLINED
|
||||
);
|
||||
assert_eq!(Modifier::from_termion(tstyle::Faint), Modifier::DIM);
|
||||
assert_eq!(
|
||||
Modifier::from_termion(tstyle::CrossedOut),
|
||||
Modifier::CROSSED_OUT
|
||||
);
|
||||
assert_eq!(Modifier::from_termion(tstyle::Blink), Modifier::SLOW_BLINK);
|
||||
assert_eq!(Modifier::from_termion(tstyle::Reset), Modifier::empty());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,8 +120,8 @@ impl Backend for TermwizBackend {
|
||||
x: Position::Absolute(x as usize),
|
||||
y: Position::Absolute(y as usize),
|
||||
},
|
||||
Change::Attribute(AttributeChange::Foreground(cell.fg.into())),
|
||||
Change::Attribute(AttributeChange::Background(cell.bg.into())),
|
||||
Change::Attribute(AttributeChange::Foreground(cell.fg.into_termwiz())),
|
||||
Change::Attribute(AttributeChange::Background(cell.bg.into_termwiz())),
|
||||
]);
|
||||
|
||||
self.buffered_terminal
|
||||
@@ -298,12 +298,49 @@ impl Backend for TermwizBackend {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<CellAttributes> for Style {
|
||||
fn from(value: CellAttributes) -> Self {
|
||||
/// A trait for converting types from Termwiz to Ratatui.
|
||||
///
|
||||
/// This trait replaces the `From` trait for converting types from Termwiz to Ratatui. It is
|
||||
/// necessary because the `From` trait is not implemented for types defined in external crates.
|
||||
pub trait FromTermwiz<T> {
|
||||
/// Converts the given Termwiz type to the Ratatui type.
|
||||
fn from_termwiz(termwiz: T) -> Self;
|
||||
}
|
||||
|
||||
/// A trait for converting types from Ratatui to Termwiz.
|
||||
///
|
||||
/// This trait replaces the `Into` trait for converting types from Ratatui to Termwiz. It is
|
||||
/// necessary because the `Into` trait is not implemented for types defined in external crates.
|
||||
pub trait IntoTermwiz<T> {
|
||||
/// Converts the given Ratatui type to the Termwiz type.
|
||||
fn into_termwiz(self) -> T;
|
||||
}
|
||||
|
||||
/// A replacement for the `Into` trait for converting types from Ratatui to Termwiz.
|
||||
///
|
||||
/// This trait is necessary because the `Into` trait is not implemented for types defined in
|
||||
/// external crates.
|
||||
///
|
||||
/// A blanket implementation is provided for all types that implement `FromTermwiz`.
|
||||
///
|
||||
/// This trait is private to the module as it would otherwise conflict with the other backend
|
||||
/// modules. It is mainly used to avoid rewriting all the `.into()` calls in this module.
|
||||
trait IntoRatatui<R> {
|
||||
fn into_ratatui(self) -> R;
|
||||
}
|
||||
|
||||
impl<C, R: FromTermwiz<C>> IntoRatatui<R> for C {
|
||||
fn into_ratatui(self) -> R {
|
||||
R::from_termwiz(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl FromTermwiz<CellAttributes> for Style {
|
||||
fn from_termwiz(value: CellAttributes) -> Self {
|
||||
let mut style = Self::new()
|
||||
.add_modifier(value.intensity().into())
|
||||
.add_modifier(value.underline().into())
|
||||
.add_modifier(value.blink().into());
|
||||
.add_modifier(value.intensity().into_ratatui())
|
||||
.add_modifier(value.underline().into_ratatui())
|
||||
.add_modifier(value.blink().into_ratatui());
|
||||
|
||||
if value.italic() {
|
||||
style.add_modifier |= Modifier::ITALIC;
|
||||
@@ -318,19 +355,19 @@ impl From<CellAttributes> for Style {
|
||||
style.add_modifier |= Modifier::HIDDEN;
|
||||
}
|
||||
|
||||
style.fg = Some(value.foreground().into());
|
||||
style.bg = Some(value.background().into());
|
||||
style.fg = Some(value.foreground().into_ratatui());
|
||||
style.bg = Some(value.background().into_ratatui());
|
||||
#[cfg(feature = "underline-color")]
|
||||
{
|
||||
style.underline_color = Some(value.underline_color().into());
|
||||
style.underline_color = Some(value.underline_color().into_ratatui());
|
||||
}
|
||||
|
||||
style
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Intensity> for Modifier {
|
||||
fn from(value: Intensity) -> Self {
|
||||
impl FromTermwiz<Intensity> for Modifier {
|
||||
fn from_termwiz(value: Intensity) -> Self {
|
||||
match value {
|
||||
Intensity::Normal => Self::empty(),
|
||||
Intensity::Bold => Self::BOLD,
|
||||
@@ -339,8 +376,8 @@ impl From<Intensity> for Modifier {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Underline> for Modifier {
|
||||
fn from(value: Underline) -> Self {
|
||||
impl FromTermwiz<Underline> for Modifier {
|
||||
fn from_termwiz(value: Underline) -> Self {
|
||||
match value {
|
||||
Underline::None => Self::empty(),
|
||||
_ => Self::UNDERLINED,
|
||||
@@ -348,8 +385,8 @@ impl From<Underline> for Modifier {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Blink> for Modifier {
|
||||
fn from(value: Blink) -> Self {
|
||||
impl FromTermwiz<Blink> for Modifier {
|
||||
fn from_termwiz(value: Blink) -> Self {
|
||||
match value {
|
||||
Blink::None => Self::empty(),
|
||||
Blink::Slow => Self::SLOW_BLINK,
|
||||
@@ -358,34 +395,36 @@ impl From<Blink> for Modifier {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Color> for ColorAttribute {
|
||||
fn from(color: Color) -> Self {
|
||||
match color {
|
||||
Color::Reset => Self::Default,
|
||||
Color::Black => AnsiColor::Black.into(),
|
||||
Color::DarkGray => AnsiColor::Grey.into(),
|
||||
Color::Gray => AnsiColor::Silver.into(),
|
||||
Color::Red => AnsiColor::Maroon.into(),
|
||||
Color::LightRed => AnsiColor::Red.into(),
|
||||
Color::Green => AnsiColor::Green.into(),
|
||||
Color::LightGreen => AnsiColor::Lime.into(),
|
||||
Color::Yellow => AnsiColor::Olive.into(),
|
||||
Color::LightYellow => AnsiColor::Yellow.into(),
|
||||
Color::Magenta => AnsiColor::Purple.into(),
|
||||
Color::LightMagenta => AnsiColor::Fuchsia.into(),
|
||||
Color::Cyan => AnsiColor::Teal.into(),
|
||||
Color::LightCyan => AnsiColor::Aqua.into(),
|
||||
Color::White => AnsiColor::White.into(),
|
||||
Color::Blue => AnsiColor::Navy.into(),
|
||||
Color::LightBlue => AnsiColor::Blue.into(),
|
||||
Color::Indexed(i) => Self::PaletteIndex(i),
|
||||
Color::Rgb(r, g, b) => Self::TrueColorWithDefaultFallback(SrgbaTuple::from((r, g, b))),
|
||||
impl IntoTermwiz<ColorAttribute> for Color {
|
||||
fn into_termwiz(self) -> ColorAttribute {
|
||||
match self {
|
||||
Self::Reset => ColorAttribute::Default,
|
||||
Self::Black => AnsiColor::Black.into(),
|
||||
Self::DarkGray => AnsiColor::Grey.into(),
|
||||
Self::Gray => AnsiColor::Silver.into(),
|
||||
Self::Red => AnsiColor::Maroon.into(),
|
||||
Self::LightRed => AnsiColor::Red.into(),
|
||||
Self::Green => AnsiColor::Green.into(),
|
||||
Self::LightGreen => AnsiColor::Lime.into(),
|
||||
Self::Yellow => AnsiColor::Olive.into(),
|
||||
Self::LightYellow => AnsiColor::Yellow.into(),
|
||||
Self::Magenta => AnsiColor::Purple.into(),
|
||||
Self::LightMagenta => AnsiColor::Fuchsia.into(),
|
||||
Self::Cyan => AnsiColor::Teal.into(),
|
||||
Self::LightCyan => AnsiColor::Aqua.into(),
|
||||
Self::White => AnsiColor::White.into(),
|
||||
Self::Blue => AnsiColor::Navy.into(),
|
||||
Self::LightBlue => AnsiColor::Blue.into(),
|
||||
Self::Indexed(i) => ColorAttribute::PaletteIndex(i),
|
||||
Self::Rgb(r, g, b) => {
|
||||
ColorAttribute::TrueColorWithDefaultFallback(SrgbaTuple::from((r, g, b)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<AnsiColor> for Color {
|
||||
fn from(value: AnsiColor) -> Self {
|
||||
impl FromTermwiz<AnsiColor> for Color {
|
||||
fn from_termwiz(value: AnsiColor) -> Self {
|
||||
match value {
|
||||
AnsiColor::Black => Self::Black,
|
||||
AnsiColor::Grey => Self::DarkGray,
|
||||
@@ -407,44 +446,44 @@ impl From<AnsiColor> for Color {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ColorAttribute> for Color {
|
||||
fn from(value: ColorAttribute) -> Self {
|
||||
impl FromTermwiz<ColorAttribute> for Color {
|
||||
fn from_termwiz(value: ColorAttribute) -> Self {
|
||||
match value {
|
||||
ColorAttribute::TrueColorWithDefaultFallback(srgba)
|
||||
| ColorAttribute::TrueColorWithPaletteFallback(srgba, _) => srgba.into(),
|
||||
| ColorAttribute::TrueColorWithPaletteFallback(srgba, _) => srgba.into_ratatui(),
|
||||
ColorAttribute::PaletteIndex(i) => Self::Indexed(i),
|
||||
ColorAttribute::Default => Self::Reset,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ColorSpec> for Color {
|
||||
fn from(value: ColorSpec) -> Self {
|
||||
impl FromTermwiz<ColorSpec> for Color {
|
||||
fn from_termwiz(value: ColorSpec) -> Self {
|
||||
match value {
|
||||
ColorSpec::Default => Self::Reset,
|
||||
ColorSpec::PaletteIndex(i) => Self::Indexed(i),
|
||||
ColorSpec::TrueColor(srgba) => srgba.into(),
|
||||
ColorSpec::TrueColor(srgba) => srgba.into_ratatui(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<SrgbaTuple> for Color {
|
||||
fn from(value: SrgbaTuple) -> Self {
|
||||
impl FromTermwiz<SrgbaTuple> for Color {
|
||||
fn from_termwiz(value: SrgbaTuple) -> Self {
|
||||
let (r, g, b, _) = value.to_srgb_u8();
|
||||
Self::Rgb(r, g, b)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<RgbColor> for Color {
|
||||
fn from(value: RgbColor) -> Self {
|
||||
impl FromTermwiz<RgbColor> for Color {
|
||||
fn from_termwiz(value: RgbColor) -> Self {
|
||||
let (r, g, b) = value.to_tuple_rgb8();
|
||||
Self::Rgb(r, g, b)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<LinearRgba> for Color {
|
||||
fn from(value: LinearRgba) -> Self {
|
||||
value.to_srgb().into()
|
||||
impl FromTermwiz<LinearRgba> for Color {
|
||||
fn from_termwiz(value: LinearRgba) -> Self {
|
||||
value.to_srgb().into_ratatui()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -465,107 +504,191 @@ mod tests {
|
||||
#[test]
|
||||
fn from_linear_rgba() {
|
||||
// full black + opaque
|
||||
assert_eq!(C::from(LinearRgba(0., 0., 0., 1.)), Color::Rgb(0, 0, 0));
|
||||
assert_eq!(
|
||||
C::from_termwiz(LinearRgba(0., 0., 0., 1.)),
|
||||
Color::Rgb(0, 0, 0)
|
||||
);
|
||||
// full black + transparent
|
||||
assert_eq!(C::from(LinearRgba(0., 0., 0., 0.)), Color::Rgb(0, 0, 0));
|
||||
assert_eq!(
|
||||
C::from_termwiz(LinearRgba(0., 0., 0., 0.)),
|
||||
Color::Rgb(0, 0, 0)
|
||||
);
|
||||
|
||||
// full white + opaque
|
||||
assert_eq!(C::from(LinearRgba(1., 1., 1., 1.)), C::Rgb(254, 254, 254));
|
||||
assert_eq!(
|
||||
C::from_termwiz(LinearRgba(1., 1., 1., 1.)),
|
||||
C::Rgb(254, 254, 254)
|
||||
);
|
||||
// full white + transparent
|
||||
assert_eq!(C::from(LinearRgba(1., 1., 1., 0.)), C::Rgb(254, 254, 254));
|
||||
assert_eq!(
|
||||
C::from_termwiz(LinearRgba(1., 1., 1., 0.)),
|
||||
C::Rgb(254, 254, 254)
|
||||
);
|
||||
|
||||
// full red
|
||||
assert_eq!(C::from(LinearRgba(1., 0., 0., 1.)), C::Rgb(254, 0, 0));
|
||||
assert_eq!(
|
||||
C::from_termwiz(LinearRgba(1., 0., 0., 1.)),
|
||||
C::Rgb(254, 0, 0)
|
||||
);
|
||||
// full green
|
||||
assert_eq!(C::from(LinearRgba(0., 1., 0., 1.)), C::Rgb(0, 254, 0));
|
||||
assert_eq!(
|
||||
C::from_termwiz(LinearRgba(0., 1., 0., 1.)),
|
||||
C::Rgb(0, 254, 0)
|
||||
);
|
||||
// full blue
|
||||
assert_eq!(C::from(LinearRgba(0., 0., 1., 1.)), C::Rgb(0, 0, 254));
|
||||
assert_eq!(
|
||||
C::from_termwiz(LinearRgba(0., 0., 1., 1.)),
|
||||
C::Rgb(0, 0, 254)
|
||||
);
|
||||
|
||||
// See https://stackoverflow.com/questions/12524623/what-are-the-practical-differences-when-working-with-colors-in-a-linear-vs-a-no
|
||||
// for an explanation
|
||||
|
||||
// half red
|
||||
assert_eq!(C::from(LinearRgba(0.214, 0., 0., 1.)), C::Rgb(127, 0, 0));
|
||||
assert_eq!(
|
||||
C::from_termwiz(LinearRgba(0.214, 0., 0., 1.)),
|
||||
C::Rgb(127, 0, 0)
|
||||
);
|
||||
// half green
|
||||
assert_eq!(C::from(LinearRgba(0., 0.214, 0., 1.)), C::Rgb(0, 127, 0));
|
||||
assert_eq!(
|
||||
C::from_termwiz(LinearRgba(0., 0.214, 0., 1.)),
|
||||
C::Rgb(0, 127, 0)
|
||||
);
|
||||
// half blue
|
||||
assert_eq!(C::from(LinearRgba(0., 0., 0.214, 1.)), C::Rgb(0, 0, 127));
|
||||
assert_eq!(
|
||||
C::from_termwiz(LinearRgba(0., 0., 0.214, 1.)),
|
||||
C::Rgb(0, 0, 127)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_srgba() {
|
||||
// full black + opaque
|
||||
assert_eq!(C::from(SrgbaTuple(0., 0., 0., 1.)), Color::Rgb(0, 0, 0));
|
||||
assert_eq!(
|
||||
C::from_termwiz(SrgbaTuple(0., 0., 0., 1.)),
|
||||
Color::Rgb(0, 0, 0)
|
||||
);
|
||||
// full black + transparent
|
||||
assert_eq!(C::from(SrgbaTuple(0., 0., 0., 0.)), Color::Rgb(0, 0, 0));
|
||||
assert_eq!(
|
||||
C::from_termwiz(SrgbaTuple(0., 0., 0., 0.)),
|
||||
Color::Rgb(0, 0, 0)
|
||||
);
|
||||
|
||||
// full white + opaque
|
||||
assert_eq!(C::from(SrgbaTuple(1., 1., 1., 1.)), C::Rgb(255, 255, 255));
|
||||
assert_eq!(
|
||||
C::from_termwiz(SrgbaTuple(1., 1., 1., 1.)),
|
||||
C::Rgb(255, 255, 255)
|
||||
);
|
||||
// full white + transparent
|
||||
assert_eq!(C::from(SrgbaTuple(1., 1., 1., 0.)), C::Rgb(255, 255, 255));
|
||||
assert_eq!(
|
||||
C::from_termwiz(SrgbaTuple(1., 1., 1., 0.)),
|
||||
C::Rgb(255, 255, 255)
|
||||
);
|
||||
|
||||
// full red
|
||||
assert_eq!(C::from(SrgbaTuple(1., 0., 0., 1.)), C::Rgb(255, 0, 0));
|
||||
assert_eq!(
|
||||
C::from_termwiz(SrgbaTuple(1., 0., 0., 1.)),
|
||||
C::Rgb(255, 0, 0)
|
||||
);
|
||||
// full green
|
||||
assert_eq!(C::from(SrgbaTuple(0., 1., 0., 1.)), C::Rgb(0, 255, 0));
|
||||
assert_eq!(
|
||||
C::from_termwiz(SrgbaTuple(0., 1., 0., 1.)),
|
||||
C::Rgb(0, 255, 0)
|
||||
);
|
||||
// full blue
|
||||
assert_eq!(C::from(SrgbaTuple(0., 0., 1., 1.)), C::Rgb(0, 0, 255));
|
||||
assert_eq!(
|
||||
C::from_termwiz(SrgbaTuple(0., 0., 1., 1.)),
|
||||
C::Rgb(0, 0, 255)
|
||||
);
|
||||
|
||||
// half red
|
||||
assert_eq!(C::from(SrgbaTuple(0.5, 0., 0., 1.)), C::Rgb(127, 0, 0));
|
||||
assert_eq!(
|
||||
C::from_termwiz(SrgbaTuple(0.5, 0., 0., 1.)),
|
||||
C::Rgb(127, 0, 0)
|
||||
);
|
||||
// half green
|
||||
assert_eq!(C::from(SrgbaTuple(0., 0.5, 0., 1.)), C::Rgb(0, 127, 0));
|
||||
assert_eq!(
|
||||
C::from_termwiz(SrgbaTuple(0., 0.5, 0., 1.)),
|
||||
C::Rgb(0, 127, 0)
|
||||
);
|
||||
// half blue
|
||||
assert_eq!(C::from(SrgbaTuple(0., 0., 0.5, 1.)), C::Rgb(0, 0, 127));
|
||||
assert_eq!(
|
||||
C::from_termwiz(SrgbaTuple(0., 0., 0.5, 1.)),
|
||||
C::Rgb(0, 0, 127)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_rgbcolor() {
|
||||
// full black
|
||||
assert_eq!(C::from(RgbColor::new_8bpc(0, 0, 0)), Color::Rgb(0, 0, 0));
|
||||
assert_eq!(
|
||||
C::from_termwiz(RgbColor::new_8bpc(0, 0, 0)),
|
||||
Color::Rgb(0, 0, 0)
|
||||
);
|
||||
// full white
|
||||
assert_eq!(
|
||||
C::from(RgbColor::new_8bpc(255, 255, 255)),
|
||||
C::from_termwiz(RgbColor::new_8bpc(255, 255, 255)),
|
||||
C::Rgb(255, 255, 255)
|
||||
);
|
||||
|
||||
// full red
|
||||
assert_eq!(C::from(RgbColor::new_8bpc(255, 0, 0)), C::Rgb(255, 0, 0));
|
||||
assert_eq!(
|
||||
C::from_termwiz(RgbColor::new_8bpc(255, 0, 0)),
|
||||
C::Rgb(255, 0, 0)
|
||||
);
|
||||
// full green
|
||||
assert_eq!(C::from(RgbColor::new_8bpc(0, 255, 0)), C::Rgb(0, 255, 0));
|
||||
assert_eq!(
|
||||
C::from_termwiz(RgbColor::new_8bpc(0, 255, 0)),
|
||||
C::Rgb(0, 255, 0)
|
||||
);
|
||||
// full blue
|
||||
assert_eq!(C::from(RgbColor::new_8bpc(0, 0, 255)), C::Rgb(0, 0, 255));
|
||||
assert_eq!(
|
||||
C::from_termwiz(RgbColor::new_8bpc(0, 0, 255)),
|
||||
C::Rgb(0, 0, 255)
|
||||
);
|
||||
|
||||
// half red
|
||||
assert_eq!(C::from(RgbColor::new_8bpc(127, 0, 0)), C::Rgb(127, 0, 0));
|
||||
assert_eq!(
|
||||
C::from_termwiz(RgbColor::new_8bpc(127, 0, 0)),
|
||||
C::Rgb(127, 0, 0)
|
||||
);
|
||||
// half green
|
||||
assert_eq!(C::from(RgbColor::new_8bpc(0, 127, 0)), C::Rgb(0, 127, 0));
|
||||
assert_eq!(
|
||||
C::from_termwiz(RgbColor::new_8bpc(0, 127, 0)),
|
||||
C::Rgb(0, 127, 0)
|
||||
);
|
||||
// half blue
|
||||
assert_eq!(C::from(RgbColor::new_8bpc(0, 0, 127)), C::Rgb(0, 0, 127));
|
||||
assert_eq!(
|
||||
C::from_termwiz(RgbColor::new_8bpc(0, 0, 127)),
|
||||
C::Rgb(0, 0, 127)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_colorspec() {
|
||||
assert_eq!(C::from(ColorSpec::Default), C::Reset);
|
||||
assert_eq!(C::from(ColorSpec::PaletteIndex(33)), C::Indexed(33));
|
||||
assert_eq!(C::from_termwiz(ColorSpec::Default), C::Reset);
|
||||
assert_eq!(C::from_termwiz(ColorSpec::PaletteIndex(33)), C::Indexed(33));
|
||||
assert_eq!(
|
||||
C::from(ColorSpec::TrueColor(SrgbaTuple(0., 0., 0., 1.))),
|
||||
C::from_termwiz(ColorSpec::TrueColor(SrgbaTuple(0., 0., 0., 1.))),
|
||||
C::Rgb(0, 0, 0)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_colorattribute() {
|
||||
assert_eq!(C::from(ColorAttribute::Default), C::Reset);
|
||||
assert_eq!(C::from(ColorAttribute::PaletteIndex(32)), C::Indexed(32));
|
||||
assert_eq!(C::from_termwiz(ColorAttribute::Default), C::Reset);
|
||||
assert_eq!(
|
||||
C::from(ColorAttribute::TrueColorWithDefaultFallback(SrgbaTuple(
|
||||
C::from_termwiz(ColorAttribute::PaletteIndex(32)),
|
||||
C::Indexed(32)
|
||||
);
|
||||
assert_eq!(
|
||||
C::from_termwiz(ColorAttribute::TrueColorWithDefaultFallback(SrgbaTuple(
|
||||
0., 0., 0., 1.
|
||||
))),
|
||||
C::Rgb(0, 0, 0)
|
||||
);
|
||||
assert_eq!(
|
||||
C::from(ColorAttribute::TrueColorWithPaletteFallback(
|
||||
C::from_termwiz(ColorAttribute::TrueColorWithPaletteFallback(
|
||||
SrgbaTuple(0., 0., 0., 1.),
|
||||
31
|
||||
)),
|
||||
@@ -575,22 +698,22 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn from_ansicolor() {
|
||||
assert_eq!(C::from(AnsiColor::Black), Color::Black);
|
||||
assert_eq!(C::from(AnsiColor::Grey), Color::DarkGray);
|
||||
assert_eq!(C::from(AnsiColor::Silver), Color::Gray);
|
||||
assert_eq!(C::from(AnsiColor::Maroon), Color::Red);
|
||||
assert_eq!(C::from(AnsiColor::Red), Color::LightRed);
|
||||
assert_eq!(C::from(AnsiColor::Green), Color::Green);
|
||||
assert_eq!(C::from(AnsiColor::Lime), Color::LightGreen);
|
||||
assert_eq!(C::from(AnsiColor::Olive), Color::Yellow);
|
||||
assert_eq!(C::from(AnsiColor::Yellow), Color::LightYellow);
|
||||
assert_eq!(C::from(AnsiColor::Purple), Color::Magenta);
|
||||
assert_eq!(C::from(AnsiColor::Fuchsia), Color::LightMagenta);
|
||||
assert_eq!(C::from(AnsiColor::Teal), Color::Cyan);
|
||||
assert_eq!(C::from(AnsiColor::Aqua), Color::LightCyan);
|
||||
assert_eq!(C::from(AnsiColor::White), Color::White);
|
||||
assert_eq!(C::from(AnsiColor::Navy), Color::Blue);
|
||||
assert_eq!(C::from(AnsiColor::Blue), Color::LightBlue);
|
||||
assert_eq!(C::from_termwiz(AnsiColor::Black), Color::Black);
|
||||
assert_eq!(C::from_termwiz(AnsiColor::Grey), Color::DarkGray);
|
||||
assert_eq!(C::from_termwiz(AnsiColor::Silver), Color::Gray);
|
||||
assert_eq!(C::from_termwiz(AnsiColor::Maroon), Color::Red);
|
||||
assert_eq!(C::from_termwiz(AnsiColor::Red), Color::LightRed);
|
||||
assert_eq!(C::from_termwiz(AnsiColor::Green), Color::Green);
|
||||
assert_eq!(C::from_termwiz(AnsiColor::Lime), Color::LightGreen);
|
||||
assert_eq!(C::from_termwiz(AnsiColor::Olive), Color::Yellow);
|
||||
assert_eq!(C::from_termwiz(AnsiColor::Yellow), Color::LightYellow);
|
||||
assert_eq!(C::from_termwiz(AnsiColor::Purple), Color::Magenta);
|
||||
assert_eq!(C::from_termwiz(AnsiColor::Fuchsia), Color::LightMagenta);
|
||||
assert_eq!(C::from_termwiz(AnsiColor::Teal), Color::Cyan);
|
||||
assert_eq!(C::from_termwiz(AnsiColor::Aqua), Color::LightCyan);
|
||||
assert_eq!(C::from_termwiz(AnsiColor::White), Color::White);
|
||||
assert_eq!(C::from_termwiz(AnsiColor::Navy), Color::Blue);
|
||||
assert_eq!(C::from_termwiz(AnsiColor::Blue), Color::LightBlue);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -599,26 +722,41 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn from_intensity() {
|
||||
assert_eq!(Modifier::from(Intensity::Normal), Modifier::empty());
|
||||
assert_eq!(Modifier::from(Intensity::Bold), Modifier::BOLD);
|
||||
assert_eq!(Modifier::from(Intensity::Half), Modifier::DIM);
|
||||
assert_eq!(Modifier::from_termwiz(Intensity::Normal), Modifier::empty());
|
||||
assert_eq!(Modifier::from_termwiz(Intensity::Bold), Modifier::BOLD);
|
||||
assert_eq!(Modifier::from_termwiz(Intensity::Half), Modifier::DIM);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_underline() {
|
||||
assert_eq!(Modifier::from(Underline::None), Modifier::empty());
|
||||
assert_eq!(Modifier::from(Underline::Single), Modifier::UNDERLINED);
|
||||
assert_eq!(Modifier::from(Underline::Double), Modifier::UNDERLINED);
|
||||
assert_eq!(Modifier::from(Underline::Curly), Modifier::UNDERLINED);
|
||||
assert_eq!(Modifier::from(Underline::Dashed), Modifier::UNDERLINED);
|
||||
assert_eq!(Modifier::from(Underline::Dotted), Modifier::UNDERLINED);
|
||||
assert_eq!(Modifier::from_termwiz(Underline::None), Modifier::empty());
|
||||
assert_eq!(
|
||||
Modifier::from_termwiz(Underline::Single),
|
||||
Modifier::UNDERLINED
|
||||
);
|
||||
assert_eq!(
|
||||
Modifier::from_termwiz(Underline::Double),
|
||||
Modifier::UNDERLINED
|
||||
);
|
||||
assert_eq!(
|
||||
Modifier::from_termwiz(Underline::Curly),
|
||||
Modifier::UNDERLINED
|
||||
);
|
||||
assert_eq!(
|
||||
Modifier::from_termwiz(Underline::Dashed),
|
||||
Modifier::UNDERLINED
|
||||
);
|
||||
assert_eq!(
|
||||
Modifier::from_termwiz(Underline::Dotted),
|
||||
Modifier::UNDERLINED
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn from_blink() {
|
||||
assert_eq!(Modifier::from(Blink::None), Modifier::empty());
|
||||
assert_eq!(Modifier::from(Blink::Slow), Modifier::SLOW_BLINK);
|
||||
assert_eq!(Modifier::from(Blink::Rapid), Modifier::RAPID_BLINK);
|
||||
assert_eq!(Modifier::from_termwiz(Blink::None), Modifier::empty());
|
||||
assert_eq!(Modifier::from_termwiz(Blink::Slow), Modifier::SLOW_BLINK);
|
||||
assert_eq!(Modifier::from_termwiz(Blink::Rapid), Modifier::RAPID_BLINK);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -635,11 +773,11 @@ mod tests {
|
||||
const STYLE: Style = Style::new().fg(Color::Reset).bg(Color::Reset);
|
||||
|
||||
// default
|
||||
assert_eq!(Style::from(CellAttributes::default()), STYLE);
|
||||
assert_eq!(Style::from_termwiz(CellAttributes::default()), STYLE);
|
||||
|
||||
// foreground color
|
||||
assert_eq!(
|
||||
Style::from(
|
||||
Style::from_termwiz(
|
||||
CellAttributes::default()
|
||||
.set_foreground(ColorAttribute::PaletteIndex(31))
|
||||
.to_owned()
|
||||
@@ -648,7 +786,7 @@ mod tests {
|
||||
);
|
||||
// background color
|
||||
assert_eq!(
|
||||
Style::from(
|
||||
Style::from_termwiz(
|
||||
CellAttributes::default()
|
||||
.set_background(ColorAttribute::PaletteIndex(31))
|
||||
.to_owned()
|
||||
@@ -657,7 +795,7 @@ mod tests {
|
||||
);
|
||||
// underlined
|
||||
assert_eq!(
|
||||
Style::from(
|
||||
Style::from_termwiz(
|
||||
CellAttributes::default()
|
||||
.set_underline(Underline::Single)
|
||||
.to_owned()
|
||||
@@ -666,12 +804,12 @@ mod tests {
|
||||
);
|
||||
// blink
|
||||
assert_eq!(
|
||||
Style::from(CellAttributes::default().set_blink(Blink::Slow).to_owned()),
|
||||
Style::from_termwiz(CellAttributes::default().set_blink(Blink::Slow).to_owned()),
|
||||
STYLE.slow_blink()
|
||||
);
|
||||
// intensity
|
||||
assert_eq!(
|
||||
Style::from(
|
||||
Style::from_termwiz(
|
||||
CellAttributes::default()
|
||||
.set_intensity(Intensity::Bold)
|
||||
.to_owned()
|
||||
@@ -680,29 +818,29 @@ mod tests {
|
||||
);
|
||||
// italic
|
||||
assert_eq!(
|
||||
Style::from(CellAttributes::default().set_italic(true).to_owned()),
|
||||
Style::from_termwiz(CellAttributes::default().set_italic(true).to_owned()),
|
||||
STYLE.italic()
|
||||
);
|
||||
// reversed
|
||||
assert_eq!(
|
||||
Style::from(CellAttributes::default().set_reverse(true).to_owned()),
|
||||
Style::from_termwiz(CellAttributes::default().set_reverse(true).to_owned()),
|
||||
STYLE.reversed()
|
||||
);
|
||||
// strikethrough
|
||||
assert_eq!(
|
||||
Style::from(CellAttributes::default().set_strikethrough(true).to_owned()),
|
||||
Style::from_termwiz(CellAttributes::default().set_strikethrough(true).to_owned()),
|
||||
STYLE.crossed_out()
|
||||
);
|
||||
// hidden
|
||||
assert_eq!(
|
||||
Style::from(CellAttributes::default().set_invisible(true).to_owned()),
|
||||
Style::from_termwiz(CellAttributes::default().set_invisible(true).to_owned()),
|
||||
STYLE.hidden()
|
||||
);
|
||||
|
||||
// underline color
|
||||
#[cfg(feature = "underline-color")]
|
||||
assert_eq!(
|
||||
Style::from(
|
||||
Style::from_termwiz(
|
||||
CellAttributes::default()
|
||||
.set_underline_color(AnsiColor::Red)
|
||||
.to_owned()
|
||||
|
||||
@@ -28,11 +28,11 @@
|
||||
//! ```
|
||||
|
||||
#[cfg(feature = "crossterm")]
|
||||
pub use crate::backend::CrosstermBackend;
|
||||
pub use crate::backend::{CrosstermBackend, FromCrossterm, IntoCrossterm};
|
||||
#[cfg(all(not(windows), feature = "termion"))]
|
||||
pub use crate::backend::TermionBackend;
|
||||
pub use crate::backend::{FromTermion, IntoTermion, TermionBackend};
|
||||
#[cfg(feature = "termwiz")]
|
||||
pub use crate::backend::TermwizBackend;
|
||||
pub use crate::backend::{FromTermwiz, IntoTermwiz, TermwizBackend};
|
||||
pub use crate::{
|
||||
backend::{self, Backend},
|
||||
buffer::{self, Buffer},
|
||||
|
||||
Reference in New Issue
Block a user