diff --git a/examples/barchart.rs b/examples/barchart.rs index 37527cae..733a732c 100644 --- a/examples/barchart.rs +++ b/examples/barchart.rs @@ -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]); } })?; diff --git a/examples/block.rs b/examples/block.rs index fe48f988..8fe4c696 100644 --- a/examples/block.rs +++ b/examples/block.rs @@ -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]); } diff --git a/examples/chart.rs b/examples/chart.rs index d9de012d..ab0c49d7 100644 --- a/examples/chart.rs +++ b/examples/chart.rs @@ -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"]), ) diff --git a/examples/demo/ui.rs b/examples/demo/ui.rs index e3d010ab..c7936400 100644 --- a/examples/demo/ui.rs +++ b/examples/demo/ui.rs @@ -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); diff --git a/examples/gauge.rs b/examples/gauge.rs index 76f0b567..fed39a09 100644 --- a/examples/gauge.rs +++ b/examples/gauge.rs @@ -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]); diff --git a/examples/list.rs b/examples/list.rs index 331a2900..8a3ee193 100644 --- a/examples/list.rs +++ b/examples/list.rs @@ -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]); { diff --git a/examples/paragraph.rs b/examples/paragraph.rs index e60ba8b2..197c15ae 100644 --- a/examples/paragraph.rs +++ b/examples/paragraph.rs @@ -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) diff --git a/examples/table.rs b/examples/table.rs index 5d4e3309..53911365 100644 --- a/examples/table.rs +++ b/examples/table.rs @@ -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)| { diff --git a/src/backend/crossterm.rs b/src/backend/crossterm.rs index 3b420900..cbf8275d 100644 --- a/src/backend/crossterm.rs +++ b/src/backend/crossterm.rs @@ -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 for Option { 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 for Option { +impl From for Vec { #[cfg(unix)] - fn from(modifier: Modifier) -> Option { - 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 { + 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 { - match modifier { - Modifier::Bold => Some(crossterm::Attribute::Bold), - Modifier::Underline => Some(crossterm::Attribute::Underlined), - _ => None, + fn from(modifier: Modifier) -> Vec { + 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 } } diff --git a/src/backend/rustbox.rs b/src/backend/rustbox.rs index 8bed14c4..0c40c80a 100644 --- a/src/backend/rustbox.rs +++ b/src/backend/rustbox.rs @@ -103,6 +103,7 @@ impl Into 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 for Color { impl Into 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 } } diff --git a/src/backend/termion.rs b/src/backend/termion.rs index d7da76fc..9b24334d 100644 --- a/src/backend/termion.rs +++ b/src/backend/termion.rs @@ -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 where @@ -74,34 +75,40 @@ where where I: Iterator, { + 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(()) } } diff --git a/src/buffer.rs b/src/buffer.rs index 5b1ecfc3..a6b7da78 100644 --- a/src/buffer.rs +++ b/src/buffer.rs @@ -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"); diff --git a/src/style.rs b/src/style.rs index 00207cd7..cf0d7b17 100644 --- a/src/style.rs +++ b/src/style.rs @@ -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 { diff --git a/src/widgets/barchart.rs b/src/widgets/barchart.rs index f745e679..06009735 100644 --- a/src/widgets/barchart.rs +++ b/src/widgets/barchart.rs @@ -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); diff --git a/src/widgets/chart.rs b/src/widgets/chart.rs index e7048922..d99ce9f5 100644 --- a/src/widgets/chart.rs +++ b/src/widgets/chart.rs @@ -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() diff --git a/src/widgets/gauge.rs b/src/widgets/gauge.rs index d38c7a56..9aa2c75b 100644 --- a/src/widgets/gauge.rs +++ b/src/widgets/gauge.rs @@ -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); /// # } /// ``` diff --git a/src/widgets/list.rs b/src/widgets/list.rs index 1a908fc4..d6cbd014 100644 --- a/src/widgets/list.rs +++ b/src/widgets/list.rs @@ -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(">>"); /// # } /// ```