ratatui/widgets/
borders.rs1use std::fmt;
2
3use bitflags::bitflags;
4
5bitflags! {
6 #[derive(Default, Clone, Copy, Eq, PartialEq, Hash)]
8 pub struct Borders: u8 {
9 const NONE = 0b0000;
11 const TOP = 0b0001;
13 const RIGHT = 0b0010;
15 const BOTTOM = 0b0100;
17 const LEFT = 0b1000;
19 const ALL = Self::TOP.bits() | Self::RIGHT.bits() | Self::BOTTOM.bits() | Self::LEFT.bits();
21 }
22}
23
24impl fmt::Debug for Borders {
28 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
32 if self.is_empty() {
33 return write!(f, "NONE");
34 }
35 if self.is_all() {
36 return write!(f, "ALL");
37 }
38 let mut first = true;
39 for (name, border) in self.iter_names() {
40 if border == Self::NONE {
41 continue;
42 }
43 if first {
44 write!(f, "{name}")?;
45 first = false;
46 } else {
47 write!(f, " | {name}")?;
48 }
49 }
50 Ok(())
51 }
52}
53
54#[cfg(feature = "macros")]
91#[macro_export]
92macro_rules! border {
93 () => {
94 Borders::NONE
95 };
96 ($b:ident) => {
97 Borders::$b
98 };
99 ($first:ident,$($other:ident),*) => {
100 Borders::$first
101 $(
102 .union(Borders::$other)
103 )*
104 };
105}
106
107#[cfg(test)]
108mod tests {
109 use super::*;
110
111 #[test]
112 fn test_borders_debug() {
113 assert_eq!(format!("{:?}", Borders::empty()), "NONE");
114 assert_eq!(format!("{:?}", Borders::NONE), "NONE");
115 assert_eq!(format!("{:?}", Borders::TOP), "TOP");
116 assert_eq!(format!("{:?}", Borders::BOTTOM), "BOTTOM");
117 assert_eq!(format!("{:?}", Borders::LEFT), "LEFT");
118 assert_eq!(format!("{:?}", Borders::RIGHT), "RIGHT");
119 assert_eq!(format!("{:?}", Borders::ALL), "ALL");
120 assert_eq!(format!("{:?}", Borders::all()), "ALL");
121
122 assert_eq!(
123 format!("{:?}", Borders::TOP | Borders::BOTTOM),
124 "TOP | BOTTOM"
125 );
126 }
127}
128
129#[cfg(all(test, feature = "macros"))]
130mod macro_tests {
131 use super::*;
132
133 #[test]
134 fn can_be_const() {
135 const NOTHING: Borders = border!();
136 const JUST_TOP: Borders = border!(TOP);
137 const TOP_BOTTOM: Borders = border!(TOP, BOTTOM);
138 const RIGHT_OPEN: Borders = border!(TOP, LEFT, BOTTOM);
139
140 assert_eq!(NOTHING, Borders::NONE);
141 assert_eq!(JUST_TOP, Borders::TOP);
142 assert_eq!(TOP_BOTTOM, Borders::TOP | Borders::BOTTOM);
143 assert_eq!(RIGHT_OPEN, Borders::TOP | Borders::LEFT | Borders::BOTTOM);
144 }
145
146 #[test]
147 fn border_empty() {
148 let empty = Borders::NONE;
149 assert_eq!(empty, border!());
150 }
151
152 #[test]
153 fn border_all() {
154 let all = Borders::ALL;
155 assert_eq!(all, border!(ALL));
156 assert_eq!(all, border!(TOP, BOTTOM, LEFT, RIGHT));
157 }
158
159 #[test]
160 fn border_left_right() {
161 let left_right = Borders::from_bits(Borders::LEFT.bits() | Borders::RIGHT.bits());
162 assert_eq!(left_right, Some(border!(RIGHT, LEFT)));
163 }
164}