diff --git a/crates/editor/src/multi_buffer.rs b/crates/editor/src/multi_buffer.rs index d4061f25dc6a22b8a3abd79ae0471c811e2b08e0..9dd40af8981dab6d82ba4dda237ca46804575519 100644 --- a/crates/editor/src/multi_buffer.rs +++ b/crates/editor/src/multi_buffer.rs @@ -1346,10 +1346,7 @@ impl MultiBuffer { .map(|state| state.buffer.clone()) } - pub fn is_completion_trigger(&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; } diff --git a/crates/editor/src/test/editor_lsp_test_context.rs b/crates/editor/src/test/editor_lsp_test_context.rs index 83aaa3b703491b5f5334d173ca8d90e731aeb5e8..4d0e9c1d2af8b27fcd796205d83f37ee9a931503 100644 --- a/crates/editor/src/test/editor_lsp_test_context.rs +++ b/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 = 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()), diff --git a/crates/vim/src/test.rs b/crates/vim/src/test.rs index 772d7a20339632faaf64d3a21363432d48af45af..3b1b8c24f2d301f5f843bfe56754a3d3d07233f9 100644 --- a/crates/vim/src/test.rs +++ b/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, + ) +} diff --git a/crates/vim/src/test/vim_test_context.rs b/crates/vim/src/test/vim_test_context.rs index 56193723d9500d1a88954bc82bd45d6e917ba9a7..24fb16fd3d736f4afec804ce8752c1c7e42f8232 100644 --- a/crates/vim/src/test/vim_test_context.rs +++ b/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); diff --git a/crates/zed/src/languages/javascript/config.toml b/crates/zed/src/languages/javascript/config.toml index 8f4670388edc40e4ff9a1bf068d4e2b945000bb2..0435f96c921fb28843e08078e34c2cebc1c33cdd 100644 --- a/crates/zed/src/languages/javascript/config.toml +++ b/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 } diff --git a/crates/zed/src/languages/tsx/config.toml b/crates/zed/src/languages/tsx/config.toml index 234dc6b01326a8398b5ab5dfbdfec93a37d910ad..63d1f85e643cf2c19b6b43f5f86ae89976b7bd74 100644 --- a/crates/zed/src/languages/tsx/config.toml +++ b/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 } diff --git a/crates/zed/src/languages/typescript/config.toml b/crates/zed/src/languages/typescript/config.toml index a2b764d9fe38e3058adfbdf292c52f667acae264..2fad1f13e182c52e2886e459fd0efa6fb673a7d6 100644 --- a/crates/zed/src/languages/typescript/config.toml +++ b/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 = ["#", "$"]