wip

HactarCE and Conrad Irwin created

Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>

Change summary

crates/agent_ui/src/acp/message_editor.rs |  1 
crates/editor/src/editor.rs               |  2 
crates/editor/src/editor_tests.rs         | 53 ++++++++++++++++++++++++
crates/project/Cargo.toml                 |  2 
crates/project/src/project.rs             |  1 
crates/snippet_provider/Cargo.toml        |  3 +
crates/snippet_provider/src/lib.rs        | 14 ++++++
7 files changed, 74 insertions(+), 2 deletions(-)

Detailed changes

crates/editor/src/editor.rs šŸ”—

@@ -23009,7 +23009,7 @@ fn snippet_completions(
             });
         }
 
-        for snippets in scopes.into_iter() {
+        for (_scope, snippets) in scopes.into_iter() {
             // Sort snippets by word count to match longer snippet prefixes first.
             let mut sorted_snippet_candidates = snippets
                 .iter()

crates/editor/src/editor_tests.rs šŸ”—

@@ -11083,6 +11083,50 @@ async fn test_snippet_indentation(cx: &mut TestAppContext) {
         ˇ"});
 }
 
+#[gpui::test]
+async fn test_snippet_with_multi_word_prefix(cx: &mut TestAppContext) {
+    init_test(cx, |_| {});
+
+    let mut cx = EditorTestContext::new(cx).await;
+    cx.update_editor(|editor, window, cx| {
+        editor.project().unwrap().update(cx, |project, cx| {
+            project.snippets().update(cx, |snippets, cx| {
+                let snippet = project::snippet_provider::Snippet {
+                    prefix: "multi word".to_string(),
+                    body: "this is many words".to_string(),
+                    description: "description".to_string(),
+                    name: "multi-word snippet test".to_string(),
+                };
+                snippets.add_snippet_for_test(
+                    None,
+                    PathBuf::from("test_snippets.json"),
+                    vec![Arc::new(snippet)],
+                    cx,
+                );
+            });
+        })
+    });
+
+    cx.set_state("mˇ");
+    cx.simulate_input("u");
+
+    cx.update_editor(|editor, window, cx| {
+        let CodeContextMenu::Completions(context_menu) = editor.context_menu.borrow().unwrap()
+        else {
+            panic!("expected completion menu")
+        };
+        assert!(context_menu.visible());
+        let completions = context_menu;
+
+        assert!(
+            completions
+                .iter()
+                .any(|c| c.string.as_str() == "multi word"),
+            "Expected to find 'multi word' snippet in completions"
+        );
+    });
+}
+
 #[gpui::test]
 async fn test_document_format_during_save(cx: &mut TestAppContext) {
     init_test(cx, |_| {});
@@ -13584,7 +13628,14 @@ async fn test_completion_mode(cx: &mut TestAppContext) {
 
             cx.set_state(&run.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));

crates/project/Cargo.toml šŸ”—

@@ -18,6 +18,7 @@ test-support = [
     "client/test-support",
     "language/test-support",
     "settings/test-support",
+    "snippet_provider/test-support",
     "text/test-support",
     "prettier/test-support",
     "worktree/test-support",
@@ -109,6 +110,7 @@ pretty_assertions.workspace = true
 release_channel.workspace = true
 rpc = { workspace = true, features = ["test-support"] }
 settings = { workspace = true, features = ["test-support"] }
+snippet_provider = { workspace = true, features = ["test-support"] }
 unindent.workspace = true
 util = { workspace = true, features = ["test-support"] }
 worktree = { workspace = true, features = ["test-support"] }

crates/project/src/project.rs šŸ”—

@@ -105,6 +105,7 @@ use search_history::SearchHistory;
 use settings::{InvalidSettingsError, Settings, SettingsLocation, SettingsStore};
 use smol::channel::Receiver;
 use snippet::Snippet;
+pub use snippet_provider;
 use snippet_provider::SnippetProvider;
 use std::{
     borrow::Cow,

crates/snippet_provider/Cargo.toml šŸ”—

@@ -8,6 +8,9 @@ license = "GPL-3.0-or-later"
 [lints]
 workspace = true
 
+[features]
+test-support = []
+
 [dependencies]
 anyhow.workspace = true
 collections.workspace = true

crates/snippet_provider/src/lib.rs šŸ”—

@@ -235,6 +235,20 @@ impl SnippetProvider {
         user_snippets
     }
 
+    #[cfg(any(test, feature = "test-support"))]
+    pub fn add_snippet_for_test(
+        &mut self,
+        language: SnippetKind,
+        path: PathBuf,
+        snippet: Vec<Arc<Snippet>>,
+        cx: &mut Context<Self>,
+    ) {
+        self.snippets
+            .entry(language)
+            .or_default()
+            .insert(path, snippet);
+    }
+
     pub fn snippets_for(&self, language: SnippetKind, cx: &App) -> Vec<Arc<Snippet>> {
         let mut requested_snippets = self.lookup_snippets::<true>(&language, cx);