diff --git a/Cargo.lock b/Cargo.lock index 0a1d8fd..7df21c5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -680,6 +680,7 @@ dependencies = [ "indoc", "itertools", "ratatui", + "unicode-width", ] [[package]] @@ -696,9 +697,9 @@ checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" [[package]] name = "unicode-width" -version = "0.1.11" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" +checksum = "68f5e5f3158ecfd4b8ff6fe086db7c8467a2dfdac97fe420f2b7c4aa97af66d6" [[package]] name = "utf8parse" diff --git a/Cargo.toml b/Cargo.toml index d46f17b..a4102fe 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,6 +15,7 @@ edition = "2021" crossterm = "0.27.0" itertools = "0.12.1" ratatui = "0.26.2" +unicode-width = "0.1.12" [dev-dependencies] clap = { version = "4.5.4", features = ["derive"] } diff --git a/src/text_prompt.rs b/src/text_prompt.rs index 77a2ddc..09f1a58 100644 --- a/src/text_prompt.rs +++ b/src/text_prompt.rs @@ -7,6 +7,7 @@ use ratatui::{ prelude::*, widgets::{Block, Paragraph, StatefulWidget, Widget}, }; +use unicode_width::UnicodeWidthStr; // TODO style the widget // TODO style each element of the widget. @@ -100,7 +101,7 @@ impl<'a> StatefulWidget for TextPrompt<'a> { " › ".cyan().dim(), Span::raw(value), ]); - let prompt_length = line.to_string().chars().count() - value_length; + let prompt_length = line.to_string().width() - value_length; let lines = wrap(line, width).take(height).collect_vec(); // constrain the position to the area @@ -247,6 +248,23 @@ mod tests { expected.set_style(Rect::new(2, 0, 6, 1), Style::new().bold()); expected.set_style(Rect::new(8, 0, 3, 1), Style::new().cyan().dim()); assert_buffer_eq!(buffer, expected); + assert_eq!(state.cursor(), (11, 0)); + } + + #[test] + fn render_emoji() { + let prompt = TextPrompt::from("🔍"); + let mut state = TextState::new(); + let mut buffer = Buffer::empty(Rect::new(0, 0, 11, 1)); + + prompt.render(buffer.area, &mut buffer, &mut state); + + let mut expected = Buffer::with_lines(vec!["? 🔍 › "]); + expected.set_style(Rect::new(0, 0, 1, 1), PENDING_STYLE); + expected.set_style(Rect::new(2, 0, 1, 1), Style::new().bold()); + expected.set_style(Rect::new(4, 0, 3, 1), Style::new().cyan().dim()); + assert_buffer_eq!(buffer, expected); + assert_eq!(state.cursor(), (7, 0)); } #[test]