Vim z 2819 (#2875)

Conrad Irwin created

Add `$` and `#` and a smoke test for vim-mode respecting the
configuration.

Change summary

crates/editor/src/multi_buffer.rs                 |  9 ++---
crates/editor/src/test/editor_lsp_test_context.rs |  5 +++
crates/vim/src/test.rs                            | 26 +++++++++++++++++
crates/vim/src/test/vim_test_context.rs           | 12 +++++++
crates/zed/src/languages/javascript/config.toml   |  1 
crates/zed/src/languages/tsx/config.toml          |  1 
crates/zed/src/languages/typescript/config.toml   |  1 
7 files changed, 49 insertions(+), 6 deletions(-)

Detailed changes

crates/editor/src/multi_buffer.rs 🔗

@@ -1346,10 +1346,7 @@ impl MultiBuffer {
             .map(|state| state.buffer.clone())
     }
 
-    pub fn is_completion_trigger<T>(&self, position: T, text: &str, cx: &AppContext) -> bool
-    where
-        T: ToOffset,
-    {
+    pub fn is_completion_trigger(&self, position: Anchor, text: &str, cx: &AppContext) -> bool {
         let mut chars = text.chars();
         let char = if let Some(char) = chars.next() {
             char
@@ -1360,7 +1357,9 @@ impl MultiBuffer {
             return false;
         }
 
-        if char.is_alphanumeric() || char == '_' {
+        let language = self.language_at(position.clone(), cx);
+
+        if char_kind(language.as_ref(), char) == CharKind::Word {
             return true;
         }
 

crates/editor/src/test/editor_lsp_test_context.rs 🔗

@@ -6,6 +6,7 @@ use std::{
 
 use anyhow::Result;
 
+use collections::HashSet;
 use futures::Future;
 use gpui::{json, ViewContext, ViewHandle};
 use indoc::indoc;
@@ -154,10 +155,14 @@ impl<'a> EditorLspTestContext<'a> {
         capabilities: lsp::ServerCapabilities,
         cx: &'a mut gpui::TestAppContext,
     ) -> EditorLspTestContext<'a> {
+        let mut word_characters: HashSet<char> = Default::default();
+        word_characters.insert('$');
+        word_characters.insert('#');
         let language = Language::new(
             LanguageConfig {
                 name: "Typescript".into(),
                 path_suffixes: vec!["ts".to_string()],
+                word_characters,
                 ..Default::default()
             },
             Some(tree_sitter_typescript::language_typescript()),

crates/vim/src/test.rs 🔗

@@ -261,3 +261,29 @@ async fn test_status_indicator(
         assert!(mode_indicator.read(cx).mode.is_some());
     });
 }
+
+#[gpui::test]
+async fn test_word_characters(cx: &mut gpui::TestAppContext) {
+    let mut cx = VimTestContext::new_typescript(cx).await;
+    cx.set_state(
+        indoc! { "
+        class A {
+            #ˇgoop = 99;
+            $ˇgoop () { return this.#gˇoop };
+        };
+        console.log(new A().$gooˇp())
+    "},
+        Mode::Normal,
+    );
+    cx.simulate_keystrokes(["v", "i", "w"]);
+    cx.assert_state(
+        indoc! {"
+        class A {
+            «#goopˇ» = 99;
+            «$goopˇ» () { return this.«#goopˇ» };
+        };
+        console.log(new A().«$goopˇ»())
+    "},
+        Mode::Visual,
+    )
+}

crates/vim/src/test/vim_test_context.rs 🔗

@@ -16,8 +16,18 @@ pub struct VimTestContext<'a> {
 
 impl<'a> VimTestContext<'a> {
     pub async fn new(cx: &'a mut gpui::TestAppContext, enabled: bool) -> VimTestContext<'a> {
-        let mut cx = EditorLspTestContext::new_rust(Default::default(), cx).await;
+        let lsp = EditorLspTestContext::new_rust(Default::default(), cx).await;
+        Self::new_with_lsp(lsp, enabled)
+    }
+
+    pub async fn new_typescript(cx: &'a mut gpui::TestAppContext) -> VimTestContext<'a> {
+        Self::new_with_lsp(
+            EditorLspTestContext::new_typescript(Default::default(), cx).await,
+            true,
+        )
+    }
 
+    pub fn new_with_lsp(mut cx: EditorLspTestContext<'a>, enabled: bool) -> VimTestContext<'a> {
         cx.update(|cx| {
             search::init(cx);
             crate::init(cx);

crates/zed/src/languages/javascript/config.toml 🔗

@@ -13,6 +13,7 @@ brackets = [
     { start = "`", end = "`", close = true, newline = false, not_in = ["comment", "string"] },
     { start = "/*", end = " */", close = true, newline = false, not_in = ["comment", "string"] },
 ]
+word_characters = ["$", "#"]
 
 [overrides.element]
 line_comment = { remove = true }

crates/zed/src/languages/tsx/config.toml 🔗

@@ -12,6 +12,7 @@ brackets = [
     { start = "`", end = "`", close = true, newline = false, not_in = ["string"] },
     { start = "/*", end = " */", close = true, newline = false, not_in = ["string", "comment"] },
 ]
+word_characters = ["#", "$"]
 
 [overrides.element]
 line_comment = { remove = true }

crates/zed/src/languages/typescript/config.toml 🔗

@@ -12,3 +12,4 @@ brackets = [
     { start = "`", end = "`", close = true, newline = false, not_in = ["string"] },
     { start = "/*", end = " */", close = true, newline = false, not_in = ["string", "comment"] },
 ]
+word_characters = ["#", "$"]