mirror of
https://github.com/ratatui/ratatui.git
synced 2025-10-02 07:21:24 +00:00
feat: preserve block titles when merging borders (#1977)
Resolves #1939
This commit is contained in:
parent
821611f76f
commit
017af11b2b
@ -300,15 +300,20 @@ impl MergeStrategy {
|
|||||||
/// [Box Drawing Unicode block]: https://en.wikipedia.org/wiki/Box_Drawing
|
/// [Box Drawing Unicode block]: https://en.wikipedia.org/wiki/Box_Drawing
|
||||||
/// [`Cell::merge_symbol`]: crate::buffer::Cell::merge_symbol
|
/// [`Cell::merge_symbol`]: crate::buffer::Cell::merge_symbol
|
||||||
pub fn merge<'a>(self, prev: &'a str, next: &'a str) -> &'a str {
|
pub fn merge<'a>(self, prev: &'a str, next: &'a str) -> &'a str {
|
||||||
let (Ok(prev_symbol), Ok(next_symbol)) =
|
// Replace should always just return the last symbol.
|
||||||
(BorderSymbol::from_str(prev), BorderSymbol::from_str(next))
|
if self == Self::Replace {
|
||||||
else {
|
|
||||||
return next;
|
return next;
|
||||||
};
|
|
||||||
if let Ok(merged) = prev_symbol.merge(next_symbol, self).try_into() {
|
|
||||||
return merged;
|
|
||||||
}
|
}
|
||||||
next
|
|
||||||
|
match (BorderSymbol::from_str(prev), BorderSymbol::from_str(next)) {
|
||||||
|
(Ok(prev_symbol), Ok(next_symbol)) => prev_symbol
|
||||||
|
.merge(next_symbol, self)
|
||||||
|
.try_into()
|
||||||
|
.unwrap_or(next),
|
||||||
|
// Non-border symbols take precedence in strategies other than Replace.
|
||||||
|
(Err(_), Ok(_)) => prev,
|
||||||
|
(_, Err(_)) => next,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -523,7 +528,6 @@ macro_rules! define_symbols {
|
|||||||
}
|
}
|
||||||
|
|
||||||
define_symbols!(
|
define_symbols!(
|
||||||
" " => (Nothing, Nothing, Nothing, Nothing),
|
|
||||||
"─" => (Plain, Nothing, Plain, Nothing),
|
"─" => (Plain, Nothing, Plain, Nothing),
|
||||||
"━" => (Thick, Nothing, Thick, Nothing),
|
"━" => (Thick, Nothing, Thick, Nothing),
|
||||||
"│" => (Nothing, Plain, Nothing, Plain),
|
"│" => (Nothing, Plain, Nothing, Plain),
|
||||||
@ -666,7 +670,7 @@ mod tests {
|
|||||||
"╄", "╅", "╆", "╇", "╈", "╉", "╊", "╋", "╌", "╍", "╎", "╏", "═", "║", "╒", "╓", "╔",
|
"╄", "╅", "╆", "╇", "╈", "╉", "╊", "╋", "╌", "╍", "╎", "╏", "═", "║", "╒", "╓", "╔",
|
||||||
"╕", "╖", "╗", "╘", "╙", "╚", "╛", "╜", "╝", "╞", "╟", "╠", "╡", "╢", "╣", "╤", "╥",
|
"╕", "╖", "╗", "╘", "╙", "╚", "╛", "╜", "╝", "╞", "╟", "╠", "╡", "╢", "╣", "╤", "╥",
|
||||||
"╦", "╧", "╨", "╩", "╪", "╫", "╬", "╭", "╮", "╯", "╰", "╴", "╵", "╶", "╷", "╸", "╹",
|
"╦", "╧", "╨", "╩", "╪", "╫", "╬", "╭", "╮", "╯", "╰", "╴", "╵", "╶", "╷", "╸", "╹",
|
||||||
"╺", "╻", "╼", "╽", "╾", "╿", " ",
|
"╺", "╻", "╼", "╽", "╾", "╿", " ", "a", "b",
|
||||||
];
|
];
|
||||||
|
|
||||||
for a in symbols {
|
for a in symbols {
|
||||||
@ -695,8 +699,8 @@ mod tests {
|
|||||||
assert_eq!(strategy.merge("┵", "┝"), "┿");
|
assert_eq!(strategy.merge("┵", "┝"), "┿");
|
||||||
assert_eq!(strategy.merge("│", "━"), "┿");
|
assert_eq!(strategy.merge("│", "━"), "┿");
|
||||||
assert_eq!(strategy.merge("┵", "╞"), "╞");
|
assert_eq!(strategy.merge("┵", "╞"), "╞");
|
||||||
assert_eq!(strategy.merge(" ", "╠"), "╠");
|
assert_eq!(strategy.merge(" ", "╠"), " ");
|
||||||
assert_eq!(strategy.merge("╠", " "), "╠");
|
assert_eq!(strategy.merge("╠", " "), " ");
|
||||||
assert_eq!(strategy.merge("╎", "╧"), "╧");
|
assert_eq!(strategy.merge("╎", "╧"), "╧");
|
||||||
assert_eq!(strategy.merge("╛", "╒"), "╪");
|
assert_eq!(strategy.merge("╛", "╒"), "╪");
|
||||||
assert_eq!(strategy.merge("│", "═"), "╪");
|
assert_eq!(strategy.merge("│", "═"), "╪");
|
||||||
@ -704,6 +708,9 @@ mod tests {
|
|||||||
assert_eq!(strategy.merge("╡", "╞"), "╪");
|
assert_eq!(strategy.merge("╡", "╞"), "╪");
|
||||||
assert_eq!(strategy.merge("┌", "╭"), "╭");
|
assert_eq!(strategy.merge("┌", "╭"), "╭");
|
||||||
assert_eq!(strategy.merge("┘", "╭"), "╭");
|
assert_eq!(strategy.merge("┘", "╭"), "╭");
|
||||||
|
assert_eq!(strategy.merge("┌", "a"), "a");
|
||||||
|
assert_eq!(strategy.merge("a", "╭"), "a");
|
||||||
|
assert_eq!(strategy.merge("a", "b"), "b");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -711,7 +718,7 @@ mod tests {
|
|||||||
let strategy = MergeStrategy::Fuzzy;
|
let strategy = MergeStrategy::Fuzzy;
|
||||||
assert_eq!(strategy.merge("┄", "╴"), "─");
|
assert_eq!(strategy.merge("┄", "╴"), "─");
|
||||||
assert_eq!(strategy.merge("│", "┆"), "┆");
|
assert_eq!(strategy.merge("│", "┆"), "┆");
|
||||||
assert_eq!(strategy.merge(" ", "┉"), "┉");
|
assert_eq!(strategy.merge(" ", "┉"), " ");
|
||||||
assert_eq!(strategy.merge("┋", "┋"), "┋");
|
assert_eq!(strategy.merge("┋", "┋"), "┋");
|
||||||
assert_eq!(strategy.merge("╷", "╶"), "┌");
|
assert_eq!(strategy.merge("╷", "╶"), "┌");
|
||||||
assert_eq!(strategy.merge("╭", "┌"), "┌");
|
assert_eq!(strategy.merge("╭", "┌"), "┌");
|
||||||
@ -725,8 +732,8 @@ mod tests {
|
|||||||
assert_eq!(strategy.merge("┘", "┌"), "┼");
|
assert_eq!(strategy.merge("┘", "┌"), "┼");
|
||||||
assert_eq!(strategy.merge("┘", "╭"), "┼");
|
assert_eq!(strategy.merge("┘", "╭"), "┼");
|
||||||
assert_eq!(strategy.merge("╎", "┉"), "┿");
|
assert_eq!(strategy.merge("╎", "┉"), "┿");
|
||||||
assert_eq!(strategy.merge(" ", "╠"), "╠");
|
assert_eq!(strategy.merge(" ", "╠"), " ");
|
||||||
assert_eq!(strategy.merge("╠", " "), "╠");
|
assert_eq!(strategy.merge("╠", " "), " ");
|
||||||
assert_eq!(strategy.merge("┵", "╞"), "╪");
|
assert_eq!(strategy.merge("┵", "╞"), "╪");
|
||||||
assert_eq!(strategy.merge("╛", "╒"), "╪");
|
assert_eq!(strategy.merge("╛", "╒"), "╪");
|
||||||
assert_eq!(strategy.merge("│", "═"), "╪");
|
assert_eq!(strategy.merge("│", "═"), "╪");
|
||||||
@ -734,5 +741,8 @@ mod tests {
|
|||||||
assert_eq!(strategy.merge("╡", "╞"), "╪");
|
assert_eq!(strategy.merge("╡", "╞"), "╪");
|
||||||
assert_eq!(strategy.merge("╎", "╧"), "╪");
|
assert_eq!(strategy.merge("╎", "╧"), "╪");
|
||||||
assert_eq!(strategy.merge("┌", "╭"), "╭");
|
assert_eq!(strategy.merge("┌", "╭"), "╭");
|
||||||
|
assert_eq!(strategy.merge("┌", "a"), "a");
|
||||||
|
assert_eq!(strategy.merge("a", "╭"), "a");
|
||||||
|
assert_eq!(strategy.merge("a", "b"), "b");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1969,6 +1969,82 @@ mod tests {
|
|||||||
pretty_assertions::assert_eq!(Buffer::with_lines(expected.lines()), buffer);
|
pretty_assertions::assert_eq!(Buffer::with_lines(expected.lines()), buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
#[case::replace(MergeStrategy::Replace, Buffer::with_lines([
|
||||||
|
"┏block top━━┓",
|
||||||
|
"┃ ┃",
|
||||||
|
"┗━━━━━━━━━━━┛",
|
||||||
|
"│ │",
|
||||||
|
"└───────────┘",
|
||||||
|
])
|
||||||
|
)]
|
||||||
|
#[case::replace(MergeStrategy::Exact, Buffer::with_lines([
|
||||||
|
"┏block top━━┓",
|
||||||
|
"┃ ┃",
|
||||||
|
"┡block btm━━┩",
|
||||||
|
"│ │",
|
||||||
|
"└───────────┘",
|
||||||
|
])
|
||||||
|
)]
|
||||||
|
#[case::replace(MergeStrategy::Fuzzy, Buffer::with_lines([
|
||||||
|
"┏block top━━┓",
|
||||||
|
"┃ ┃",
|
||||||
|
"┡block btm━━┩",
|
||||||
|
"│ │",
|
||||||
|
"└───────────┘",
|
||||||
|
])
|
||||||
|
)]
|
||||||
|
fn merged_titles_bottom_first(#[case] strategy: MergeStrategy, #[case] expected: Buffer) {
|
||||||
|
let mut buffer = Buffer::empty(Rect::new(0, 0, 13, 5));
|
||||||
|
Block::bordered()
|
||||||
|
.title("block btm")
|
||||||
|
.render(Rect::new(0, 2, 13, 3), &mut buffer);
|
||||||
|
Block::bordered()
|
||||||
|
.title("block top")
|
||||||
|
.border_type(BorderType::Thick)
|
||||||
|
.merge_borders(strategy)
|
||||||
|
.render(Rect::new(0, 0, 13, 3), &mut buffer);
|
||||||
|
assert_eq!(buffer, expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
#[case::replace(MergeStrategy::Replace, Buffer::with_lines([
|
||||||
|
"┏block top━━┓",
|
||||||
|
"┃ ┃",
|
||||||
|
"┌block btm──┐",
|
||||||
|
"│ │",
|
||||||
|
"└───────────┘",
|
||||||
|
])
|
||||||
|
)]
|
||||||
|
#[case::replace(MergeStrategy::Exact, Buffer::with_lines([
|
||||||
|
"┏block top━━┓",
|
||||||
|
"┃ ┃",
|
||||||
|
"┞block btm──┦",
|
||||||
|
"│ │",
|
||||||
|
"└───────────┘",
|
||||||
|
])
|
||||||
|
)]
|
||||||
|
#[case::replace(MergeStrategy::Fuzzy, Buffer::with_lines([
|
||||||
|
"┏block top━━┓",
|
||||||
|
"┃ ┃",
|
||||||
|
"┞block btm──┦",
|
||||||
|
"│ │",
|
||||||
|
"└───────────┘",
|
||||||
|
])
|
||||||
|
)]
|
||||||
|
fn merged_titles_top_first(#[case] strategy: MergeStrategy, #[case] expected: Buffer) {
|
||||||
|
let mut buffer = Buffer::empty(Rect::new(0, 0, 13, 5));
|
||||||
|
Block::bordered()
|
||||||
|
.title("block top")
|
||||||
|
.border_type(BorderType::Thick)
|
||||||
|
.render(Rect::new(0, 0, 13, 3), &mut buffer);
|
||||||
|
Block::bordered()
|
||||||
|
.title("block btm")
|
||||||
|
.merge_borders(strategy)
|
||||||
|
.render(Rect::new(0, 2, 13, 3), &mut buffer);
|
||||||
|
assert_eq!(buffer, expected);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn left_titles() {
|
fn left_titles() {
|
||||||
let mut buffer = Buffer::empty(Rect::new(0, 0, 10, 1));
|
let mut buffer = Buffer::empty(Rect::new(0, 0, 10, 1));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user