Detailed changes
@@ -9810,26 +9810,30 @@ mod tests {
#[gpui::test]
async fn test_extra_newline_insertion(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,
- newline: true,
- },
- ],
- ..Default::default()
- },
- Some(tree_sitter_rust::language()),
- ));
+ 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,
+ },
+ ],
+ ..Default::default()
+ },
+ Some(tree_sitter_rust::language()),
+ )
+ .with_indents_query("")
+ .unwrap(),
+ );
let text = concat!(
"{ }\n", // Suppress rustfmt
@@ -1523,16 +1523,17 @@ impl BufferSnapshot {
// Get the "indentation ranges" that intersect this row range.
let grammar = self.grammar()?;
let prev_non_blank_row = self.prev_non_blank_row(row_range.start);
+ let indents_query = grammar.indents_query.as_ref()?;
let mut query_cursor = QueryCursorHandle::new();
- let indent_capture_ix = grammar.indents_query.capture_index_for_name("indent");
- let end_capture_ix = grammar.indents_query.capture_index_for_name("end");
+ let indent_capture_ix = indents_query.capture_index_for_name("indent");
+ let end_capture_ix = indents_query.capture_index_for_name("end");
query_cursor.set_point_range(
Point::new(prev_non_blank_row.unwrap_or(row_range.start), 0).to_ts_point()
..Point::new(row_range.end, 0).to_ts_point(),
);
let mut indentation_ranges = Vec::<Range<Point>>::new();
for mat in query_cursor.matches(
- &grammar.indents_query,
+ indents_query,
self.tree.as_ref()?.root_node(),
TextProvider(self.as_rope()),
) {
@@ -1787,20 +1788,20 @@ impl BufferSnapshot {
.as_ref()
.and_then(|language| language.grammar.as_ref())?;
+ let outline_query = grammar.outline_query.as_ref()?;
let mut cursor = QueryCursorHandle::new();
cursor.set_byte_range(range.clone());
let matches = cursor.matches(
- &grammar.outline_query,
+ outline_query,
tree.root_node(),
TextProvider(self.as_rope()),
);
let mut chunks = self.chunks(0..self.len(), true);
- let item_capture_ix = grammar.outline_query.capture_index_for_name("item")?;
- let name_capture_ix = grammar.outline_query.capture_index_for_name("name")?;
- let context_capture_ix = grammar
- .outline_query
+ let item_capture_ix = outline_query.capture_index_for_name("item")?;
+ let name_capture_ix = outline_query.capture_index_for_name("name")?;
+ let context_capture_ix = outline_query
.capture_index_for_name("context")
.unwrap_or(u32::MAX);
@@ -1892,14 +1893,15 @@ impl BufferSnapshot {
range: Range<T>,
) -> Option<(Range<usize>, Range<usize>)> {
let (grammar, tree) = self.grammar().zip(self.tree.as_ref())?;
- let open_capture_ix = grammar.brackets_query.capture_index_for_name("open")?;
- let close_capture_ix = grammar.brackets_query.capture_index_for_name("close")?;
+ let brackets_query = grammar.brackets_query.as_ref()?;
+ let open_capture_ix = brackets_query.capture_index_for_name("open")?;
+ let close_capture_ix = brackets_query.capture_index_for_name("close")?;
// Find bracket pairs that *inclusively* contain the given range.
let range = range.start.to_offset(self).saturating_sub(1)..range.end.to_offset(self) + 1;
let mut cursor = QueryCursorHandle::new();
let matches = cursor.set_byte_range(range).matches(
- &grammar.brackets_query,
+ &brackets_query,
tree.root_node(),
TextProvider(self.as_rope()),
);
@@ -2071,24 +2073,26 @@ impl<'a> BufferChunks<'a> {
) -> Self {
let mut highlights = None;
if let Some((grammar, tree)) = grammar.zip(tree) {
- let mut query_cursor = QueryCursorHandle::new();
+ if let Some(highlights_query) = grammar.highlights_query.as_ref() {
+ let mut query_cursor = QueryCursorHandle::new();
- // TODO - add a Tree-sitter API to remove the need for this.
- let cursor = unsafe {
- std::mem::transmute::<_, &'static mut QueryCursor>(query_cursor.deref_mut())
- };
- let captures = cursor.set_byte_range(range.clone()).captures(
- &grammar.highlights_query,
- tree.root_node(),
- TextProvider(text),
- );
- highlights = Some(BufferChunkHighlights {
- captures,
- next_capture: None,
- stack: Default::default(),
- highlight_map: grammar.highlight_map(),
- _query_cursor: query_cursor,
- })
+ // TODO - add a Tree-sitter API to remove the need for this.
+ let cursor = unsafe {
+ std::mem::transmute::<_, &'static mut QueryCursor>(query_cursor.deref_mut())
+ };
+ let captures = cursor.set_byte_range(range.clone()).captures(
+ highlights_query,
+ tree.root_node(),
+ TextProvider(text),
+ );
+ highlights = Some(BufferChunkHighlights {
+ captures,
+ next_capture: None,
+ stack: Default::default(),
+ highlight_map: grammar.highlight_map(),
+ _query_cursor: query_cursor,
+ })
+ }
}
let diagnostic_endpoints = diagnostic_endpoints.into_iter().peekable();
@@ -171,10 +171,10 @@ pub struct Language {
pub struct Grammar {
pub(crate) ts_language: tree_sitter::Language,
- pub(crate) highlights_query: Query,
- pub(crate) brackets_query: Query,
- pub(crate) indents_query: Query,
- pub(crate) outline_query: Query,
+ pub(crate) highlights_query: Option<Query>,
+ pub(crate) brackets_query: Option<Query>,
+ pub(crate) indents_query: Option<Query>,
+ pub(crate) outline_query: Option<Query>,
pub(crate) highlight_map: Mutex<HighlightMap>,
}
@@ -437,10 +437,10 @@ impl Language {
config,
grammar: ts_language.map(|ts_language| {
Arc::new(Grammar {
- brackets_query: Query::new(ts_language, "").unwrap(),
- highlights_query: Query::new(ts_language, "").unwrap(),
- indents_query: Query::new(ts_language, "").unwrap(),
- outline_query: Query::new(ts_language, "").unwrap(),
+ highlights_query: None,
+ brackets_query: None,
+ indents_query: None,
+ outline_query: None,
ts_language,
highlight_map: Default::default(),
})
@@ -457,45 +457,33 @@ impl Language {
}
pub fn with_highlights_query(mut self, source: &str) -> Result<Self> {
- let grammar = self
- .grammar
- .as_mut()
- .and_then(Arc::get_mut)
- .ok_or_else(|| anyhow!("grammar does not exist or is already being used"))?;
- grammar.highlights_query = Query::new(grammar.ts_language, source)?;
+ let grammar = self.grammar_mut();
+ grammar.highlights_query = Some(Query::new(grammar.ts_language, source)?);
Ok(self)
}
pub fn with_brackets_query(mut self, source: &str) -> Result<Self> {
- let grammar = self
- .grammar
- .as_mut()
- .and_then(Arc::get_mut)
- .ok_or_else(|| anyhow!("grammar does not exist or is already being used"))?;
- grammar.brackets_query = Query::new(grammar.ts_language, source)?;
+ let grammar = self.grammar_mut();
+ grammar.brackets_query = Some(Query::new(grammar.ts_language, source)?);
Ok(self)
}
pub fn with_indents_query(mut self, source: &str) -> Result<Self> {
- let grammar = self
- .grammar
- .as_mut()
- .and_then(Arc::get_mut)
- .ok_or_else(|| anyhow!("grammar does not exist or is already being used"))?;
- grammar.indents_query = Query::new(grammar.ts_language, source)?;
+ let grammar = self.grammar_mut();
+ grammar.indents_query = Some(Query::new(grammar.ts_language, source)?);
Ok(self)
}
pub fn with_outline_query(mut self, source: &str) -> Result<Self> {
- let grammar = self
- .grammar
- .as_mut()
- .and_then(Arc::get_mut)
- .ok_or_else(|| anyhow!("grammar does not exist or is already being used"))?;
- grammar.outline_query = Query::new(grammar.ts_language, source)?;
+ let grammar = self.grammar_mut();
+ grammar.outline_query = Some(Query::new(grammar.ts_language, source)?);
Ok(self)
}
+ fn grammar_mut(&mut self) -> &mut Grammar {
+ Arc::get_mut(self.grammar.as_mut().unwrap()).unwrap()
+ }
+
pub fn with_lsp_adapter(mut self, lsp_adapter: Arc<dyn LspAdapter>) -> Self {
self.adapter = Some(lsp_adapter);
self
@@ -586,8 +574,10 @@ impl Language {
pub fn set_theme(&self, theme: &SyntaxTheme) {
if let Some(grammar) = self.grammar.as_ref() {
- *grammar.highlight_map.lock() =
- HighlightMap::new(grammar.highlights_query.capture_names(), theme);
+ if let Some(highlights_query) = &grammar.highlights_query {
+ *grammar.highlight_map.lock() =
+ HighlightMap::new(highlights_query.capture_names(), theme);
+ }
}
}
@@ -621,7 +611,10 @@ impl Grammar {
}
pub fn highlight_id_for_name(&self, name: &str) -> Option<HighlightId> {
- let capture_id = self.highlights_query.capture_index_for_name(name)?;
+ let capture_id = self
+ .highlights_query
+ .as_ref()?
+ .capture_index_for_name(name)?;
Some(self.highlight_map.lock().get(capture_id))
}
}
@@ -784,6 +784,47 @@ fn test_autoindent_with_edit_at_end_of_buffer(cx: &mut MutableAppContext) {
});
}
+#[gpui::test]
+fn test_autoindent_disabled(cx: &mut MutableAppContext) {
+ cx.add_model(|cx| {
+ let text = "
+ * one
+ - a
+ - b
+ * two
+ "
+ .unindent();
+
+ let mut buffer = Buffer::new(0, text, cx).with_language(
+ Arc::new(Language::new(
+ LanguageConfig {
+ name: "Markdown".into(),
+ ..Default::default()
+ },
+ Some(tree_sitter_json::language()),
+ )),
+ cx,
+ );
+ buffer.edit_with_autoindent(
+ [(Point::new(3, 0)..Point::new(3, 0), "\n")],
+ IndentSize::spaces(4),
+ cx,
+ );
+ assert_eq!(
+ buffer.text(),
+ "
+ * one
+ - a
+ - b
+
+ * two
+ "
+ .unindent()
+ );
+ buffer
+ });
+}
+
#[gpui::test]
fn test_serialization(cx: &mut gpui::MutableAppContext) {
let mut now = Instant::now();