mirror of
https://github.com/ratatui/ratatui.git
synced 2025-10-02 07:21:24 +00:00
fix: fix handling of multi-byte chars in bar chart (#1934)
The split_at method requires that the split point is at a valid utf8 character boundary. Fixes: https://github.com/ratatui/ratatui/issues/1928
This commit is contained in:
parent
ca2ad4a1f9
commit
21e3b598ce
@ -1441,4 +1441,35 @@ mod tests {
|
|||||||
assert_eq!(updated_chart.data.len(), 2);
|
assert_eq!(updated_chart.data.len(), 2);
|
||||||
assert_eq!(updated_chart.data[1].bars, [Bar::with_label("Blue", 3)]);
|
assert_eq!(updated_chart.data[1].bars, [Bar::with_label("Blue", 3)]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Regression test for issue <https://github.com/ratatui/ratatui/issues/1928>
|
||||||
|
///
|
||||||
|
/// This test ensures that the `BarChart` doesn't panic when rendering text labels with
|
||||||
|
/// multi-byte characters in the bar labels.
|
||||||
|
#[test]
|
||||||
|
fn regression_1928() {
|
||||||
|
let text_value = "\u{202f}"; // Narrow No-Break Space
|
||||||
|
let bars = [
|
||||||
|
Bar::default().text_value(text_value).value(0),
|
||||||
|
Bar::default().text_value(text_value).value(1),
|
||||||
|
Bar::default().text_value(text_value).value(2),
|
||||||
|
Bar::default().text_value(text_value).value(3),
|
||||||
|
Bar::default().text_value(text_value).value(4),
|
||||||
|
];
|
||||||
|
let chart = BarChart::default()
|
||||||
|
.data(BarGroup::default().bars(&bars))
|
||||||
|
.bar_gap(0)
|
||||||
|
.direction(Direction::Horizontal);
|
||||||
|
let mut buffer = Buffer::empty(Rect::new(0, 0, 4, 5));
|
||||||
|
chart.render(buffer.area, &mut buffer);
|
||||||
|
#[rustfmt::skip]
|
||||||
|
let expected = Buffer::with_lines([
|
||||||
|
"\u{202f} ",
|
||||||
|
"\u{202f} ",
|
||||||
|
"\u{202f}█ ",
|
||||||
|
"\u{202f}██ ",
|
||||||
|
"\u{202f}███",
|
||||||
|
]);
|
||||||
|
assert_eq!(buffer, expected);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -216,6 +216,13 @@ impl<'a> Bar<'a> {
|
|||||||
buf.set_stringn(area.x, area.y, text, bar_length, style);
|
buf.set_stringn(area.x, area.y, text, bar_length, style);
|
||||||
// render the second part with the bar_style
|
// render the second part with the bar_style
|
||||||
if text.len() > bar_length {
|
if text.len() > bar_length {
|
||||||
|
// Find the last character boundary at or before bar_length
|
||||||
|
let bar_length = text
|
||||||
|
.char_indices()
|
||||||
|
.take_while(|(i, _)| *i < bar_length)
|
||||||
|
.last()
|
||||||
|
.map_or(0, |(i, c)| i + c.len_utf8());
|
||||||
|
|
||||||
let (first, second) = text.split_at(bar_length);
|
let (first, second) = text.split_at(bar_length);
|
||||||
|
|
||||||
let style = bar_style.patch(self.style);
|
let style = bar_style.patch(self.style);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user