Support several modifiers and indexed colors at once

This commit is contained in:
David Flemström 2019-02-25 15:15:00 +01:00 committed by Florian Dehau
parent d360cd3434
commit b7664a4108
17 changed files with 265 additions and 197 deletions

View file

@ -97,7 +97,7 @@ fn main() -> Result<(), failure::Error> {
.bar_width(5)
.bar_gap(3)
.style(Style::default().fg(Color::Green))
.value_style(Style::default().bg(Color::Green).modifier(Modifier::Bold))
.value_style(Style::default().bg(Color::Green).modifier(Modifier::BOLD))
.render(&mut f, chunks[0]);
BarChart::default()
.block(Block::default().title("Data3").borders(Borders::ALL))
@ -106,7 +106,7 @@ fn main() -> Result<(), failure::Error> {
.bar_width(7)
.bar_gap(0)
.value_style(Style::default().bg(Color::Red))
.label_style(Style::default().fg(Color::Cyan).modifier(Modifier::Italic))
.label_style(Style::default().fg(Color::Cyan).modifier(Modifier::ITALIC))
.render(&mut f, chunks[1]);
}
})?;

View file

@ -54,7 +54,7 @@ fn main() -> Result<(), failure::Error> {
Style::default()
.fg(Color::White)
.bg(Color::Red)
.modifier(Modifier::Bold),
.modifier(Modifier::BOLD),
)
.render(&mut f, chunks[1]);
}

View file

@ -73,14 +73,14 @@ fn main() -> Result<(), failure::Error> {
.block(
Block::default()
.title("Chart")
.title_style(Style::default().fg(Color::Cyan).modifier(Modifier::Bold))
.title_style(Style::default().fg(Color::Cyan).modifier(Modifier::BOLD))
.borders(Borders::ALL),
)
.x_axis(
Axis::default()
.title("X Axis")
.style(Style::default().fg(Color::Gray))
.labels_style(Style::default().modifier(Modifier::Italic))
.style(Style::default().fg(Color::White))
.labels_style(Style::default().modifier(Modifier::ITALIC))
.bounds(app.window)
.labels(&[
&format!("{}", app.window[0]),
@ -91,8 +91,8 @@ fn main() -> Result<(), failure::Error> {
.y_axis(
Axis::default()
.title("Y Axis")
.style(Style::default().fg(Color::Gray))
.labels_style(Style::default().modifier(Modifier::Italic))
.style(Style::default().fg(Color::White))
.labels_style(Style::default().modifier(Modifier::ITALIC))
.bounds([-20.0, 20.0])
.labels(&["-20", "0", "20"]),
)

View file

@ -69,7 +69,7 @@ where
Style::default()
.fg(Color::Magenta)
.bg(Color::Black)
.modifier(Modifier::Italic),
.modifier(Modifier::ITALIC),
)
.label(&format!("{} / 100", app.progress))
.percent(app.progress)
@ -107,7 +107,7 @@ where
.block(Block::default().borders(Borders::ALL).title("List"))
.items(&app.tasks.items)
.select(Some(app.tasks.selected))
.highlight_style(Style::default().fg(Color::Yellow).modifier(Modifier::Bold))
.highlight_style(Style::default().fg(Color::Yellow).modifier(Modifier::BOLD))
.highlight_symbol(">")
.render(f, chunks[0]);
let info_style = Style::default().fg(Color::White);
@ -138,7 +138,7 @@ where
Style::default()
.fg(Color::Black)
.bg(Color::Green)
.modifier(Modifier::Italic),
.modifier(Modifier::ITALIC),
)
.label_style(Style::default().fg(Color::Yellow))
.style(Style::default().fg(Color::Green))
@ -149,14 +149,14 @@ where
.block(
Block::default()
.title("Chart")
.title_style(Style::default().fg(Color::Cyan).modifier(Modifier::Bold))
.title_style(Style::default().fg(Color::Cyan).modifier(Modifier::BOLD))
.borders(Borders::ALL),
)
.x_axis(
Axis::default()
.title("X Axis")
.style(Style::default().fg(Color::Gray))
.labels_style(Style::default().modifier(Modifier::Italic))
.labels_style(Style::default().modifier(Modifier::ITALIC))
.bounds(app.signals.window)
.labels(&[
&format!("{}", app.signals.window[0]),
@ -168,7 +168,7 @@ where
Axis::default()
.title("Y Axis")
.style(Style::default().fg(Color::Gray))
.labels_style(Style::default().modifier(Modifier::Italic))
.labels_style(Style::default().modifier(Modifier::ITALIC))
.bounds([-20.0, 20.0])
.labels(&["-20", "0", "20"]),
)
@ -200,13 +200,13 @@ where
Text::raw(" "),
Text::styled("rainbow", Style::default().fg(Color::Blue)),
Text::raw(".\nOh and if you didn't "),
Text::styled("notice", Style::default().modifier(Modifier::Italic)),
Text::styled("notice", Style::default().modifier(Modifier::ITALIC)),
Text::raw(" you can "),
Text::styled("automatically", Style::default().modifier(Modifier::Bold)),
Text::styled("automatically", Style::default().modifier(Modifier::BOLD)),
Text::raw(" "),
Text::styled("wrap", Style::default().modifier(Modifier::Invert)),
Text::styled("wrap", Style::default().modifier(Modifier::REVERSED)),
Text::raw(" your "),
Text::styled("text", Style::default().modifier(Modifier::Underline)),
Text::styled("text", Style::default().modifier(Modifier::UNDERLINED)),
Text::raw(".\nOne more thing is that it should display unicode characters: 10€")
];
Paragraph::new(text.iter())
@ -214,7 +214,7 @@ where
Block::default()
.borders(Borders::ALL)
.title("Footer")
.title_style(Style::default().fg(Color::Magenta).modifier(Modifier::Bold)),
.title_style(Style::default().fg(Color::Magenta).modifier(Modifier::BOLD)),
)
.wrap(true)
.render(f, area);

View file

@ -99,7 +99,7 @@ fn main() -> Result<(), failure::Error> {
.render(&mut f, chunks[2]);
Gauge::default()
.block(Block::default().title("Gauge4").borders(Borders::ALL))
.style(Style::default().fg(Color::Cyan).modifier(Modifier::Italic))
.style(Style::default().fg(Color::Cyan).modifier(Modifier::ITALIC))
.percent(app.progress4)
.label(&format!("{}/100", app.progress2))
.render(&mut f, chunks[3]);

View file

@ -102,7 +102,7 @@ fn main() -> Result<(), failure::Error> {
.items(&app.items)
.select(app.selected)
.style(style)
.highlight_style(style.fg(Color::LightGreen).modifier(Modifier::Bold))
.highlight_style(style.fg(Color::LightGreen).modifier(Modifier::BOLD))
.highlight_symbol(">")
.render(&mut f, chunks[0]);
{

View file

@ -60,18 +60,18 @@ fn main() -> Result<(), failure::Error> {
Text::styled("This is a line\n", Style::default().bg(Color::Blue)),
Text::styled(
"This is a longer line\n",
Style::default().modifier(Modifier::CrossedOut),
Style::default().modifier(Modifier::CROSSED_OUT),
),
Text::styled(&long_line, Style::default().bg(Color::Green)),
Text::styled(
"This is a line\n",
Style::default().fg(Color::Green).modifier(Modifier::Italic),
Style::default().fg(Color::Green).modifier(Modifier::ITALIC),
),
];
let block = Block::default()
.borders(Borders::ALL)
.title_style(Style::default().modifier(Modifier::Bold));
.title_style(Style::default().modifier(Modifier::BOLD));
Paragraph::new(text.iter())
.block(block.clone().title("Left, no wrap"))
.alignment(Alignment::Left)

View file

@ -53,7 +53,7 @@ fn main() -> Result<(), failure::Error> {
// Input
loop {
terminal.draw(|mut f| {
let selected_style = Style::default().fg(Color::Yellow).modifier(Modifier::Bold);
let selected_style = Style::default().fg(Color::Yellow).modifier(Modifier::BOLD);
let normal_style = Style::default().fg(Color::White);
let header = ["Header1", "Header2", "Header3"];
let rows = app.items.iter().enumerate().map(|(i, item)| {

View file

@ -149,9 +149,8 @@ impl Backend for CrosstermBackend {
if let Some(color) = cell.style.bg.into() {
s = s.on(color)
}
if let Some(attr) = cell.style.modifier.into() {
s = s.attr(attr)
}
s.object_style.attrs = cell.style.modifier.into();
self.crossterm.paint(s).map_err(convert_error)?;
}
Ok(())
@ -178,32 +177,59 @@ impl From<Color> for Option<crossterm::Color> {
Color::LightMagenta => Some(crossterm::Color::Magenta),
Color::LightCyan => Some(crossterm::Color::Cyan),
Color::White => Some(crossterm::Color::White),
Color::Indexed(i) => Some(crossterm::Color::AnsiValue(i)),
Color::Rgb(r, g, b) => Some(crossterm::Color::Rgb { r, g, b }),
}
}
}
impl From<Modifier> for Option<crossterm::Attribute> {
impl From<Modifier> for Vec<crossterm::Attribute> {
#[cfg(unix)]
fn from(modifier: Modifier) -> Option<crossterm::Attribute> {
match modifier {
Modifier::Blink => Some(crossterm::Attribute::SlowBlink),
Modifier::Bold => Some(crossterm::Attribute::Bold),
Modifier::CrossedOut => Some(crossterm::Attribute::CrossedOut),
Modifier::Faint => Some(crossterm::Attribute::Dim),
Modifier::Invert => Some(crossterm::Attribute::Reverse),
Modifier::Italic => Some(crossterm::Attribute::Italic),
Modifier::Underline => Some(crossterm::Attribute::Underlined),
_ => None,
fn from(modifier: Modifier) -> Vec<crossterm::Attribute> {
let mut result = Vec::new();
if modifier.contains(Modifier::BOLD) {
result.push(crossterm::Attribute::Bold)
}
if modifier.contains(Modifier::DIM) {
result.push(crossterm::Attribute::Dim)
}
if modifier.contains(Modifier::ITALIC) {
result.push(crossterm::Attribute::Italic)
}
if modifier.contains(Modifier::UNDERLINED) {
result.push(crossterm::Attribute::Underlined)
}
if modifier.contains(Modifier::SLOW_BLINK) {
result.push(crossterm::Attribute::SlowBlink)
}
if modifier.contains(Modifier::RAPID_BLINK) {
result.push(crossterm::Attribute::RapidBlink)
}
if modifier.contains(Modifier::REVERSED) {
result.push(crossterm::Attribute::Reverse)
}
if modifier.contains(Modifier::HIDDEN) {
result.push(crossterm::Attribute::Hidden)
}
if modifier.contains(Modifier::CROSSED_OUT) {
result.push(crossterm::Attribute::CrossedOut)
}
result
}
#[cfg(windows)]
fn from(modifier: Modifier) -> Option<crossterm::Attribute> {
match modifier {
Modifier::Bold => Some(crossterm::Attribute::Bold),
Modifier::Underline => Some(crossterm::Attribute::Underlined),
_ => None,
fn from(modifier: Modifier) -> Vec<crossterm::Attribute> {
let mut result = Vec::new();
if modifier.contains(Modifier::BOLD) {
result.push(crossterm::Attribute::Bold)
}
if modifier.contains(Modifier::UNDERLINED) {
result.push(crossterm::Attribute::Underlined)
}
result
}
}

View file

@ -103,6 +103,7 @@ impl Into<rustbox::Color> for Color {
Color::Cyan | Color::LightCyan => rustbox::Color::Cyan,
Color::White => rustbox::Color::White,
Color::Blue | Color::LightBlue => rustbox::Color::Blue,
Color::Indexed(i) => rustbox::Color::Byte(i as u16),
Color::Rgb(r, g, b) => rustbox::Color::Byte(rgb_to_byte(r, g, b)),
}
}
@ -110,11 +111,16 @@ impl Into<rustbox::Color> for Color {
impl Into<rustbox::Style> for Modifier {
fn into(self) -> rustbox::Style {
match self {
Modifier::Bold => rustbox::RB_BOLD,
Modifier::Underline => rustbox::RB_UNDERLINE,
Modifier::Invert => rustbox::RB_REVERSE,
_ => rustbox::RB_NORMAL,
let mut result = rustbox::Style::empty();
if self.contains(Modifier::BOLD) {
result.insert(rustbox::RB_BOLD);
}
if self.contains(Modifier::UNDERLINED) {
result.insert(rustbox::RB_UNDERLINE);
}
if self.contains(Modifier::REVERSED) {
result.insert(rustbox::RB_REVERSE);
}
result
}
}

View file

@ -1,11 +1,12 @@
use log::debug;
use std::fmt;
use std::io;
use std::io::Write;
use super::Backend;
use crate::buffer::Cell;
use crate::layout::Rect;
use crate::style::{Color, Modifier, Style};
use crate::style;
pub struct TermionBackend<W>
where
@ -74,34 +75,40 @@ where
where
I: Iterator<Item = (u16, u16, &'a Cell)>,
{
use std::fmt::Write;
let mut string = String::with_capacity(content.size_hint().0 * 3);
let mut style = Style::default();
let mut style = style::Style::default();
let mut last_y = 0;
let mut last_x = 0;
let mut inst = 0;
for (x, y, cell) in content {
if y != last_y || x != last_x + 1 || inst == 0 {
string.push_str(&format!("{}", termion::cursor::Goto(x + 1, y + 1)));
write!(string, "{}", termion::cursor::Goto(x + 1, y + 1)).unwrap();
inst += 1;
}
last_x = x;
last_y = y;
if cell.style.modifier != style.modifier {
string.push_str(&cell.style.modifier.termion_modifier());
write!(
string,
"{}",
ModifierDiff {
from: style.modifier,
to: cell.style.modifier
}
)
.unwrap();
style.modifier = cell.style.modifier;
if style.modifier == Modifier::Reset {
style.bg = Color::Reset;
style.fg = Color::Reset;
}
inst += 1;
}
if cell.style.fg != style.fg {
string.push_str(&cell.style.fg.termion_fg());
write!(string, "{}", Fg(cell.style.fg)).unwrap();
style.fg = cell.style.fg;
inst += 1;
}
if cell.style.bg != style.bg {
string.push_str(&cell.style.bg.termion_bg());
write!(string, "{}", Bg(cell.style.bg)).unwrap();
style.bg = cell.style.bg;
inst += 1;
}
@ -113,9 +120,9 @@ where
self.stdout,
"{}{}{}{}",
string,
Color::Reset.termion_fg(),
Color::Reset.termion_bg(),
Modifier::Reset.termion_modifier()
Fg(style::Color::Reset),
Bg(style::Color::Reset),
termion::style::Reset,
)
}
@ -130,102 +137,118 @@ where
}
}
macro_rules! termion_fg {
($color:ident) => {
format!("{}", termion::color::Fg(termion::color::$color))
};
struct Fg(style::Color);
struct Bg(style::Color);
struct ModifierDiff {
from: style::Modifier,
to: style::Modifier,
}
macro_rules! termion_fg_rgb {
($r:expr, $g:expr, $b:expr) => {
format!("{}", termion::color::Fg(termion::color::Rgb($r, $g, $b)))
};
}
macro_rules! termion_bg {
($color:ident) => {
format!("{}", termion::color::Bg(termion::color::$color))
};
}
macro_rules! termion_bg_rgb {
($r:expr, $g:expr, $b:expr) => {
format!("{}", termion::color::Bg(termion::color::Rgb($r, $g, $b)))
};
}
macro_rules! termion_modifier {
($style:ident) => {
format!("{}", termion::style::$style)
};
}
impl Color {
pub fn termion_fg(self) -> String {
match self {
Color::Reset => termion_fg!(Reset),
Color::Black => termion_fg!(Black),
Color::Red => termion_fg!(Red),
Color::Green => termion_fg!(Green),
Color::Yellow => termion_fg!(Yellow),
Color::Blue => termion_fg!(Blue),
Color::Magenta => termion_fg!(Magenta),
Color::Cyan => termion_fg!(Cyan),
Color::Gray => termion_fg!(White),
Color::DarkGray => termion_fg!(LightBlack),
Color::LightRed => termion_fg!(LightRed),
Color::LightGreen => termion_fg!(LightGreen),
Color::LightBlue => termion_fg!(LightBlue),
Color::LightYellow => termion_fg!(LightYellow),
Color::LightMagenta => termion_fg!(LightMagenta),
Color::LightCyan => termion_fg!(LightCyan),
Color::White => termion_fg!(LightWhite),
Color::Rgb(r, g, b) => termion_fg_rgb!(r, g, b),
impl fmt::Display for Fg {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use termion::color::Color;
match self.0 {
style::Color::Reset => termion::color::Reset.write_fg(f),
style::Color::Black => termion::color::Black.write_fg(f),
style::Color::Red => termion::color::Red.write_fg(f),
style::Color::Green => termion::color::Green.write_fg(f),
style::Color::Yellow => termion::color::Yellow.write_fg(f),
style::Color::Blue => termion::color::Blue.write_fg(f),
style::Color::Magenta => termion::color::Magenta.write_fg(f),
style::Color::Cyan => termion::color::Cyan.write_fg(f),
style::Color::Gray => termion::color::White.write_fg(f),
style::Color::DarkGray => termion::color::LightBlack.write_fg(f),
style::Color::LightRed => termion::color::LightRed.write_fg(f),
style::Color::LightGreen => termion::color::LightGreen.write_fg(f),
style::Color::LightBlue => termion::color::LightBlue.write_fg(f),
style::Color::LightYellow => termion::color::LightYellow.write_fg(f),
style::Color::LightMagenta => termion::color::LightMagenta.write_fg(f),
style::Color::LightCyan => termion::color::LightCyan.write_fg(f),
style::Color::White => termion::color::LightWhite.write_fg(f),
style::Color::Indexed(i) => termion::color::AnsiValue(i).write_fg(f),
style::Color::Rgb(r, g, b) => termion::color::Rgb(r, g, b).write_fg(f),
}
}
pub fn termion_bg(self) -> String {
match self {
Color::Reset => termion_bg!(Reset),
Color::Black => termion_bg!(Black),
Color::Red => termion_bg!(Red),
Color::Green => termion_bg!(Green),
Color::Yellow => termion_bg!(Yellow),
Color::Blue => termion_bg!(Blue),
Color::Magenta => termion_bg!(Magenta),
Color::Cyan => termion_bg!(Cyan),
Color::Gray => termion_bg!(White),
Color::DarkGray => termion_bg!(LightBlack),
Color::LightRed => termion_bg!(LightRed),
Color::LightGreen => termion_bg!(LightGreen),
Color::LightBlue => termion_bg!(LightBlue),
Color::LightYellow => termion_bg!(LightYellow),
Color::LightMagenta => termion_bg!(LightMagenta),
Color::LightCyan => termion_bg!(LightCyan),
Color::White => termion_bg!(LightWhite),
Color::Rgb(r, g, b) => termion_bg_rgb!(r, g, b),
}
impl fmt::Display for Bg {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use termion::color::Color;
match self.0 {
style::Color::Reset => termion::color::Reset.write_bg(f),
style::Color::Black => termion::color::Black.write_bg(f),
style::Color::Red => termion::color::Red.write_bg(f),
style::Color::Green => termion::color::Green.write_bg(f),
style::Color::Yellow => termion::color::Yellow.write_bg(f),
style::Color::Blue => termion::color::Blue.write_bg(f),
style::Color::Magenta => termion::color::Magenta.write_bg(f),
style::Color::Cyan => termion::color::Cyan.write_bg(f),
style::Color::Gray => termion::color::White.write_bg(f),
style::Color::DarkGray => termion::color::LightBlack.write_bg(f),
style::Color::LightRed => termion::color::LightRed.write_bg(f),
style::Color::LightGreen => termion::color::LightGreen.write_bg(f),
style::Color::LightBlue => termion::color::LightBlue.write_bg(f),
style::Color::LightYellow => termion::color::LightYellow.write_bg(f),
style::Color::LightMagenta => termion::color::LightMagenta.write_bg(f),
style::Color::LightCyan => termion::color::LightCyan.write_bg(f),
style::Color::White => termion::color::LightWhite.write_bg(f),
style::Color::Indexed(i) => termion::color::AnsiValue(i).write_bg(f),
style::Color::Rgb(r, g, b) => termion::color::Rgb(r, g, b).write_bg(f),
}
}
}
impl Modifier {
pub fn termion_modifier(self) -> String {
match self {
Modifier::Blink => termion_modifier!(Blink),
Modifier::Bold => termion_modifier!(Bold),
Modifier::CrossedOut => termion_modifier!(CrossedOut),
Modifier::Faint => termion_modifier!(Faint),
Modifier::Framed => termion_modifier!(Framed),
Modifier::Invert => termion_modifier!(Invert),
Modifier::Italic => termion_modifier!(Italic),
Modifier::NoBlink => termion_modifier!(NoBlink),
Modifier::NoBold => termion_modifier!(NoBold),
Modifier::NoCrossedOut => termion_modifier!(NoCrossedOut),
Modifier::NoFaint => termion_modifier!(NoFaint),
Modifier::NoInvert => termion_modifier!(NoInvert),
Modifier::NoItalic => termion_modifier!(NoItalic),
Modifier::NoUnderline => termion_modifier!(NoUnderline),
Modifier::Reset => termion_modifier!(Reset),
Modifier::Underline => termion_modifier!(Underline),
impl fmt::Display for ModifierDiff {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let remove = self.from - self.to;
if remove.contains(style::Modifier::REVERSED) {
write!(f, "{}", termion::style::NoInvert)?;
}
if remove.contains(style::Modifier::BOLD) {
write!(f, "{}", termion::style::NoBold)?;
}
if remove.contains(style::Modifier::ITALIC) {
write!(f, "{}", termion::style::NoItalic)?;
}
if remove.contains(style::Modifier::UNDERLINED) {
write!(f, "{}", termion::style::NoUnderline)?;
}
if remove.contains(style::Modifier::DIM) {
write!(f, "{}", termion::style::NoFaint)?;
}
if remove.contains(style::Modifier::CROSSED_OUT) {
write!(f, "{}", termion::style::NoCrossedOut)?;
}
if remove.contains(style::Modifier::SLOW_BLINK)
|| remove.contains(style::Modifier::RAPID_BLINK)
{
write!(f, "{}", termion::style::NoBlink)?;
}
let add = self.to - self.from;
if add.contains(style::Modifier::REVERSED) {
write!(f, "{}", termion::style::Invert)?;
}
if add.contains(style::Modifier::BOLD) {
write!(f, "{}", termion::style::Bold)?;
}
if add.contains(style::Modifier::ITALIC) {
write!(f, "{}", termion::style::Italic)?;
}
if add.contains(style::Modifier::UNDERLINED) {
write!(f, "{}", termion::style::Underline)?;
}
if add.contains(style::Modifier::DIM) {
write!(f, "{}", termion::style::Faint)?;
}
if add.contains(style::Modifier::CROSSED_OUT) {
write!(f, "{}", termion::style::CrossedOut)?;
}
if add.contains(style::Modifier::SLOW_BLINK) || add.contains(style::Modifier::RAPID_BLINK) {
write!(f, "{}", termion::style::Blink)?;
}
Ok(())
}
}

View file

@ -88,7 +88,7 @@ impl Default for Cell {
/// style: Style {
/// fg: Color::Red,
/// bg: Color::White,
/// modifier: Modifier::Reset
/// modifier: Modifier::empty()
/// }});
/// buf.get_mut(5, 0).set_char('x');
/// assert_eq!(buf.get(5, 0).symbol, "x");

View file

@ -1,3 +1,5 @@
use bitflags::bitflags;
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum Color {
Reset,
@ -18,6 +20,7 @@ pub enum Color {
LightCyan,
White,
Rgb(u8, u8, u8),
Indexed(u8),
}
impl Color {
@ -33,62 +36,72 @@ impl Color {
Color::Blue => "b",
Color::Magenta => "m",
Color::Cyan => "c",
Color::Gray => "g",
Color::DarkGray => "G",
Color::Gray => "w",
Color::DarkGray => "B",
Color::LightRed => "R",
Color::LightGreen => "G",
Color::LightYellow => "Y",
Color::LightBlue => "B",
Color::LightMagenta => "M",
Color::LightCyan => "C",
Color::White => "w",
Color::White => "W",
Color::Indexed(_) => "i",
Color::Rgb(_, _, _) => "o",
}
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum Modifier {
Blink,
Bold,
CrossedOut,
Faint,
Framed,
Invert,
Italic,
NoBlink,
NoBold,
NoCrossedOut,
NoFaint,
NoInvert,
NoItalic,
NoUnderline,
Reset,
Underline,
bitflags! {
pub struct Modifier: u16 {
const BOLD = 0b0000_0000_0001;
const DIM = 0b0000_0000_0010;
const ITALIC = 0b0000_0000_0100;
const UNDERLINED = 0b0000_0000_1000;
const SLOW_BLINK = 0b0000_0001_0000;
const RAPID_BLINK = 0b0000_0010_0000;
const REVERSED = 0b0000_0100_0000;
const HIDDEN = 0b0000_1000_0000;
const CROSSED_OUT = 0b0001_0000_0000;
}
}
impl Modifier {
/// Returns a short code associated with the color, used for debug purpose
/// only
pub(crate) fn code(&self) -> &str {
match self {
Modifier::Blink => "bl",
Modifier::Bold => "bo",
Modifier::CrossedOut => "cr",
Modifier::Faint => "fa",
Modifier::Framed => "fr",
Modifier::Invert => "in",
Modifier::Italic => "it",
Modifier::NoBlink => "BL",
Modifier::NoBold => "BO",
Modifier::NoCrossedOut => "CR",
Modifier::NoFaint => "FA",
Modifier::NoInvert => "IN",
Modifier::NoItalic => "IT",
Modifier::NoUnderline => "UN",
Modifier::Reset => "re",
Modifier::Underline => "un",
pub(crate) fn code(&self) -> String {
use std::fmt::Write;
let mut result = String::new();
if self.contains(Modifier::BOLD) {
write!(result, "BO").unwrap();
}
if self.contains(Modifier::DIM) {
write!(result, "DI").unwrap();
}
if self.contains(Modifier::ITALIC) {
write!(result, "IT").unwrap();
}
if self.contains(Modifier::UNDERLINED) {
write!(result, "UN").unwrap();
}
if self.contains(Modifier::SLOW_BLINK) {
write!(result, "SL").unwrap();
}
if self.contains(Modifier::RAPID_BLINK) {
write!(result, "RA").unwrap();
}
if self.contains(Modifier::REVERSED) {
write!(result, "RE").unwrap();
}
if self.contains(Modifier::HIDDEN) {
write!(result, "HI").unwrap();
}
if self.contains(Modifier::CROSSED_OUT) {
write!(result, "CR").unwrap();
}
result
}
}
@ -104,7 +117,7 @@ impl Default for Style {
Style {
fg: Color::Reset,
bg: Color::Reset,
modifier: Modifier::Reset,
modifier: Modifier::empty(),
}
}
}
@ -113,7 +126,7 @@ impl Style {
pub fn reset(&mut self) {
self.fg = Color::Reset;
self.bg = Color::Reset;
self.modifier = Modifier::Reset;
self.modifier = Modifier::empty();
}
pub fn fg(mut self, color: Color) -> Style {

View file

@ -21,7 +21,7 @@ use crate::widgets::{Block, Widget};
/// .bar_width(3)
/// .bar_gap(1)
/// .style(Style::default().fg(Color::Yellow).bg(Color::Red))
/// .value_style(Style::default().fg(Color::Red).modifier(Modifier::Bold))
/// .value_style(Style::default().fg(Color::Red).modifier(Modifier::BOLD))
/// .label_style(Style::default().fg(Color::White))
/// .data(&[("B0", 0), ("B1", 2), ("B2", 4), ("B3", 3)])
/// .max(4);

View file

@ -174,13 +174,13 @@ impl Default for ChartLayout {
/// .x_axis(Axis::default()
/// .title("X Axis")
/// .title_style(Style::default().fg(Color::Red))
/// .style(Style::default().fg(Color::Gray))
/// .style(Style::default().fg(Color::White))
/// .bounds([0.0, 10.0])
/// .labels(&["0.0", "5.0", "10.0"]))
/// .y_axis(Axis::default()
/// .title("Y Axis")
/// .title_style(Style::default().fg(Color::Red))
/// .style(Style::default().fg(Color::Gray))
/// .style(Style::default().fg(Color::White))
/// .bounds([0.0, 10.0])
/// .labels(&["0.0", "5.0", "10.0"]))
/// .datasets(&[Dataset::default()

View file

@ -15,7 +15,7 @@ use crate::widgets::{Block, Widget};
/// # fn main() {
/// Gauge::default()
/// .block(Block::default().borders(Borders::ALL).title("Progress"))
/// .style(Style::default().fg(Color::White).bg(Color::Black).modifier(Modifier::Italic))
/// .style(Style::default().fg(Color::White).bg(Color::Black).modifier(Modifier::ITALIC))
/// .percent(20);
/// # }
/// ```

View file

@ -125,7 +125,7 @@ where
/// .items(&["Item 1", "Item 2", "Item 3"])
/// .select(Some(1))
/// .style(Style::default().fg(Color::White))
/// .highlight_style(Style::default().modifier(Modifier::Italic))
/// .highlight_style(Style::default().modifier(Modifier::ITALIC))
/// .highlight_symbol(">>");
/// # }
/// ```