From 994dbedd7b6736b2d0d10652c14adf0cd64c7629 Mon Sep 17 00:00:00 2001 From: blindfs Date: Wed, 12 Mar 2025 10:41:19 +0800 Subject: [PATCH 1/3] fix: columnar_menu create_string with quoted suggestions --- src/menu/columnar_menu.rs | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/src/menu/columnar_menu.rs b/src/menu/columnar_menu.rs index 4de25ee5..7558d92d 100644 --- a/src/menu/columnar_menu.rs +++ b/src/menu/columnar_menu.rs @@ -299,10 +299,21 @@ impl ColumnarMenu { use_ansi_coloring: bool, ) -> String { if use_ansi_coloring { - let match_len = self.working_details.shortest_base_string.len(); + // strip quotes + let is_quote = |c: char| "`'\"".contains(c); + let shortest_base = &self.working_details.shortest_base_string; + let shortest_base = shortest_base + .strip_prefix(is_quote) + .unwrap_or(shortest_base); + let match_len = shortest_base.len(); // Split string so the match text can be styled - let (match_str, remaining_str) = suggestion.value.split_at(match_len); + let skip_len = suggestion + .value + .chars() + .take_while(|c| is_quote(*c)) + .count(); + let (match_str, remaining_str) = suggestion.value.split_at(match_len + skip_len); let suggestion_style_prefix = suggestion .style @@ -773,4 +784,19 @@ mod tests { "cursor should be at the end after completion" ); } + + #[test] + fn test_menu_create_string() { + // https://github.com/nushell/nushell/issues/13951 + let mut completer = FakeCompleter::new(&["おはよう", "`おはよう(`"]); + let mut menu = ColumnarMenu::default().with_name("testmenu"); + let mut editor = Editor::default(); + + editor.set_buffer("おは".to_string(), UndoBehavior::CreateUndoPoint); + + menu.update_values(&mut editor, &mut completer); + + // After replacing the editor, make sure insertion_point is at the right spot + assert!(menu.menu_string(2, true).contains("`おは")); + } } From 908b03075564540ed16010044babaff5dcbe4914 Mon Sep 17 00:00:00 2001 From: blindfs Date: Wed, 12 Mar 2025 10:53:33 +0800 Subject: [PATCH 2/3] cleanup --- src/menu/columnar_menu.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/menu/columnar_menu.rs b/src/menu/columnar_menu.rs index 7558d92d..949b98cb 100644 --- a/src/menu/columnar_menu.rs +++ b/src/menu/columnar_menu.rs @@ -793,10 +793,7 @@ mod tests { let mut editor = Editor::default(); editor.set_buffer("おは".to_string(), UndoBehavior::CreateUndoPoint); - menu.update_values(&mut editor, &mut completer); - - // After replacing the editor, make sure insertion_point is at the right spot assert!(menu.menu_string(2, true).contains("`おは")); } } From b80acac43f4ed8722a840647ec35698494ae11b1 Mon Sep 17 00:00:00 2001 From: blindfs Date: Wed, 12 Mar 2025 12:21:34 +0800 Subject: [PATCH 3/3] fix: same for the ide_menu --- src/menu/columnar_menu.rs | 4 +++- src/menu/ide_menu.rs | 39 +++++++++++++++++++++++++++++++++------ 2 files changed, 36 insertions(+), 7 deletions(-) diff --git a/src/menu/columnar_menu.rs b/src/menu/columnar_menu.rs index 949b98cb..ee357aa3 100644 --- a/src/menu/columnar_menu.rs +++ b/src/menu/columnar_menu.rs @@ -313,7 +313,9 @@ impl ColumnarMenu { .chars() .take_while(|c| is_quote(*c)) .count(); - let (match_str, remaining_str) = suggestion.value.split_at(match_len + skip_len); + let (match_str, remaining_str) = suggestion + .value + .split_at((match_len + skip_len).min(suggestion.value.len())); let suggestion_style_prefix = suggestion .style diff --git a/src/menu/ide_menu.rs b/src/menu/ide_menu.rs index 2c11fa32..0e8c03bc 100644 --- a/src/menu/ide_menu.rs +++ b/src/menu/ide_menu.rs @@ -512,14 +512,18 @@ impl IdeMenu { }; if use_ansi_coloring { - let match_len = self - .working_details - .shortest_base_string - .len() - .min(string.len()); + // strip quotes + let is_quote = |c: char| "`'\"".contains(c); + let shortest_base = &self.working_details.shortest_base_string; + let shortest_base = shortest_base + .strip_prefix(is_quote) + .unwrap_or(shortest_base); + let match_len = shortest_base.len().min(string.len()); // Split string so the match text can be styled - let (match_str, remaining_str) = string.split_at(match_len); + let skip_len = string.chars().take_while(|c| is_quote(*c)).count(); + let (match_str, remaining_str) = + string.split_at((match_len + skip_len).min(string.len())); let suggestion_style_prefix = suggestion .style @@ -1441,4 +1445,27 @@ mod tests { menu.menu_string(500, true); } + + #[test] + fn test_menu_create_value_string() { + // https://github.com/nushell/nushell/issues/13951 + let mut completer = FakeCompleter::new(&["おはよう", "`おはよう(`"]); + let mut menu = IdeMenu::default().with_name("testmenu"); + menu.working_details = IdeMenuDetails { + cursor_col: 50, + menu_width: 50, + completion_width: 50, + description_width: 50, + description_is_right: true, + space_left: 50, + space_right: 50, + description_offset: 50, + shortest_base_string: String::new(), + }; + let mut editor = Editor::default(); + + editor.set_buffer("おは".to_string(), UndoBehavior::CreateUndoPoint); + menu.update_values(&mut editor, &mut completer); + assert!(menu.menu_string(2, true).contains("`おは")); + } }