From 6fe955e8052efc685b27b39b486a5edfbc0cc776 Mon Sep 17 00:00:00 2001 From: HactarCE <6060305+HactarCE@users.noreply.github.com> Date: Fri, 17 Oct 2025 11:52:37 -0400 Subject: [PATCH] Add `snippets_only` to `ShowCompletions` Co-authored by: Conrad Irwin --- crates/editor/src/editor.rs | 28 +++---- crates/editor/src/editor_tests.rs | 118 ++++++++++++++++++++++++++---- 2 files changed, 115 insertions(+), 31 deletions(-) diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index ca25124a11ef2742ac3b1db39f5cf8591f8a5a83..635207de1a630c895e7bd12898356a353ca14c50 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -23009,14 +23009,8 @@ fn snippet_completions( }); } - for (scope, snippets) in scopes.into_iter() { - let max_snippet_words = snippets - .iter() - .flat_map(|snippet| &snippet.prefix) - .map(|prefix| snippet_match_points(prefix).count()) - .max() - .unwrap_or(0); - + for snippets in scopes.into_iter() { + // Sort snippets by word count to match longer snippet prefixes first. let mut sorted_snippet_candidates = snippets .iter() .enumerate() @@ -23029,23 +23023,21 @@ fn snippet_completions( ( (snippet_ix, prefix_ix), prefix, - snippet_match_points(prefix).count(), + snippet_candidate_suffixes(prefix).count(), ) }) }) .collect_vec(); - - // Match longer snippets first sorted_snippet_candidates - .sort_unstable_by_key(|(_, _, match_points)| usize::MAX - *match_points); + .sort_unstable_by_key(|(_, _, word_count)| Reverse(*word_count)); // One snippet may be matched multiple times, but each prefix may only be matched once. let mut sorted_snippet_candidates_seen = HashSet::::default(); - let buffer_windows = snippet_match_points(&max_buffer_window) + let buffer_windows = snippet_candidate_suffixes(&max_buffer_window) .take( sorted_snippet_candidates .last() - .map(|(_, _, match_points)| *match_points) + .map(|(_, _, word_count)| *word_count) .unwrap_or_default(), ) .collect_vec(); @@ -23114,7 +23106,7 @@ fn snippet_completions( .map(|string_match| (string_match, buffer_window.len())), ); - if matches.len() == MAX_RESULTS { + if matches.len() >= MAX_RESULTS { break; } } @@ -23129,8 +23121,8 @@ fn snippet_completions( is_incomplete = true; } - // TODO: ok to match the same snippet multiple times with different prefixes? (probably yes) - // TODO: ok to match the same prefix multiple times with different start points? (probably no) + // TODO! ok to match the same snippet multiple times with different prefixes? (probably yes) + // TODO! ok to match the same prefix multiple times with different start points? (probably no) completions.extend( matches @@ -24458,7 +24450,7 @@ pub(crate) fn split_words(text: &str) -> impl std::iter::Iterator + /// strings a snippet could match to. More precisely: returns an iterator over /// suffixes of `text` created by splitting at word boundaries (for a particular /// definition of "word"). -pub(crate) fn snippet_match_points(text: &str) -> impl std::iter::Iterator { +pub(crate) fn snippet_candidate_suffixes(text: &str) -> impl std::iter::Iterator { let mut prev_index = 0; let mut prev_codepoint: Option = None; let is_word_char = |c: char| c.is_alphanumeric() || c == '_'; diff --git a/crates/editor/src/editor_tests.rs b/crates/editor/src/editor_tests.rs index 30f092ff0db80dd9295b2c636dabfee1cf138d9c..fcc05dbbc36dc275a8a01eea00bdcdf81869b872 100644 --- a/crates/editor/src/editor_tests.rs +++ b/crates/editor/src/editor_tests.rs @@ -13644,7 +13644,14 @@ async fn test_completion_with_mode_specified_by_action(cx: &mut TestAppContext) cx.set_state(initial_state); cx.update_editor(|editor, window, cx| { - editor.show_completions(&ShowCompletions { trigger: None }, window, cx); + editor.show_completions( + &ShowCompletions { + trigger: None, + snippets_only: false, + }, + window, + cx, + ); }); let counter = Arc::new(AtomicUsize::new(0)); @@ -13680,7 +13687,14 @@ async fn test_completion_with_mode_specified_by_action(cx: &mut TestAppContext) cx.set_state(initial_state); cx.update_editor(|editor, window, cx| { - editor.show_completions(&ShowCompletions { trigger: None }, window, cx); + editor.show_completions( + &ShowCompletions { + trigger: None, + snippets_only: false, + }, + window, + cx, + ); }); handle_completion_request_with_insert_and_replace( &mut cx, @@ -13767,7 +13781,14 @@ async fn test_completion_replacing_surrounding_text_with_multicursors(cx: &mut T "}; cx.set_state(initial_state); cx.update_editor(|editor, window, cx| { - editor.show_completions(&ShowCompletions { trigger: None }, window, cx); + editor.show_completions( + &ShowCompletions { + trigger: None, + snippets_only: false, + }, + window, + cx, + ); }); handle_completion_request_with_insert_and_replace( &mut cx, @@ -13821,7 +13842,14 @@ async fn test_completion_replacing_surrounding_text_with_multicursors(cx: &mut T "}; cx.set_state(initial_state); cx.update_editor(|editor, window, cx| { - editor.show_completions(&ShowCompletions { trigger: None }, window, cx); + editor.show_completions( + &ShowCompletions { + trigger: None, + snippets_only: false, + }, + window, + cx, + ); }); handle_completion_request_with_insert_and_replace( &mut cx, @@ -13870,7 +13898,14 @@ async fn test_completion_replacing_surrounding_text_with_multicursors(cx: &mut T "}; cx.set_state(initial_state); cx.update_editor(|editor, window, cx| { - editor.show_completions(&ShowCompletions { trigger: None }, window, cx); + editor.show_completions( + &ShowCompletions { + trigger: None, + snippets_only: false, + }, + window, + cx, + ); }); handle_completion_request_with_insert_and_replace( &mut cx, @@ -14021,7 +14056,14 @@ async fn test_completion_in_multibuffer_with_replace_range(cx: &mut TestAppConte }); editor.update_in(cx, |editor, window, cx| { - editor.show_completions(&ShowCompletions { trigger: None }, window, cx); + editor.show_completions( + &ShowCompletions { + trigger: None, + snippets_only: false, + }, + window, + cx, + ); }); fake_server @@ -14260,7 +14302,14 @@ async fn test_completion(cx: &mut TestAppContext) { cx.assert_editor_state("editor.cloˇ"); assert!(cx.editor(|e, _, _| e.context_menu.borrow_mut().is_none())); cx.update_editor(|editor, window, cx| { - editor.show_completions(&ShowCompletions { trigger: None }, window, cx); + editor.show_completions( + &ShowCompletions { + trigger: None, + snippets_only: false, + }, + window, + cx, + ); }); handle_completion_request( "editor.", @@ -15112,6 +15161,7 @@ async fn test_as_is_completions(cx: &mut TestAppContext) { editor.show_completions( &ShowCompletions { trigger: Some("\n".into()), + snippets_only: false, }, window, cx, @@ -15213,7 +15263,14 @@ int fn_branch(bool do_branch1, bool do_branch2); }))) }); cx.update_editor(|editor, window, cx| { - editor.show_completions(&ShowCompletions { trigger: None }, window, cx); + editor.show_completions( + &ShowCompletions { + trigger: None, + snippets_only: false, + }, + window, + cx, + ); }); cx.executor().run_until_parked(); cx.update_editor(|editor, window, cx| { @@ -15262,7 +15319,14 @@ int fn_branch(bool do_branch1, bool do_branch2); }))) }); cx.update_editor(|editor, window, cx| { - editor.show_completions(&ShowCompletions { trigger: None }, window, cx); + editor.show_completions( + &ShowCompletions { + trigger: None, + snippets_only: false, + }, + window, + cx, + ); }); cx.executor().run_until_parked(); cx.update_editor(|editor, window, cx| { @@ -17001,7 +17065,7 @@ fn test_split_words() { #[test] fn test_split_words_for_snippet_prefix() { fn split(text: &str) -> Vec<&str> { - snippet_match_points(text).collect() + snippet_candidate_suffixes(text).collect() } assert_eq!(split("HelloWorld"), &["HelloWorld"]); @@ -17013,7 +17077,21 @@ fn test_split_words_for_snippet_prefix() { assert_eq!( split("this@is!@#$^many . symbols"), &[ - "this", "@", "is", "!", "@", "#", "$", "^", "many", " ", " ", " ", ".", " ", "symbols" + "this@is!@#$^many . symbols", + "@is!@#$^many . symbols", + "is!@#$^many . symbols", + "!@#$^many . symbols", + "@#$^many . symbols", + "#$^many . symbols", + "$^many . symbols", + "^many . symbols", + "many . symbols", + " . symbols", + " . symbols", + " . symbols", + ". symbols", + " symbols", + "symbols" ], ); } @@ -17754,7 +17832,14 @@ async fn test_context_menus_hide_hover_popover(cx: &mut gpui::TestAppContext) { } }); cx.update_editor(|editor, window, cx| { - editor.show_completions(&ShowCompletions { trigger: None }, window, cx); + editor.show_completions( + &ShowCompletions { + trigger: None, + snippets_only: false, + }, + window, + cx, + ); }); completion_requests.next().await; cx.condition(|editor, _| editor.context_menu_visible()) @@ -24150,7 +24235,14 @@ async fn test_html_linked_edits_on_completion(cx: &mut TestAppContext) { ]))) }); editor.update_in(cx, |editor, window, cx| { - editor.show_completions(&ShowCompletions { trigger: None }, window, cx); + editor.show_completions( + &ShowCompletions { + trigger: None, + snippets_only: false, + }, + window, + cx, + ); }); cx.run_until_parked(); completion_handle.next().await.unwrap();