From 358b50ba21dd924a6a05efa3f96f5ce7ea6b9467 Mon Sep 17 00:00:00 2001 From: Josh McKinney Date: Thu, 1 Jun 2023 06:37:59 -0700 Subject: [PATCH] build(deps)!: upgrade bitflags to 2.3 (#205) BREAKING CHANGE: The serde representation of bitflags has changed. Any existing serialized types that have Borders or Modifiers will need to be re-serialized. This is documented in the bitflags changelog. https://github.com/bitflags/bitflags/blob/main/CHANGELOG.md#200-rc2 --- Cargo.toml | 3 ++- src/buffer.rs | 2 +- src/style.rs | 42 +++++++++++++++++++++++++++++++++- src/widgets/mod.rs | 57 +++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 100 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 9c767b9c..448abdbc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,6 +22,7 @@ default = ["crossterm"] all-widgets = ["widget-calendar"] widget-calendar = ["time"] macros = [] +serde = ["dep:serde", "bitflags/serde"] [package.metadata.docs.rs] all-features = true @@ -29,7 +30,7 @@ all-features = true cargo-args = ["-Zunstable-options", "-Zrustdoc-scrape-examples"] [dependencies] -bitflags = "1.3" +bitflags = "2.3" cassowary = "0.3" unicode-segmentation = "1.10" unicode-width = "0.1" diff --git a/src/buffer.rs b/src/buffer.rs index 9cf61f75..fdb1ffd6 100644 --- a/src/buffer.rs +++ b/src/buffer.rs @@ -614,7 +614,7 @@ mod tests { \"G'day World!\", ], styles: [ - x: 0, y: 0, fg: Reset, bg: Reset, modifier: (empty), + x: 0, y: 0, fg: Reset, bg: Reset, modifier: NONE, x: 0, y: 1, fg: Green, bg: Yellow, modifier: BOLD, ] }" diff --git a/src/style.rs b/src/style.rs index 31455df7..8cae24e7 100644 --- a/src/style.rs +++ b/src/style.rs @@ -1,7 +1,10 @@ //! `style` contains the primitives used to control how your user interface will look. use bitflags::bitflags; -use std::str::FromStr; +use std::{ + fmt::{self, Debug}, + str::FromStr, +}; #[derive(Debug, Clone, Copy, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] @@ -40,6 +43,7 @@ bitflags! { /// let m = Modifier::BOLD | Modifier::ITALIC; /// ``` #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] + #[derive(Clone, Copy, PartialEq, Eq)] pub struct Modifier: u16 { const BOLD = 0b0000_0000_0001; const DIM = 0b0000_0000_0010; @@ -53,6 +57,20 @@ bitflags! { } } +/// Implement the `Debug` trait for `Modifier` manually. +/// +/// This will avoid printing the empty modifier as 'Borders(0x0)' and instead print it as 'NONE'. +impl fmt::Debug for Modifier { + /// Format the modifier as `NONE` if the modifier is empty or as a list of flags separated by + /// `|` otherwise. + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + if self.is_empty() { + return write!(f, "NONE"); + } + fmt::Debug::fmt(&self.0, f) + } +} + /// Style let you control the main characteristics of the displayed elements. /// /// ```rust @@ -392,6 +410,28 @@ mod tests { } } + #[test] + fn test_modifier_debug() { + assert_eq!(format!("{:?}", Modifier::empty()), "NONE"); + assert_eq!(format!("{:?}", Modifier::BOLD), "BOLD"); + assert_eq!(format!("{:?}", Modifier::DIM), "DIM"); + assert_eq!(format!("{:?}", Modifier::ITALIC), "ITALIC"); + assert_eq!(format!("{:?}", Modifier::UNDERLINED), "UNDERLINED"); + assert_eq!(format!("{:?}", Modifier::SLOW_BLINK), "SLOW_BLINK"); + assert_eq!(format!("{:?}", Modifier::RAPID_BLINK), "RAPID_BLINK"); + assert_eq!(format!("{:?}", Modifier::REVERSED), "REVERSED"); + assert_eq!(format!("{:?}", Modifier::HIDDEN), "HIDDEN"); + assert_eq!(format!("{:?}", Modifier::CROSSED_OUT), "CROSSED_OUT"); + assert_eq!( + format!("{:?}", Modifier::BOLD | Modifier::DIM), + "BOLD | DIM" + ); + assert_eq!( + format!("{:?}", Modifier::all()), + "BOLD | DIM | ITALIC | UNDERLINED | SLOW_BLINK | RAPID_BLINK | REVERSED | HIDDEN | CROSSED_OUT" + ); + } + #[test] fn test_rgb_color() { let color: Color = Color::from_str("#FF0000").unwrap(); diff --git a/src/widgets/mod.rs b/src/widgets/mod.rs index 7d92a77f..5e305269 100644 --- a/src/widgets/mod.rs +++ b/src/widgets/mod.rs @@ -31,6 +31,8 @@ mod sparkline; mod table; mod tabs; +use std::fmt::{self, Debug}; + pub use self::barchart::BarChart; pub use self::block::{Block, BorderType, Padding}; pub use self::chart::{Axis, Chart, Dataset, GraphType}; @@ -47,6 +49,7 @@ use bitflags::bitflags; bitflags! { /// Bitflags that can be composed to set the visible borders essentially on the block widget. + #[derive(Clone, Copy, Default, PartialEq, Eq)] pub struct Borders: u8 { /// Show no border (default) const NONE = 0b0000; @@ -59,7 +62,37 @@ bitflags! { /// Show the left border const LEFT = 0b1000; /// Show all borders - const ALL = Self::TOP.bits | Self::RIGHT.bits | Self::BOTTOM.bits | Self::LEFT.bits; + const ALL = Self::TOP.bits() | Self::RIGHT.bits() | Self::BOTTOM.bits() | Self::LEFT.bits(); + } +} + +/// Implement the `Debug` trait for the `Borders` bitflags. This is a manual implementation to +/// display the flags in a more readable way. The default implementation would display the +/// flags as 'Border(0x0)' for `Borders::NONE` for example. +impl Debug for Borders { + /// Display the Borders bitflags as a list of names. For example, `Borders::NONE` will be + /// displayed as `NONE` and `Borders::ALL` will be displayed as `ALL`. If multiple flags are + /// set, they will be displayed separated by a pipe character. + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + if self.is_empty() { + return write!(f, "NONE"); + } + if self.is_all() { + return write!(f, "ALL"); + } + let mut first = true; + for (name, border) in self.iter_names() { + if border == Borders::NONE { + continue; + } + if first { + write!(f, "{}", name)?; + first = false; + } else { + write!(f, " | {}", name)?; + } + } + Ok(()) } } @@ -223,3 +256,25 @@ macro_rules! border { Borders::NONE } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_borders_debug() { + assert_eq!(format!("{:?}", Borders::empty()), "NONE"); + assert_eq!(format!("{:?}", Borders::NONE), "NONE"); + assert_eq!(format!("{:?}", Borders::TOP), "TOP"); + assert_eq!(format!("{:?}", Borders::BOTTOM), "BOTTOM"); + assert_eq!(format!("{:?}", Borders::LEFT), "LEFT"); + assert_eq!(format!("{:?}", Borders::RIGHT), "RIGHT"); + assert_eq!(format!("{:?}", Borders::ALL), "ALL"); + assert_eq!(format!("{:?}", Borders::all()), "ALL"); + + assert_eq!( + format!("{:?}", Borders::TOP | Borders::BOTTOM), + "TOP | BOTTOM" + ); + } +}