Skip to content

Commit

Permalink
feat(stylize): allow all widgets to be styled (ratatui#289)
Browse files Browse the repository at this point in the history
* feat(stylize): allow all widgets to be styled

- Add styled impl to:
  - Barchart
  - Chart (including Axis and Dataset),
  - Guage and LineGuage
  - List and ListItem
  - Sparkline
  - Table, Row, and Cell
  - Tabs
  - Style
- Allow modifiers to be removed (e.g. .not_italic())
- Allow .bg() to recieve Into<Color>
- Made shorthand methods consistent with modifier names (e.g. dim() not
  dimmed() and underlined() not underline())
- Simplify integration tests
- Add doc comments
- Simplified stylize macros with https://crates.io/crates/paste

* build: run clippy before tests

Runny clippy first means that we fail fast when there is an issue that
can easily be fixed rather than having to wait 30-40s for the failure
  • Loading branch information
joshka authored and a-kenji committed Jul 16, 2023
1 parent 795ba44 commit 5ac0f31
Show file tree
Hide file tree
Showing 17 changed files with 904 additions and 322 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ bitflags = "2.3"
cassowary = "0.3"
crossterm = { version = "0.26", optional = true }
indoc = "2.0"
paste = "1.0"
serde = { version = "1", optional = true, features = ["derive"] }
termion = { version = "2.0", optional = true }
termwiz = { version = "0.20.0", optional = true }
Expand Down
4 changes: 2 additions & 2 deletions Makefile.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,18 @@ run_task = [
private = true
dependencies = [
"style-check",
"clippy-unix",
"check-unix",
"test-unix",
"clippy-unix",
]

[tasks.ci-windows]
private = true
dependencies = [
"style-check",
"clippy-windows",
"check-windows",
"test-windows",
"clippy-windows",
]

[tasks.style-check]
Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ pub mod prelude {
backend::Backend,
buffer::Buffer,
layout::{Alignment, Constraint, Corner, Direction, Layout, Margin, Rect},
style::{Color, Modifier, Style, Stylize},
style::{Color, Modifier, Style, Styled, Stylize},
symbols::{self, Marker},
terminal::{Frame, Terminal, TerminalOptions, Viewport},
text::{Line, Masked, Span, Text},
Expand Down
170 changes: 163 additions & 7 deletions src/style.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,28 +15,26 @@
//!
//! # Using style shorthands
//!
//! This is best for consise styling.
//! This is best for concise styling.
//! ## Example
//! ```
//! use ratatui::{
//! style::{Color, Modifier, Style, Styled, Stylize},
//! text::Span,
//! };
//! use ratatui::prelude::*;
//!
//! assert_eq!(
//! "hello".red().on_blue().bold(),
//! Span::styled("hello", Style::default().fg(Color::Red).bg(Color::Blue).add_modifier(Modifier::BOLD))
//! )
//! ```
mod stylized;

use std::{
fmt::{self, Debug},
str::FromStr,
};

use bitflags::bitflags;
pub use stylized::{Styled, Stylize};

mod stylize;
pub use stylize::{Styled, Stylize};

/// ANSI Color
///
Expand Down Expand Up @@ -258,6 +256,17 @@ impl Default for Style {
}
}

impl Styled for Style {
type Item = Style;

fn style(&self) -> Style {
*self
}

fn set_style(self, style: Style) -> Self::Item {
self.patch(style)
}
}
impl Style {
pub const fn new() -> Style {
Style {
Expand Down Expand Up @@ -671,4 +680,151 @@ mod tests {
.remove_modifier(Modifier::ITALIC)
)
}

#[test]
fn style_can_be_stylized() {
// foreground colors
assert_eq!(Style::new().black(), Style::new().fg(Color::Black));
assert_eq!(Style::new().red(), Style::new().fg(Color::Red));
assert_eq!(Style::new().green(), Style::new().fg(Color::Green));
assert_eq!(Style::new().yellow(), Style::new().fg(Color::Yellow));
assert_eq!(Style::new().blue(), Style::new().fg(Color::Blue));
assert_eq!(Style::new().magenta(), Style::new().fg(Color::Magenta));
assert_eq!(Style::new().cyan(), Style::new().fg(Color::Cyan));
assert_eq!(Style::new().white(), Style::new().fg(Color::White));
assert_eq!(Style::new().gray(), Style::new().fg(Color::Gray));
assert_eq!(Style::new().dark_gray(), Style::new().fg(Color::DarkGray));
assert_eq!(Style::new().light_red(), Style::new().fg(Color::LightRed));
assert_eq!(
Style::new().light_green(),
Style::new().fg(Color::LightGreen)
);
assert_eq!(
Style::new().light_yellow(),
Style::new().fg(Color::LightYellow)
);
assert_eq!(Style::new().light_blue(), Style::new().fg(Color::LightBlue));
assert_eq!(
Style::new().light_magenta(),
Style::new().fg(Color::LightMagenta)
);
assert_eq!(Style::new().light_cyan(), Style::new().fg(Color::LightCyan));
assert_eq!(Style::new().white(), Style::new().fg(Color::White));

// Background colors
assert_eq!(Style::new().on_black(), Style::new().bg(Color::Black));
assert_eq!(Style::new().on_red(), Style::new().bg(Color::Red));
assert_eq!(Style::new().on_green(), Style::new().bg(Color::Green));
assert_eq!(Style::new().on_yellow(), Style::new().bg(Color::Yellow));
assert_eq!(Style::new().on_blue(), Style::new().bg(Color::Blue));
assert_eq!(Style::new().on_magenta(), Style::new().bg(Color::Magenta));
assert_eq!(Style::new().on_cyan(), Style::new().bg(Color::Cyan));
assert_eq!(Style::new().on_white(), Style::new().bg(Color::White));
assert_eq!(Style::new().on_gray(), Style::new().bg(Color::Gray));
assert_eq!(
Style::new().on_dark_gray(),
Style::new().bg(Color::DarkGray)
);
assert_eq!(
Style::new().on_light_red(),
Style::new().bg(Color::LightRed)
);
assert_eq!(
Style::new().on_light_green(),
Style::new().bg(Color::LightGreen)
);
assert_eq!(
Style::new().on_light_yellow(),
Style::new().bg(Color::LightYellow)
);
assert_eq!(
Style::new().on_light_blue(),
Style::new().bg(Color::LightBlue)
);
assert_eq!(
Style::new().on_light_magenta(),
Style::new().bg(Color::LightMagenta)
);
assert_eq!(
Style::new().on_light_cyan(),
Style::new().bg(Color::LightCyan)
);
assert_eq!(Style::new().on_white(), Style::new().bg(Color::White));

// Add Modifiers
assert_eq!(
Style::new().bold(),
Style::new().add_modifier(Modifier::BOLD)
);
assert_eq!(Style::new().dim(), Style::new().add_modifier(Modifier::DIM));
assert_eq!(
Style::new().italic(),
Style::new().add_modifier(Modifier::ITALIC)
);
assert_eq!(
Style::new().underlined(),
Style::new().add_modifier(Modifier::UNDERLINED)
);
assert_eq!(
Style::new().slow_blink(),
Style::new().add_modifier(Modifier::SLOW_BLINK)
);
assert_eq!(
Style::new().rapid_blink(),
Style::new().add_modifier(Modifier::RAPID_BLINK)
);
assert_eq!(
Style::new().reversed(),
Style::new().add_modifier(Modifier::REVERSED)
);
assert_eq!(
Style::new().hidden(),
Style::new().add_modifier(Modifier::HIDDEN)
);
assert_eq!(
Style::new().crossed_out(),
Style::new().add_modifier(Modifier::CROSSED_OUT)
);

// Remove Modifiers
assert_eq!(
Style::new().not_bold(),
Style::new().remove_modifier(Modifier::BOLD)
);
assert_eq!(
Style::new().not_dim(),
Style::new().remove_modifier(Modifier::DIM)
);
assert_eq!(
Style::new().not_italic(),
Style::new().remove_modifier(Modifier::ITALIC)
);
assert_eq!(
Style::new().not_underlined(),
Style::new().remove_modifier(Modifier::UNDERLINED)
);
assert_eq!(
Style::new().not_slow_blink(),
Style::new().remove_modifier(Modifier::SLOW_BLINK)
);
assert_eq!(
Style::new().not_rapid_blink(),
Style::new().remove_modifier(Modifier::RAPID_BLINK)
);
assert_eq!(
Style::new().not_reversed(),
Style::new().remove_modifier(Modifier::REVERSED)
);
assert_eq!(
Style::new().not_hidden(),
Style::new().remove_modifier(Modifier::HIDDEN)
);
assert_eq!(
Style::new().not_crossed_out(),
Style::new().remove_modifier(Modifier::CROSSED_OUT)
);

// reset
assert_eq!(Style::new().reset(), Style::reset());
}
}
Loading

0 comments on commit 5ac0f31

Please sign in to comment.