From ef8bc7c5a8d3a48c2b562d4dd59fbeb6d6122b03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Orhun=20Parmaks=C4=B1z?= Date: Mon, 22 May 2023 00:26:39 +0200 Subject: [PATCH] feat(border): add border! macro for easy bitflag manipulation (#11) Adds a `border!` macro that takes TOP, BOTTOM, LEFT, RIGHT, and ALL and returns a Borders object. An empty `border!()` call returns Borders::NONE This is gated behind a `macros` feature flag to ensure short build times. To enable, add the following to your `Cargo.toml`: ```toml ratatui = { version = 0.21.0, features = ["macros"] } ``` Co-authored-by: C-Jameson --- Cargo.toml | 1 + Makefile.toml | 6 +++--- src/widgets/mod.rs | 38 ++++++++++++++++++++++++++++++++++++++ tests/border_macro.rs | 19 +++++++++++++++++++ 4 files changed, 61 insertions(+), 3 deletions(-) create mode 100644 tests/border_macro.rs diff --git a/Cargo.toml b/Cargo.toml index c4bd1fe0..f6d0f097 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,6 +21,7 @@ rust-version = "1.65.0" default = ["crossterm"] all-widgets = ["widget-calendar"] widget-calendar = ["time"] +macros = [] [package.metadata.docs.rs] all-features = true diff --git a/Makefile.toml b/Makefile.toml index e04cca8f..3077c9a6 100644 --- a/Makefile.toml +++ b/Makefile.toml @@ -118,15 +118,15 @@ args = [ ] [tasks.test-crossterm] -env = { TUI_FEATURES = "serde,crossterm,all-widgets" } +env = { TUI_FEATURES = "serde,crossterm,all-widgets,macros" } run_task = "test" [tasks.test-termion] -env = { TUI_FEATURES = "serde,termion,all-widgets" } +env = { TUI_FEATURES = "serde,termion,all-widgets,macros" } run_task = "test" [tasks.test-termwiz] -env = { TUI_FEATURES = "serde,termwiz,all-widgets" } +env = { TUI_FEATURES = "serde,termwiz,all-widgets,macros" } run_task = "test" [tasks.test] diff --git a/src/widgets/mod.rs b/src/widgets/mod.rs index 00e21642..7d92a77f 100644 --- a/src/widgets/mod.rs +++ b/src/widgets/mod.rs @@ -185,3 +185,41 @@ pub trait StatefulWidget { type State; fn render(self, area: Rect, buf: &mut Buffer, state: &mut Self::State); } + +/// Macro that constructs and returns a [`Borders`] object from TOP, BOTTOM, LEFT, RIGHT, NONE, and ALL. +/// Internally it creates an empty `Borders` object and then inserts each bit flag specified +/// into it using `Borders::insert()`. +/// +/// ## Examples +/// +///``` +/// # use tui::widgets::{Block, Borders}; +/// # use tui::style::{Style, Color}; +/// # use tui::border; +/// +/// Block::default() +/// //Construct a `Borders` object and use it in place +/// .borders(border!(TOP, BOTTOM)); +/// +/// //`border!` can be called with any order of individual sides +/// let bottom_first = border!(BOTTOM, LEFT, TOP); +/// //with the ALL keyword which works as expected +/// let all = border!(ALL); +/// //or with nothing to return a `Borders::NONE' bitflag. +/// let none = border!(NONE); +/// +///``` +#[cfg(feature = "macros")] +#[macro_export] +macro_rules! border { + ( $($b:tt), +) => {{ + let mut border = Borders::empty(); + $( + border.insert(Borders::$b); + )* + border + }}; + () =>{ + Borders::NONE + } +} diff --git a/tests/border_macro.rs b/tests/border_macro.rs new file mode 100644 index 00000000..fc8cc8cd --- /dev/null +++ b/tests/border_macro.rs @@ -0,0 +1,19 @@ +#![cfg(feature = "macros")] +use ratatui::{border, widgets::Borders}; + +#[test] +fn border_empty_test() { + let empty = Borders::NONE; + assert_eq!(empty, border!()); +} +#[test] +fn border_all_test() { + let all = Borders::ALL; + assert_eq!(all, border!(ALL)); + assert_eq!(all, border!(TOP, BOTTOM, LEFT, RIGHT)); +} +#[test] +fn border_left_right_test() { + let left_right = Borders::from_bits(Borders::LEFT.bits() | Borders::RIGHT.bits()); + assert_eq!(left_right, Some(border!(RIGHT, LEFT))); +}