From 14c67fbb52101d10b2d2e26898c408ab8dd3ec2d Mon Sep 17 00:00:00 2001 From: Jack Wills <32690432+mrjackwills@users.noreply.github.com> Date: Mon, 5 Feb 2024 19:59:19 +0000 Subject: [PATCH] fix(list): highlight symbol when using a multi-bytes char (#924) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ratatui v0.26.0 brought a regression in the List widget, in which the highlight symbol width was incorrectly calculated - specifically when the highlight symbol was a multi-char character, e.g. `▶`. --- src/widgets/list.rs | 2 +- tests/widgets_list.rs | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/src/widgets/list.rs b/src/widgets/list.rs index d7458a63..7adfa692 100755 --- a/src/widgets/list.rs +++ b/src/widgets/list.rs @@ -895,7 +895,7 @@ impl StatefulWidgetRef for List<'_> { let is_selected = state.selected.map_or(false, |s| s == i); let item_area = if selection_spacing { - let highlight_symbol_width = self.highlight_symbol.unwrap_or("").len() as u16; + let highlight_symbol_width = self.highlight_symbol.unwrap_or("").width() as u16; Rect { x: row_area.x + highlight_symbol_width, width: row_area.width - highlight_symbol_width, diff --git a/tests/widgets_list.rs b/tests/widgets_list.rs index 00429994..9f0ba27b 100644 --- a/tests/widgets_list.rs +++ b/tests/widgets_list.rs @@ -52,6 +52,38 @@ fn widgets_list_should_highlight_the_selected_item() { terminal.backend().assert_buffer(&expected); } +#[test] +fn widgets_list_should_highlight_the_selected_item_wide_symbol() { + let backend = TestBackend::new(10, 3); + let mut terminal = Terminal::new(backend).unwrap(); + let mut state = ListState::default(); + + let wide_symbol = "▶ "; + + state.select(Some(1)); + terminal + .draw(|f| { + let size = f.size(); + let items = vec![ + ListItem::new("Item 1"), + ListItem::new("Item 2"), + ListItem::new("Item 3"), + ]; + let list = List::new(items) + .highlight_style(Style::default().bg(Color::Yellow)) + .highlight_symbol(wide_symbol); + f.render_stateful_widget(list, size, &mut state); + }) + .unwrap(); + + let mut expected = Buffer::with_lines(vec![" Item 1 ", "▶ Item 2 ", " Item 3 "]); + + for x in 0..10 { + expected.get_mut(x, 1).set_bg(Color::Yellow); + } + terminal.backend().assert_buffer(&expected); +} + #[test] fn widgets_list_should_truncate_items() { let backend = TestBackend::new(10, 2);