From 89221569234d774bbef125f98f8d9d9d11318966 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Thu, 16 Feb 2023 17:06:51 -0800 Subject: [PATCH 1/5] Restructure how bracket pairs are overridden to unify lists This way, a bracket pair that is disabled in a given scope can still be skipped, if it was auto-closed before that scope existed. --- crates/editor/src/editor.rs | 8 +- crates/editor/src/editor_tests.rs | 261 ++++++++++-------- .../editor/src/highlight_matching_bracket.rs | 36 +-- crates/language/src/buffer_tests.rs | 80 +++--- crates/language/src/language.rs | 106 +++++-- crates/zed/src/languages/c/config.toml | 20 +- crates/zed/src/languages/cpp/config.toml | 20 +- crates/zed/src/languages/css/config.toml | 18 +- crates/zed/src/languages/elixir/config.toml | 18 +- crates/zed/src/languages/go/config.toml | 20 +- crates/zed/src/languages/html/config.toml | 20 +- .../zed/src/languages/javascript/config.toml | 24 +- crates/zed/src/languages/json/config.toml | 8 +- crates/zed/src/languages/lua/config.toml | 12 +- crates/zed/src/languages/python/config.toml | 24 +- crates/zed/src/languages/ruby/config.toml | 18 +- crates/zed/src/languages/rust/config.toml | 23 +- crates/zed/src/languages/scheme/config.toml | 14 +- crates/zed/src/languages/toml/config.toml | 16 +- crates/zed/src/languages/tsx/config.toml | 15 +- .../zed/src/languages/typescript/config.toml | 24 +- crates/zed/src/languages/yaml/config.toml | 8 +- 22 files changed, 340 insertions(+), 453 deletions(-) diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index f9d50019854cd7e683d522231683f1e63a1f77f5..787f7b8514b2e72829b7f9b8b704a9ad2664ccbd 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -1761,8 +1761,8 @@ impl Editor { // bracket of any of this language's bracket pairs. let mut bracket_pair = None; let mut is_bracket_pair_start = false; - for pair in language.brackets() { - if pair.close && pair.start.ends_with(text.as_ref()) { + for (pair, enabled) in language.brackets() { + if enabled && pair.close && pair.start.ends_with(text.as_ref()) { bracket_pair = Some(pair.clone()); is_bracket_pair_start = true; break; @@ -1930,11 +1930,11 @@ impl Editor { .map(|c| c.len_utf8()) .sum::(); - insert_extra_newline = language.brackets().iter().any(|pair| { + insert_extra_newline = language.brackets().any(|(pair, enabled)| { let pair_start = pair.start.trim_end(); let pair_end = pair.end.trim_start(); - pair.newline + enabled && pair.newline && buffer .contains_str_at(end + trailing_whitespace_len, pair_end) && buffer.contains_str_at( diff --git a/crates/editor/src/editor_tests.rs b/crates/editor/src/editor_tests.rs index 9b5cececff3659921a1ccbc12754158c709ecaf7..64ff6dec38873671ffc98fe3bec613c203913166 100644 --- a/crates/editor/src/editor_tests.rs +++ b/crates/editor/src/editor_tests.rs @@ -14,7 +14,7 @@ use gpui::{ geometry::{rect::RectF, vector::vec2f}, platform::{WindowBounds, WindowOptions}, }; -use language::{FakeLspAdapter, LanguageConfig, LanguageRegistry, Point}; +use language::{BracketPairConfig, FakeLspAdapter, LanguageConfig, LanguageRegistry, Point}; use project::FakeFs; use settings::EditorSettings; use util::{ @@ -3002,20 +3002,23 @@ async fn test_autoindent_selections(cx: &mut gpui::TestAppContext) { let language = Arc::new( Language::new( LanguageConfig { - brackets: vec![ - BracketPair { - start: "{".to_string(), - end: "}".to_string(), - close: false, - newline: true, - }, - BracketPair { - start: "(".to_string(), - end: ")".to_string(), - close: false, - newline: true, - }, - ], + brackets: BracketPairConfig { + pairs: vec![ + BracketPair { + start: "{".to_string(), + end: "}".to_string(), + close: false, + newline: true, + }, + BracketPair { + start: "(".to_string(), + end: ")".to_string(), + close: false, + newline: true, + }, + ], + ..Default::default() + }, ..Default::default() }, Some(tree_sitter_rust::language()), @@ -3059,38 +3062,41 @@ async fn test_autoclose_pairs(cx: &mut gpui::TestAppContext) { let language = Arc::new(Language::new( LanguageConfig { - brackets: vec![ - BracketPair { - start: "{".to_string(), - end: "}".to_string(), - close: true, - newline: true, - }, - BracketPair { - start: "(".to_string(), - end: ")".to_string(), - close: true, - newline: true, - }, - BracketPair { - start: "/*".to_string(), - end: " */".to_string(), - close: true, - newline: true, - }, - BracketPair { - start: "[".to_string(), - end: "]".to_string(), - close: false, - newline: true, - }, - BracketPair { - start: "\"".to_string(), - end: "\"".to_string(), - close: true, - newline: false, - }, - ], + brackets: BracketPairConfig { + pairs: vec![ + BracketPair { + start: "{".to_string(), + end: "}".to_string(), + close: true, + newline: true, + }, + BracketPair { + start: "(".to_string(), + end: ")".to_string(), + close: true, + newline: true, + }, + BracketPair { + start: "/*".to_string(), + end: " */".to_string(), + close: true, + newline: true, + }, + BracketPair { + start: "[".to_string(), + end: "]".to_string(), + close: false, + newline: true, + }, + BracketPair { + start: "\"".to_string(), + end: "\"".to_string(), + close: true, + newline: false, + }, + ], + ..Default::default() + }, autoclose_before: "})]".to_string(), ..Default::default() }, @@ -3227,10 +3233,52 @@ async fn test_autoclose_with_embedded_language(cx: &mut gpui::TestAppContext) { Language::new( LanguageConfig { name: "HTML".into(), - brackets: vec![ + brackets: BracketPairConfig { + pairs: vec![ + BracketPair { + start: "<".into(), + end: ">".into(), + close: true, + ..Default::default() + }, + BracketPair { + start: "{".into(), + end: "}".into(), + close: true, + ..Default::default() + }, + BracketPair { + start: "(".into(), + end: ")".into(), + close: true, + ..Default::default() + }, + ], + ..Default::default() + }, + autoclose_before: "})]>".into(), + ..Default::default() + }, + Some(tree_sitter_html::language()), + ) + .with_injection_query( + r#" + (script_element + (raw_text) @content + (#set! "language" "javascript")) + "#, + ) + .unwrap(), + ); + + let javascript_language = Arc::new(Language::new( + LanguageConfig { + name: "JavaScript".into(), + brackets: BracketPairConfig { + pairs: vec![ BracketPair { - start: "<".into(), - end: ">".into(), + start: "/*".into(), + end: " */".into(), close: true, ..Default::default() }, @@ -3247,44 +3295,8 @@ async fn test_autoclose_with_embedded_language(cx: &mut gpui::TestAppContext) { ..Default::default() }, ], - autoclose_before: "})]>".into(), ..Default::default() }, - Some(tree_sitter_html::language()), - ) - .with_injection_query( - r#" - (script_element - (raw_text) @content - (#set! "language" "javascript")) - "#, - ) - .unwrap(), - ); - - let javascript_language = Arc::new(Language::new( - LanguageConfig { - name: "JavaScript".into(), - brackets: vec![ - BracketPair { - start: "/*".into(), - end: " */".into(), - close: true, - ..Default::default() - }, - BracketPair { - start: "{".into(), - end: "}".into(), - close: true, - ..Default::default() - }, - BracketPair { - start: "(".into(), - end: ")".into(), - close: true, - ..Default::default() - }, - ], autoclose_before: "})]>".into(), ..Default::default() }, @@ -3452,20 +3464,23 @@ async fn test_surround_with_pair(cx: &mut gpui::TestAppContext) { cx.update(|cx| cx.set_global(Settings::test(cx))); let language = Arc::new(Language::new( LanguageConfig { - brackets: vec![ - BracketPair { - start: "{".to_string(), - end: "}".to_string(), - close: true, - newline: true, - }, - BracketPair { - start: "/* ".to_string(), - end: "*/".to_string(), - close: true, - ..Default::default() - }, - ], + brackets: BracketPairConfig { + pairs: vec![ + BracketPair { + start: "{".to_string(), + end: "}".to_string(), + close: true, + newline: true, + }, + BracketPair { + start: "/* ".to_string(), + end: "*/".to_string(), + close: true, + ..Default::default() + }, + ], + ..Default::default() + }, ..Default::default() }, Some(tree_sitter_rust::language()), @@ -3603,12 +3618,15 @@ async fn test_delete_autoclose_pair(cx: &mut gpui::TestAppContext) { cx.update(|cx| cx.set_global(Settings::test(cx))); let language = Arc::new(Language::new( LanguageConfig { - brackets: vec![BracketPair { - start: "{".to_string(), - end: "}".to_string(), - close: true, - newline: true, - }], + brackets: BracketPairConfig { + pairs: vec![BracketPair { + start: "{".to_string(), + end: "}".to_string(), + close: true, + newline: true, + }], + ..Default::default() + }, autoclose_before: "}".to_string(), ..Default::default() }, @@ -5030,20 +5048,23 @@ async fn test_extra_newline_insertion(cx: &mut gpui::TestAppContext) { let language = Arc::new( Language::new( LanguageConfig { - brackets: vec![ - BracketPair { - start: "{".to_string(), - end: "}".to_string(), - close: true, - newline: true, - }, - BracketPair { - start: "/* ".to_string(), - end: " */".to_string(), - close: true, - newline: true, - }, - ], + brackets: BracketPairConfig { + pairs: vec![ + BracketPair { + start: "{".to_string(), + end: "}".to_string(), + close: true, + newline: true, + }, + BracketPair { + start: "/* ".to_string(), + end: " */".to_string(), + close: true, + newline: true, + }, + ], + ..Default::default() + }, ..Default::default() }, Some(tree_sitter_rust::language()), diff --git a/crates/editor/src/highlight_matching_bracket.rs b/crates/editor/src/highlight_matching_bracket.rs index 0d868d460c3f44267c79588d08081a747b67807f..ce3864f56a2cf228284092719dda7408ecd574f8 100644 --- a/crates/editor/src/highlight_matching_bracket.rs +++ b/crates/editor/src/highlight_matching_bracket.rs @@ -32,11 +32,10 @@ pub fn refresh_matching_bracket_highlights(editor: &mut Editor, cx: &mut ViewCon #[cfg(test)] mod tests { - use crate::test::editor_lsp_test_context::EditorLspTestContext; - use super::*; + use crate::test::editor_lsp_test_context::EditorLspTestContext; use indoc::indoc; - use language::{BracketPair, Language, LanguageConfig}; + use language::{BracketPair, BracketPairConfig, Language, LanguageConfig}; #[gpui::test] async fn test_matching_bracket_highlights(cx: &mut gpui::TestAppContext) { @@ -45,20 +44,23 @@ mod tests { LanguageConfig { name: "Rust".into(), path_suffixes: vec!["rs".to_string()], - brackets: vec![ - BracketPair { - start: "{".to_string(), - end: "}".to_string(), - close: false, - newline: true, - }, - BracketPair { - start: "(".to_string(), - end: ")".to_string(), - close: false, - newline: true, - }, - ], + brackets: BracketPairConfig { + pairs: vec![ + BracketPair { + start: "{".to_string(), + end: "}".to_string(), + close: false, + newline: true, + }, + BracketPair { + start: "(".to_string(), + end: ")".to_string(), + close: false, + newline: true, + }, + ], + ..Default::default() + }, ..Default::default() }, Some(tree_sitter_rust::language()), diff --git a/crates/language/src/buffer_tests.rs b/crates/language/src/buffer_tests.rs index e6e75447637296d4b78cab1b2d9f791882cc7d27..36add5f1f3fe036b222c9751dfe3496c1596d677 100644 --- a/crates/language/src/buffer_tests.rs +++ b/crates/language/src/buffer_tests.rs @@ -1527,42 +1527,34 @@ fn test_language_config_at(cx: &mut MutableAppContext) { LanguageConfig { name: "JavaScript".into(), line_comment: Some("// ".into()), - brackets: vec![ - BracketPair { - start: "{".into(), - end: "}".into(), - close: true, - newline: false, - }, - BracketPair { - start: "'".into(), - end: "'".into(), - close: true, - newline: false, - }, - ], - overrides: [ - ( - "element".into(), - LanguageConfigOverride { - line_comment: Override::Remove { remove: true }, - block_comment: Override::Set(("{/*".into(), "*/}".into())), - ..Default::default() + brackets: BracketPairConfig { + pairs: vec![ + BracketPair { + start: "{".into(), + end: "}".into(), + close: true, + newline: false, }, - ), - ( - "string".into(), - LanguageConfigOverride { - brackets: Override::Set(vec![BracketPair { - start: "{".into(), - end: "}".into(), - close: true, - newline: false, - }]), - ..Default::default() + BracketPair { + start: "'".into(), + end: "'".into(), + close: true, + newline: false, }, - ), - ] + ], + disabled_scopes_by_bracket_ix: vec![ + Vec::new(), // + vec!["string".into()], + ], + }, + overrides: [( + "element".into(), + LanguageConfigOverride { + line_comment: Override::Remove { remove: true }, + block_comment: Override::Set(("{/*".into(), "*/}".into())), + ..Default::default() + }, + )] .into_iter() .collect(), ..Default::default() @@ -1584,11 +1576,19 @@ fn test_language_config_at(cx: &mut MutableAppContext) { let config = snapshot.language_scope_at(0).unwrap(); assert_eq!(config.line_comment_prefix().unwrap().as_ref(), "// "); - assert_eq!(config.brackets().len(), 2); + // Both bracket pairs are enabled + assert_eq!( + config.brackets().map(|e| e.1).collect::>(), + &[true, true] + ); let string_config = snapshot.language_scope_at(3).unwrap(); - assert_eq!(config.line_comment_prefix().unwrap().as_ref(), "// "); - assert_eq!(string_config.brackets().len(), 1); + assert_eq!(string_config.line_comment_prefix().unwrap().as_ref(), "// "); + // Second bracket pair is disabled + assert_eq!( + string_config.brackets().map(|e| e.1).collect::>(), + &[true, false] + ); let element_config = snapshot.language_scope_at(10).unwrap(); assert_eq!(element_config.line_comment_prefix(), None); @@ -1596,7 +1596,11 @@ fn test_language_config_at(cx: &mut MutableAppContext) { element_config.block_comment_delimiters(), Some((&"{/*".into(), &"*/}".into())) ); - assert_eq!(element_config.brackets().len(), 2); + // Both bracket pairs are enabled + assert_eq!( + element_config.brackets().map(|e| e.1).collect::>(), + &[true, true] + ); buffer }); diff --git a/crates/language/src/language.rs b/crates/language/src/language.rs index 4279ce665402be81f9ad26994bcebe8e1ea63a34..c84fc109ff431946db52a0fa725332622ff8c861 100644 --- a/crates/language/src/language.rs +++ b/crates/language/src/language.rs @@ -231,7 +231,7 @@ pub struct CodeLabel { pub struct LanguageConfig { pub name: Arc, pub path_suffixes: Vec, - pub brackets: Vec, + pub brackets: BracketPairConfig, #[serde(default = "auto_indent_using_last_non_empty_line_default")] pub auto_indent_using_last_non_empty_line: bool, #[serde(default, deserialize_with = "deserialize_regex")] @@ -270,8 +270,8 @@ pub struct LanguageConfigOverride { pub line_comment: Override>, #[serde(default)] pub block_comment: Override<(Arc, Arc)>, - #[serde(default)] - pub brackets: Override>, + #[serde(skip_deserializing)] + pub disabled_bracket_ixs: Vec, } #[derive(Deserialize, Debug)] @@ -336,7 +336,41 @@ pub struct FakeLspAdapter { pub disk_based_diagnostics_sources: Vec, } -#[derive(Clone, Debug, Default, Deserialize)] +#[derive(Clone, Debug, Default)] +pub struct BracketPairConfig { + pub pairs: Vec, + pub disabled_scopes_by_bracket_ix: Vec>, +} + +impl<'de> Deserialize<'de> for BracketPairConfig { + fn deserialize(deserializer: D) -> std::result::Result + where + D: Deserializer<'de>, + { + #[derive(Deserialize)] + pub struct Entry { + #[serde(flatten)] + pub bracket_pair: BracketPair, + #[serde(default)] + pub not_in: Vec, + } + + let result = Vec::::deserialize(deserializer)?; + let mut brackets = Vec::with_capacity(result.len()); + let mut disabled_scopes_by_bracket_ix = Vec::with_capacity(result.len()); + for entry in result { + brackets.push(entry.bracket_pair); + disabled_scopes_by_bracket_ix.push(entry.not_in); + } + + Ok(BracketPairConfig { + pairs: brackets, + disabled_scopes_by_bracket_ix, + }) + } +} + +#[derive(Clone, Debug, Default, Deserialize, PartialEq)] pub struct BracketPair { pub start: String, pub end: String, @@ -393,7 +427,7 @@ struct InjectionConfig { struct OverrideConfig { query: Query, - values: HashMap, + values: HashMap, } #[derive(Default, Clone)] @@ -967,16 +1001,11 @@ impl Language { pub fn with_override_query(mut self, source: &str) -> Result { let query = Query::new(self.grammar_mut().ts_language, source)?; - let mut values = HashMap::default(); + let mut override_configs_by_id = HashMap::default(); for (ix, name) in query.capture_names().iter().enumerate() { if !name.starts_with('_') { - let value = self.config.overrides.remove(name).ok_or_else(|| { - anyhow!( - "language {:?} has override in query but not in config: {name:?}", - self.config.name - ) - })?; - values.insert(ix as u32, value); + let value = self.config.overrides.remove(name).unwrap_or_default(); + override_configs_by_id.insert(ix as u32, (name.clone(), value)); } } @@ -988,7 +1017,28 @@ impl Language { ))?; } - self.grammar_mut().override_config = Some(OverrideConfig { query, values }); + for (name, override_config) in override_configs_by_id.values_mut() { + override_config.disabled_bracket_ixs = self + .config + .brackets + .disabled_scopes_by_bracket_ix + .iter() + .enumerate() + .filter_map(|(ix, disabled_scope_names)| { + if disabled_scope_names.contains(name) { + Some(ix as u16) + } else { + None + } + }) + .collect(); + } + + self.config.brackets.disabled_scopes_by_bracket_ix.clear(); + self.grammar_mut().override_config = Some(OverrideConfig { + query, + values: override_configs_by_id, + }); Ok(self) } @@ -1132,12 +1182,26 @@ impl LanguageScope { .map(|e| (&e.0, &e.1)) } - pub fn brackets(&self) -> &[BracketPair] { - Override::as_option( - self.config_override().map(|o| &o.brackets), - Some(&self.language.config.brackets), - ) - .map_or(&[], Vec::as_slice) + pub fn brackets(&self) -> impl Iterator { + let mut disabled_ids = self + .config_override() + .map_or(&[] as _, |o| o.disabled_bracket_ixs.as_slice()); + self.language + .config + .brackets + .pairs + .iter() + .enumerate() + .map(move |(ix, bracket)| { + let mut is_enabled = true; + if let Some(next_disabled_ix) = disabled_ids.first() { + if ix == *next_disabled_ix as usize { + disabled_ids = &disabled_ids[1..]; + is_enabled = false; + } + } + (bracket, is_enabled) + }) } pub fn should_autoclose_before(&self, c: char) -> bool { @@ -1148,7 +1212,7 @@ impl LanguageScope { let id = self.override_id?; let grammar = self.language.grammar.as_ref()?; let override_config = grammar.override_config.as_ref()?; - override_config.values.get(&id) + override_config.values.get(&id).map(|e| &e.1) } } diff --git a/crates/zed/src/languages/c/config.toml b/crates/zed/src/languages/c/config.toml index 1a5fe9339ad9fa3a0c9da1198ae5bebfd8600819..f986f4b834b09e81274467cc6b30c8ea7075838e 100644 --- a/crates/zed/src/languages/c/config.toml +++ b/crates/zed/src/languages/c/config.toml @@ -6,21 +6,7 @@ brackets = [ { start = "{", end = "}", close = true, newline = true }, { start = "[", end = "]", close = true, newline = true }, { start = "(", end = ")", close = true, newline = true }, - { start = "\"", end = "\"", close = true, newline = false }, - { start = "'", end = "'", close = true, newline = false }, - { start = "/*", end = " */", close = true, newline = false }, -] - -[overrides.comment] -brackets = [ - { start = "{", end = "}", close = true, newline = true }, - { start = "[", end = "]", close = true, newline = true }, - { start = "(", end = ")", close = true, newline = true }, -] - -[overrides.string] -brackets = [ - { start = "{", end = "}", close = true, newline = true }, - { start = "[", end = "]", close = true, newline = true }, - { start = "(", end = ")", close = true, newline = true }, + { start = "\"", end = "\"", close = true, newline = false, not_in = ["string"] }, + { start = "'", end = "'", close = true, newline = false, not_in = ["string", "comment"] }, + { start = "/*", end = " */", close = true, newline = false, not_in = ["string", "comment"] }, ] diff --git a/crates/zed/src/languages/cpp/config.toml b/crates/zed/src/languages/cpp/config.toml index c83adfb067f2d2da8819b32b144c90f1c40992b4..c719fae1eb61622271f71c4d924e08f649b42fd3 100644 --- a/crates/zed/src/languages/cpp/config.toml +++ b/crates/zed/src/languages/cpp/config.toml @@ -6,21 +6,7 @@ brackets = [ { start = "{", end = "}", close = true, newline = true }, { start = "[", end = "]", close = true, newline = true }, { start = "(", end = ")", close = true, newline = true }, - { start = "\"", end = "\"", close = true, newline = false }, - { start = "'", end = "'", close = true, newline = false }, - { start = "/*", end = " */", close = true, newline = false }, -] - -[overrides.comment] -brackets = [ - { start = "{", end = "}", close = true, newline = true }, - { start = "[", end = "]", close = true, newline = true }, - { start = "(", end = ")", close = true, newline = true }, -] - -[overrides.string] -brackets = [ - { start = "{", end = "}", close = true, newline = true }, - { start = "[", end = "]", close = true, newline = true }, - { start = "(", end = ")", close = true, newline = true }, + { start = "\"", end = "\"", close = true, newline = false, not_in = ["string"] }, + { start = "'", end = "'", close = true, newline = false, not_in = ["string", "comment"] }, + { start = "/*", end = " */", close = true, newline = false, not_in = ["string", "comment"] }, ] diff --git a/crates/zed/src/languages/css/config.toml b/crates/zed/src/languages/css/config.toml index cf8d4f1e2f88682139fb6a4bf28623ca4826e338..ba9660c4ed1f9b2de49558fc919e521d3f2f16f1 100644 --- a/crates/zed/src/languages/css/config.toml +++ b/crates/zed/src/languages/css/config.toml @@ -5,20 +5,6 @@ brackets = [ { start = "{", end = "}", close = true, newline = true }, { start = "[", end = "]", close = true, newline = true }, { start = "(", end = ")", close = true, newline = true }, - { start = "\"", end = "\"", close = true, newline = false }, - { start = "'", end = "'", close = true, newline = false }, -] - -[overrides.comment] -brackets = [ - { start = "{", end = "}", close = true, newline = true }, - { start = "[", end = "]", close = true, newline = true }, - { start = "(", end = ")", close = true, newline = true }, -] - -[overrides.string] -brackets = [ - { start = "{", end = "}", close = true, newline = true }, - { start = "[", end = "]", close = true, newline = true }, - { start = "(", end = ")", close = true, newline = true }, + { start = "\"", end = "\"", close = true, newline = false, not_in = ["string", "comment"] }, + { start = "'", end = "'", close = true, newline = false, not_in = ["string", "comment"] }, ] diff --git a/crates/zed/src/languages/elixir/config.toml b/crates/zed/src/languages/elixir/config.toml index 0185d8eec35a2173eb802f0e0618e43b23fd19dd..05c126e9da4ccfbe9c3beed134ed1b374cbcecab 100644 --- a/crates/zed/src/languages/elixir/config.toml +++ b/crates/zed/src/languages/elixir/config.toml @@ -6,20 +6,6 @@ brackets = [ { start = "{", end = "}", close = true, newline = true }, { start = "[", end = "]", close = true, newline = true }, { start = "(", end = ")", close = true, newline = true }, - { start = "\"", end = "\"", close = true, newline = false }, - { start = "'", end = "'", close = true, newline = false }, -] - -[overrides.comment] -brackets = [ - { start = "{", end = "}", close = true, newline = true }, - { start = "[", end = "]", close = true, newline = true }, - { start = "(", end = ")", close = true, newline = true }, -] - -[overrides.string] -brackets = [ - { start = "{", end = "}", close = true, newline = true }, - { start = "[", end = "]", close = true, newline = true }, - { start = "(", end = ")", close = true, newline = true }, + { start = "\"", end = "\"", close = true, newline = false, not_in = ["string", "comment"] }, + { start = "'", end = "'", close = true, newline = false, not_in = ["string", "comment"] }, ] diff --git a/crates/zed/src/languages/go/config.toml b/crates/zed/src/languages/go/config.toml index 3f9464594cd76528ff6bf0e80b75ad6d3a08d4cf..1951e193f0fcae77c23c4b915f030d0d960e020a 100644 --- a/crates/zed/src/languages/go/config.toml +++ b/crates/zed/src/languages/go/config.toml @@ -6,21 +6,7 @@ brackets = [ { start = "{", end = "}", close = true, newline = true }, { start = "[", end = "]", close = true, newline = true }, { start = "(", end = ")", close = true, newline = true }, - { start = "\"", end = "\"", close = true, newline = false }, - { start = "'", end = "'", close = true, newline = false }, - { start = "/*", end = " */", close = true, newline = false }, -] - -[overrides.comment] -brackets = [ - { start = "{", end = "}", close = true, newline = true }, - { start = "[", end = "]", close = true, newline = true }, - { start = "(", end = ")", close = true, newline = true }, -] - -[overrides.string] -brackets = [ - { start = "{", end = "}", close = true, newline = true }, - { start = "[", end = "]", close = true, newline = true }, - { start = "(", end = ")", close = true, newline = true }, + { start = "\"", end = "\"", close = true, newline = false, not_in = ["comment", "string"] }, + { start = "'", end = "'", close = true, newline = false, not_in = ["comment", "string"] }, + { start = "/*", end = " */", close = true, newline = false, not_in = ["comment", "string"] }, ] diff --git a/crates/zed/src/languages/html/config.toml b/crates/zed/src/languages/html/config.toml index f4f0ba26eac95488c79c6db91afb5700ebe6a4dd..077a421ce1b0e0375b56d2fc8cac48a601e03a65 100644 --- a/crates/zed/src/languages/html/config.toml +++ b/crates/zed/src/languages/html/config.toml @@ -1,26 +1,12 @@ name = "HTML" path_suffixes = ["html"] autoclose_before = ">})" -brackets = [ - { start = "<", end = ">", close = true, newline = true }, - { start = "{", end = "}", close = true, newline = true }, - { start = "(", end = ")", close = true, newline = true }, - { start = "\"", end = "\"", close = true, newline = false }, - { start = "!--", end = " --", close = true, newline = false }, -] - block_comment = [""] - -[overrides.comment] -brackets = [ - { start = "{", end = "}", close = true, newline = true }, - { start = "[", end = "]", close = true, newline = true }, - { start = "(", end = ")", close = true, newline = true }, -] - -[overrides.string] brackets = [ { start = "{", end = "}", close = true, newline = true }, { start = "[", end = "]", close = true, newline = true }, { start = "(", end = ")", close = true, newline = true }, + { start = "\"", end = "\"", close = true, newline = false, not_in = ["comment", "string"] }, + { start = "<", end = ">", close = true, newline = true, not_in = ["comment", "string"] }, + { start = "!--", end = " --", close = true, newline = false, not_in = ["comment", "string"] }, ] diff --git a/crates/zed/src/languages/javascript/config.toml b/crates/zed/src/languages/javascript/config.toml index a5a656393dcb6aa338a8431eb63d8dc5ca4898d5..7c49ac951384be6594f6f1b702d6052f6ecd30c8 100644 --- a/crates/zed/src/languages/javascript/config.toml +++ b/crates/zed/src/languages/javascript/config.toml @@ -6,25 +6,11 @@ brackets = [ { start = "{", end = "}", close = true, newline = true }, { start = "[", end = "]", close = true, newline = true }, { start = "(", end = ")", close = true, newline = true }, - { start = "<", end = ">", close = false, newline = true }, - { start = "\"", end = "\"", close = true, newline = false }, - { start = "'", end = "'", close = true, newline = false }, - { start = "`", end = "`", close = true, newline = false }, - { start = "/*", end = " */", close = true, newline = false }, -] - -[overrides.comment] -brackets = [ - { start = "{", end = "}", close = true, newline = true }, - { start = "[", end = "]", close = true, newline = true }, - { start = "(", end = ")", close = true, newline = true }, -] - -[overrides.string] -brackets = [ - { start = "{", end = "}", close = true, newline = true }, - { start = "[", end = "]", close = true, newline = true }, - { start = "(", end = ")", close = true, newline = true }, + { start = "<", end = ">", close = false, newline = true, not_in = ["comment", "string"] }, + { start = "\"", end = "\"", close = true, newline = false, not_in = ["comment", "string"] }, + { start = "'", end = "'", close = true, newline = false, not_in = ["comment", "string"] }, + { start = "`", end = "`", close = true, newline = false, not_in = ["comment", "string"] }, + { start = "/*", end = " */", close = true, newline = false, not_in = ["comment", "string"] }, ] [overrides.element] diff --git a/crates/zed/src/languages/json/config.toml b/crates/zed/src/languages/json/config.toml index 48a1fb0c993f0481d0862eb4a1820c922adcb12d..87f41882a5fd92ee4ce66f8fb32031fc85d68bbf 100644 --- a/crates/zed/src/languages/json/config.toml +++ b/crates/zed/src/languages/json/config.toml @@ -5,11 +5,5 @@ autoclose_before = ",]}" brackets = [ { start = "{", end = "}", close = true, newline = true }, { start = "[", end = "]", close = true, newline = true }, - { start = "\"", end = "\"", close = true, newline = false }, -] - -[overrides.string] -brackets = [ - { start = "{", end = "}", close = true, newline = true }, - { start = "[", end = "]", close = true, newline = true }, + { start = "\"", end = "\"", close = true, newline = false, not_in = ["string"] }, ] diff --git a/crates/zed/src/languages/lua/config.toml b/crates/zed/src/languages/lua/config.toml index effb37f945a1f0f2c9780d25e752d419f83e557e..fe44a3d2aaa5b0c57d13f41d925193d478d714a9 100644 --- a/crates/zed/src/languages/lua/config.toml +++ b/crates/zed/src/languages/lua/config.toml @@ -3,13 +3,7 @@ path_suffixes = ["lua"] line_comment = "-- " autoclose_before = ",]}" brackets = [ -{ start = "{", end = "}", close = true, newline = true }, -{ start = "[", end = "]", close = true, newline = true }, -{ start = "\"", end = "\"", close = true, newline = false }, + { start = "{", end = "}", close = true, newline = true }, + { start = "[", end = "]", close = true, newline = true }, + { start = "\"", end = "\"", close = true, newline = false, not_in = ["string"] }, ] - -[overrides.string] -brackets = [ -{ start = "{", end = "}", close = true, newline = true }, -{ start = "[", end = "]", close = true, newline = true }, -] \ No newline at end of file diff --git a/crates/zed/src/languages/python/config.toml b/crates/zed/src/languages/python/config.toml index 45f20e25a3570b7b939fa04cf7a2c14e3528ba15..e733676d895f266d98a20affc9fee4be5a3b91a2 100644 --- a/crates/zed/src/languages/python/config.toml +++ b/crates/zed/src/languages/python/config.toml @@ -2,28 +2,14 @@ name = "Python" path_suffixes = ["py", "pyi"] line_comment = "# " autoclose_before = ";:.,=}])>" -brackets = [ - { start = "{", end = "}", close = true, newline = true }, - { start = "[", end = "]", close = true, newline = true }, - { start = "(", end = ")", close = true, newline = true }, - { start = "\"", end = "\"", close = true, newline = false }, - { start = "'", end = "'", close = false, newline = false }, -] - -auto_indent_using_last_non_empty_line = false -increase_indent_pattern = ":\\s*$" -decrease_indent_pattern = "^\\s*(else|elif|except|finally)\\b.*:" - -[overrides.comment] brackets = [ { start = "{", end = "}", close = true, newline = true }, { start = "[", end = "]", close = true, newline = true }, { start = "(", end = ")", close = true, newline = true }, + { start = "\"", end = "\"", close = true, newline = false, not_in = ["string"] }, + { start = "'", end = "'", close = false, newline = false, not_in = ["string"] }, ] -[overrides.string] -brackets = [ - { start = "{", end = "}", close = true, newline = true }, - { start = "[", end = "]", close = true, newline = true }, - { start = "(", end = ")", close = true, newline = true }, -] +auto_indent_using_last_non_empty_line = false +increase_indent_pattern = ":\\s*$" +decrease_indent_pattern = "^\\s*(else|elif|except|finally)\\b.*:" diff --git a/crates/zed/src/languages/ruby/config.toml b/crates/zed/src/languages/ruby/config.toml index 4fd21d8bd0a2598f30a006e5ccd232ec089475af..329e080740385fe74b98ee1b32de7e95864cbea7 100644 --- a/crates/zed/src/languages/ruby/config.toml +++ b/crates/zed/src/languages/ruby/config.toml @@ -6,20 +6,6 @@ brackets = [ { start = "{", end = "}", close = true, newline = true }, { start = "[", end = "]", close = true, newline = true }, { start = "(", end = ")", close = true, newline = true }, - { start = "\"", end = "\"", close = true, newline = false }, - { start = "'", end = "'", close = true, newline = false }, -] - -[overrides.comment] -brackets = [ - { start = "{", end = "}", close = true, newline = true }, - { start = "[", end = "]", close = true, newline = true }, - { start = "(", end = ")", close = true, newline = true }, -] - -[overrides.string] -brackets = [ - { start = "{", end = "}", close = true, newline = true }, - { start = "[", end = "]", close = true, newline = true }, - { start = "(", end = ")", close = true, newline = true }, + { start = "\"", end = "\"", close = true, newline = false, not_in = ["comment", "string"] }, + { start = "'", end = "'", close = true, newline = false, not_in = ["comment", "string"] }, ] diff --git a/crates/zed/src/languages/rust/config.toml b/crates/zed/src/languages/rust/config.toml index f9f6b597173e49243c8552ab6a3cd64f7a7d1957..705287f0a758045ce8179bfc8a6bf18e564970b8 100644 --- a/crates/zed/src/languages/rust/config.toml +++ b/crates/zed/src/languages/rust/config.toml @@ -6,24 +6,7 @@ brackets = [ { start = "{", end = "}", close = true, newline = true }, { start = "[", end = "]", close = true, newline = true }, { start = "(", end = ")", close = true, newline = true }, - { start = "<", end = ">", close = false, newline = true }, - { start = "\"", end = "\"", close = true, newline = false }, - { start = "'", end = "'", close = false, newline = false }, - { start = "/*", end = " */", close = true, newline = false }, -] - -[overrides.comment] -brackets = [ - { start = "{", end = "}", close = true, newline = true }, - { start = "[", end = "]", close = true, newline = true }, - { start = "(", end = ")", close = true, newline = true }, - { start = "<", end = ">", close = false, newline = true }, -] - -[overrides.string] -brackets = [ - { start = "{", end = "}", close = true, newline = true }, - { start = "[", end = "]", close = true, newline = true }, - { start = "(", end = ")", close = true, newline = true }, - { start = "<", end = ">", close = false, newline = true }, + { start = "<", end = ">", close = false, newline = true, not_in = ["string", "comment"] }, + { start = "\"", end = "\"", close = true, newline = false, not_in = ["string"] }, + { start = "/*", end = " */", close = true, newline = false, not_in = ["string", "comment"] }, ] diff --git a/crates/zed/src/languages/scheme/config.toml b/crates/zed/src/languages/scheme/config.toml index 46e11bdc1158cd89237c0c10ef35de3a6b8ceb14..7b47698833ebecd304fa2773fdc89691ab3806a8 100644 --- a/crates/zed/src/languages/scheme/config.toml +++ b/crates/zed/src/languages/scheme/config.toml @@ -5,17 +5,5 @@ autoclose_before = "])" brackets = [ { start = "[", end = "]", close = true, newline = false }, { start = "(", end = ")", close = true, newline = false }, - { start = "\"", end = "\"", close = true, newline = false }, -] - -[overrides.comment] -brackets = [ - { start = "{", end = "}", close = true, newline = true }, - { start = "[", end = "]", close = true, newline = true }, -] - -[overrides.string] -brackets = [ - { start = "{", end = "}", close = true, newline = true }, - { start = "[", end = "]", close = true, newline = true }, + { start = "\"", end = "\"", close = true, newline = false, not_in = ["comment", "string"] }, ] diff --git a/crates/zed/src/languages/toml/config.toml b/crates/zed/src/languages/toml/config.toml index 30797bf141bf0a77a0dfcab431445104ee067095..4e89f5cabd99fb2faf120b32943be31d20d2a514 100644 --- a/crates/zed/src/languages/toml/config.toml +++ b/crates/zed/src/languages/toml/config.toml @@ -5,18 +5,6 @@ autoclose_before = ",]}" brackets = [ { start = "{", end = "}", close = true, newline = true }, { start = "[", end = "]", close = true, newline = true }, - { start = "\"", end = "\"", close = true, newline = false }, - { start = "'", end = "'", close = true, newline = false }, -] - -[overrides.comment] -brackets = [ - { start = "{", end = "}", close = true, newline = true }, - { start = "[", end = "]", close = true, newline = true }, -] - -[overrides.string] -brackets = [ - { start = "{", end = "}", close = true, newline = true }, - { start = "[", end = "]", close = true, newline = true }, + { start = "\"", end = "\"", close = true, newline = false, not_in = ["comment", "string"] }, + { start = "'", end = "'", close = true, newline = false, not_in = ["comment", "string"] }, ] diff --git a/crates/zed/src/languages/tsx/config.toml b/crates/zed/src/languages/tsx/config.toml index 4f466cc961e3836ee8d458cdcc4d863f61ab92a5..234dc6b01326a8398b5ab5dfbdfec93a37d910ad 100644 --- a/crates/zed/src/languages/tsx/config.toml +++ b/crates/zed/src/languages/tsx/config.toml @@ -6,18 +6,13 @@ brackets = [ { start = "{", end = "}", close = true, newline = true }, { start = "[", end = "]", close = true, newline = true }, { start = "(", end = ")", close = true, newline = true }, - { start = "<", end = ">", close = false, newline = true }, - { start = "\"", end = "\"", close = true, newline = false }, - { start = "'", end = "'", close = true, newline = false }, - { start = "`", end = "`", close = true, newline = false }, - { start = "/*", end = " */", close = true, newline = false }, + { start = "<", end = ">", close = false, newline = true, not_in = ["string", "comment"] }, + { start = "\"", end = "\"", close = true, newline = false, not_in = ["string"] }, + { start = "'", end = "'", close = true, newline = false, not_in = ["string", "comment"] }, + { start = "`", end = "`", close = true, newline = false, not_in = ["string"] }, + { start = "/*", end = " */", close = true, newline = false, not_in = ["string", "comment"] }, ] [overrides.element] line_comment = { remove = true } block_comment = ["{/* ", " */}"] - -[overrides.string] -brackets = [ - { start = "{", end = "}", close = true, newline = true }, -] diff --git a/crates/zed/src/languages/typescript/config.toml b/crates/zed/src/languages/typescript/config.toml index 3c2146e0015254ac69cecae7acc07422bf1bce28..4f006b342a4a420c956ba15ef747e10216212044 100644 --- a/crates/zed/src/languages/typescript/config.toml +++ b/crates/zed/src/languages/typescript/config.toml @@ -6,23 +6,9 @@ brackets = [ { start = "{", end = "}", close = true, newline = true }, { start = "[", end = "]", close = true, newline = true }, { start = "(", end = ")", close = true, newline = true }, - { start = "<", end = ">", close = false, newline = true }, - { start = "\"", end = "\"", close = true, newline = false }, - { start = "'", end = "'", close = true, newline = false }, - { start = "`", end = "`", close = true, newline = false }, - { start = "/*", end = " */", close = true, newline = false }, -] - -[overrides.comment] -brackets = [ - { start = "{", end = "}", close = true, newline = true }, - { start = "[", end = "]", close = true, newline = true }, - { start = "(", end = ")", close = true, newline = true }, -] - -[overrides.string] -brackets = [ - { start = "{", end = "}", close = true, newline = true }, - { start = "[", end = "]", close = true, newline = true }, - { start = "(", end = ")", close = true, newline = true }, + { start = "<", end = ">", close = false, newline = true, not_in = ["string", "comment"] }, + { start = "\"", end = "\"", close = true, newline = false, not_in = ["string"] }, + { start = "'", end = "'", close = true, newline = false, not_in = ["string", "comment"] }, + { start = "`", end = "`", close = true, newline = false, not_in = ["string"] }, + { start = "/*", end = " */", close = true, newline = false, not_in = ["string", "comment"] }, ] diff --git a/crates/zed/src/languages/yaml/config.toml b/crates/zed/src/languages/yaml/config.toml index 08dac475b370666aa6186ed55e397fbce7a4c7ba..6912d9245701dacd41c0c33fa49065d361dcbd22 100644 --- a/crates/zed/src/languages/yaml/config.toml +++ b/crates/zed/src/languages/yaml/config.toml @@ -5,13 +5,7 @@ autoclose_before = ",]}" brackets = [ { start = "{", end = "}", close = true, newline = true }, { start = "[", end = "]", close = true, newline = true }, - { start = "\"", end = "\"", close = true, newline = false }, + { start = "\"", end = "\"", close = true, newline = false, not_in = ["string"] }, ] increase_indent_pattern = ":\\s*[|>]?\\s*$" - -[overrides.string] -brackets = [ - { start = "{", end = "}", close = true, newline = true }, - { start = "[", end = "]", close = true, newline = true }, -] From 7c98395e77a0abb81c25c8e384980219fb2481e6 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Fri, 17 Feb 2023 09:44:14 -0800 Subject: [PATCH 2/5] Add missing comment pattern to TSX overrides query --- crates/zed/src/languages/tsx/overrides.scm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/zed/src/languages/tsx/overrides.scm b/crates/zed/src/languages/tsx/overrides.scm index d86186a903373bb8f1351141b5611ba48aa090ca..03066371b110eb728126a49043dd03b9fd7a5a2d 100644 --- a/crates/zed/src/languages/tsx/overrides.scm +++ b/crates/zed/src/languages/tsx/overrides.scm @@ -1,7 +1,8 @@ +(comment) @comment +(string) @string [ (jsx_element) (jsx_fragment) (jsx_self_closing_element) (jsx_expression) ] @element -(string) @string From 8be844a13f7684cd845276faed0316f9313d0105 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Fri, 17 Feb 2023 09:44:27 -0800 Subject: [PATCH 3/5] Add test that loads all bundled languages --- crates/language/src/language.rs | 18 ++++++++++++++++++ crates/zed/src/zed.rs | 15 ++++++++++++++- 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/crates/language/src/language.rs b/crates/language/src/language.rs index c84fc109ff431946db52a0fa725332622ff8c861..cb981b5e4ebfdc26a46546c089fc7a36f0a71fea 100644 --- a/crates/language/src/language.rs +++ b/crates/language/src/language.rs @@ -1017,6 +1017,24 @@ impl Language { ))?; } + for disabled_scope_name in self + .config + .brackets + .disabled_scopes_by_bracket_ix + .iter() + .flatten() + { + if !override_configs_by_id + .values() + .any(|(scope_name, _)| scope_name == disabled_scope_name) + { + Err(anyhow!( + "language {:?} has overrides in config not in query: {disabled_scope_name:?}", + self.config.name + ))?; + } + } + for (name, override_config) in override_configs_by_id.values_mut() { override_config.disabled_bracket_ixs = self .config diff --git a/crates/zed/src/zed.rs b/crates/zed/src/zed.rs index 16b5413fda2fe759e0f522e92fac0f074476df41..95790596bf1f2789ff860ce635b18fcc0451bc87 100644 --- a/crates/zed/src/zed.rs +++ b/crates/zed/src/zed.rs @@ -701,8 +701,9 @@ mod tests { use assets::Assets; use editor::{scroll::autoscroll::Autoscroll, DisplayPoint, Editor}; use gpui::{ - executor::Deterministic, AssetSource, MutableAppContext, TestAppContext, ViewHandle, + executor::Deterministic, AssetSource, MutableAppContext, Task, TestAppContext, ViewHandle, }; + use language::LanguageRegistry; use project::{Project, ProjectPath}; use serde_json::json; use std::{ @@ -1886,6 +1887,18 @@ mod tests { assert!(has_default_theme); } + #[gpui::test] + fn test_bundled_languages(cx: &mut MutableAppContext) { + let mut languages = LanguageRegistry::new(Task::ready(())); + languages.set_executor(cx.background().clone()); + let languages = Arc::new(languages); + languages::init(languages.clone()); + for name in languages.language_names() { + languages.language_for_name(&name); + } + cx.foreground().run_until_parked(); + } + fn init(cx: &mut TestAppContext) -> Arc { cx.foreground().forbid_parking(); cx.update(|cx| { From ab82e13167c3fabf26beaac94f4222b4686d5e80 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Mon, 20 Feb 2023 11:06:12 -0800 Subject: [PATCH 4/5] Run cargo fmt --- crates/collab/src/tests/integration_tests.rs | 9 +++++++-- crates/editor/src/editor.rs | 19 +++++++++++-------- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/crates/collab/src/tests/integration_tests.rs b/crates/collab/src/tests/integration_tests.rs index f2cb2eddbb56c74fe5feaca2b7a43ddc082a34c0..2fc19b005b7ded5a1212fb09e41f545d7191503c 100644 --- a/crates/collab/src/tests/integration_tests.rs +++ b/crates/collab/src/tests/integration_tests.rs @@ -2244,7 +2244,9 @@ async fn test_propagate_saves_and_fs_changes( }); // Edit the buffer as the host and concurrently save as guest B. - let save_b = project_b.update(cx_b, |project, cx| project.save_buffer(buffer_b.clone(), cx)); + let save_b = project_b.update(cx_b, |project, cx| { + project.save_buffer(buffer_b.clone(), cx) + }); buffer_a.update(cx_a, |buf, cx| buf.edit([(0..0, "hi-a, ")], None, cx)); save_b.await.unwrap(); assert_eq!( @@ -2917,7 +2919,10 @@ async fn test_buffer_conflict_after_save( assert!(!buf.has_conflict()); }); - project_b.update(cx_b, |project, cx| project.save_buffer(buffer_b.clone(), cx)) + project_b + .update(cx_b, |project, cx| { + project.save_buffer(buffer_b.clone(), cx) + }) .await .unwrap(); cx_a.foreground().forbid_parking(); diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 787f7b8514b2e72829b7f9b8b704a9ad2664ccbd..dde01054704bdc63c20c06e18088192aa5202851 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -84,7 +84,7 @@ use std::{ }; pub use sum_tree::Bias; use theme::{DiagnosticStyle, Theme}; -use util::{post_inc, ResultExt, TryFutureExt, RangeExt}; +use util::{post_inc, RangeExt, ResultExt, TryFutureExt}; use workspace::{ItemNavHistory, ViewId, Workspace, WorkspaceId}; use crate::git::diff_hunk_to_display; @@ -1934,7 +1934,8 @@ impl Editor { let pair_start = pair.start.trim_end(); let pair_end = pair.end.trim_start(); - enabled && pair.newline + enabled + && pair.newline && buffer .contains_str_at(end + trailing_whitespace_len, pair_end) && buffer.contains_str_at( @@ -4790,8 +4791,10 @@ impl Editor { ) { self.change_selections(Some(Autoscroll::fit()), cx, |s| { s.move_offsets_with(|snapshot, selection| { - let Some(enclosing_bracket_ranges) = snapshot.enclosing_bracket_ranges(selection.start..selection.end) else { return; }; - + let Some(enclosing_bracket_ranges) = snapshot.enclosing_bracket_ranges(selection.start..selection.end) else { + return; + }; + let mut best_length = usize::MAX; let mut best_inside = false; let mut best_in_bracket_range = false; @@ -4801,17 +4804,17 @@ impl Editor { let length = close.end() - open.start; let inside = selection.start >= open.end && selection.end <= *close.start(); let in_bracket_range = open.to_inclusive().contains(&selection.head()) || close.contains(&selection.head()); - + // If best is next to a bracket and current isn't, skip if !in_bracket_range && best_in_bracket_range { continue; } - + // Prefer smaller lengths unless best is inside and current isn't if length > best_length && (best_inside || !inside) { continue; } - + best_length = length; best_inside = inside; best_in_bracket_range = in_bracket_range; @@ -4829,7 +4832,7 @@ impl Editor { } }); } - + if let Some(destination) = best_destination { selection.collapse_to(destination, SelectionGoal::None); } From a11165ad0aa90f29833f501fd59a4d9a5f30a456 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Mon, 20 Feb 2023 13:46:17 -0800 Subject: [PATCH 5/5] Add unit test for auto-closing quotation marks with overrides --- crates/editor/src/editor_tests.rs | 98 +++++++++++++++++++++++++++++++ crates/language/src/language.rs | 2 +- 2 files changed, 99 insertions(+), 1 deletion(-) diff --git a/crates/editor/src/editor_tests.rs b/crates/editor/src/editor_tests.rs index 64ff6dec38873671ffc98fe3bec613c203913166..94699a8d5a3da3939e339e6824c050a81acccd01 100644 --- a/crates/editor/src/editor_tests.rs +++ b/crates/editor/src/editor_tests.rs @@ -13,6 +13,7 @@ use gpui::{ executor::Deterministic, geometry::{rect::RectF, vector::vec2f}, platform::{WindowBounds, WindowOptions}, + serde_json, }; use language::{BracketPairConfig, FakeLspAdapter, LanguageConfig, LanguageRegistry, Point}; use project::FakeFs; @@ -3459,6 +3460,103 @@ async fn test_autoclose_with_embedded_language(cx: &mut gpui::TestAppContext) { ); } +#[gpui::test] +async fn test_autoclose_with_overrides(cx: &mut gpui::TestAppContext) { + let mut cx = EditorTestContext::new(cx); + + let rust_language = Arc::new( + Language::new( + LanguageConfig { + name: "Rust".into(), + brackets: serde_json::from_value(json!([ + { "start": "{", "end": "}", "close": true, "newline": true }, + { "start": "\"", "end": "\"", "close": true, "newline": false, "not_in": ["string"] }, + ])) + .unwrap(), + autoclose_before: "})]>".into(), + ..Default::default() + }, + Some(tree_sitter_rust::language()), + ) + .with_override_query("(string_literal) @string") + .unwrap(), + ); + + let registry = Arc::new(LanguageRegistry::test()); + registry.add(rust_language.clone()); + + cx.update_buffer(|buffer, cx| { + buffer.set_language_registry(registry); + buffer.set_language(Some(rust_language), cx); + }); + + cx.set_state( + &r#" + let x = ˇ + "# + .unindent(), + ); + + // Inserting a quotation mark. A closing quotation mark is automatically inserted. + cx.update_editor(|editor, cx| { + editor.handle_input("\"", cx); + }); + cx.assert_editor_state( + &r#" + let x = "ˇ" + "# + .unindent(), + ); + + // Inserting another quotation mark. The cursor moves across the existing + // automatically-inserted quotation mark. + cx.update_editor(|editor, cx| { + editor.handle_input("\"", cx); + }); + cx.assert_editor_state( + &r#" + let x = ""ˇ + "# + .unindent(), + ); + + // Reset + cx.set_state( + &r#" + let x = ˇ + "# + .unindent(), + ); + + // Inserting a quotation mark inside of a string. A second quotation mark is not inserted. + cx.update_editor(|editor, cx| { + editor.handle_input("\"", cx); + editor.handle_input(" ", cx); + editor.move_left(&Default::default(), cx); + editor.handle_input("\\", cx); + editor.handle_input("\"", cx); + }); + cx.assert_editor_state( + &r#" + let x = "\"ˇ " + "# + .unindent(), + ); + + // Inserting a closing quotation mark at the position of an automatically-inserted quotation + // mark. Nothing is inserted. + cx.update_editor(|editor, cx| { + editor.move_right(&Default::default(), cx); + editor.handle_input("\"", cx); + }); + cx.assert_editor_state( + &r#" + let x = "\" "ˇ + "# + .unindent(), + ); +} + #[gpui::test] async fn test_surround_with_pair(cx: &mut gpui::TestAppContext) { cx.update(|cx| cx.set_global(Settings::test(cx))); diff --git a/crates/language/src/language.rs b/crates/language/src/language.rs index cb981b5e4ebfdc26a46546c089fc7a36f0a71fea..983bc58f762e24a01fa1d9ff1beeca7585dda1e8 100644 --- a/crates/language/src/language.rs +++ b/crates/language/src/language.rs @@ -258,7 +258,7 @@ pub struct LanguageQueries { pub overrides: Option>, } -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct LanguageScope { language: Arc, override_id: Option,