mirror of
https://github.com/ratatui/ratatui.git
synced 2025-09-28 13:31:14 +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[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);
|
||||
// render the second part with the bar_style
|
||||
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 style = bar_style.patch(self.style);
|
||||
|
Loading…
x
Reference in New Issue
Block a user