From 5ae3b1586282773f0c38f83df7fc59f8776bc6ea Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Sun, 9 Nov 2025 01:40:58 +0200 Subject: [PATCH] Fix previous bracket coloring overwriting --- crates/editor/src/bracket_colorization.rs | 23 +++++++++++-------- crates/language/src/buffer.rs | 28 ++++++++++++++++------- crates/language/src/buffer/row_chunk.rs | 8 +++++++ 3 files changed, 42 insertions(+), 17 deletions(-) diff --git a/crates/editor/src/bracket_colorization.rs b/crates/editor/src/bracket_colorization.rs index 6da68a25fe95080a366a522514baee9572046b22..2e27f585f978b00681db222f21e935f230a168c0 100644 --- a/crates/editor/src/bracket_colorization.rs +++ b/crates/editor/src/bracket_colorization.rs @@ -16,8 +16,9 @@ impl Editor { self.fetched_tree_sitter_chunks.clear(); } + let accents_count = cx.theme().accents().0.len(); let multi_buffer_snapshot = self.buffer().read(cx).snapshot(cx); - let bracket_matches = self.visible_excerpts(cx).into_iter().fold( + let bracket_matches_by_accent = self.visible_excerpts(cx).into_iter().fold( HashMap::default(), |mut acc, (excerpt_id, (buffer, buffer_version, buffer_range))| { let buffer_snapshot = buffer.read(cx).snapshot(); @@ -33,7 +34,7 @@ impl Editor { .entry(excerpt_id) .or_default(); - for (depth, open_range, close_range) in buffer_snapshot + let brackets_by_accent = buffer_snapshot .fetch_bracket_ranges( buffer_range.start..buffer_range.end, Some((&buffer_version, fetched_chunks)), @@ -61,14 +62,18 @@ impl Editor { .anchor_in_excerpt(excerpt_id, buffer_close_range.start)? ..multi_buffer_snapshot .anchor_in_excerpt(excerpt_id, buffer_close_range.end)?; + + let accent_number = pair.id % accents_count; + Some(( - pair.depth, + accent_number, multi_buffer_open_range, multi_buffer_close_range, )) - }) - { - let ranges = acc.entry(depth).or_insert_with(Vec::new); + }); + + for (accent_number, open_range, close_range) in brackets_by_accent { + let ranges = acc.entry(accent_number).or_insert_with(Vec::new); ranges.push(open_range); ranges.push(close_range); } @@ -83,8 +88,8 @@ impl Editor { } let editor_background = cx.theme().colors().editor_background; - for (depth, bracket_highlights) in bracket_matches { - let bracket_color = cx.theme().accents().color_for_index(depth as u32); + for (accent_number, bracket_highlights) in bracket_matches_by_accent { + let bracket_color = cx.theme().accents().color_for_index(accent_number as u32); let adjusted_color = ensure_minimum_contrast(bracket_color, editor_background, 55.0); let style = HighlightStyle { color: Some(adjusted_color), @@ -92,7 +97,7 @@ impl Editor { }; self.highlight_text_key::( - depth, + accent_number, bracket_highlights, style, true, diff --git a/crates/language/src/buffer.rs b/crates/language/src/buffer.rs index 7b8c8d678eed96d2acf62bd48b07230651763b7e..7f2907627a329ae7662e32d4d7e25a6386a08145 100644 --- a/crates/language/src/buffer.rs +++ b/crates/language/src/buffer.rs @@ -67,7 +67,7 @@ pub use text::{ use theme::{ActiveTheme as _, SyntaxTheme}; #[cfg(any(test, feature = "test-support"))] use util::RandomCharIter; -use util::{RangeExt, debug_panic, maybe, paths::PathStyle, rel_path::RelPath}; +use util::{RangeExt, debug_panic, maybe, paths::PathStyle, post_inc, rel_path::RelPath}; #[cfg(any(test, feature = "test-support"))] pub use {tree_sitter_python, tree_sitter_rust, tree_sitter_typescript}; @@ -850,7 +850,7 @@ pub struct BracketMatch { pub open_range: Range, pub close_range: Range, pub newline_only: bool, - pub depth: usize, + pub id: usize, } impl BracketMatch { @@ -4191,6 +4191,23 @@ impl BufferSnapshot { let bracket_matches = match tree_sitter_data.brackets_by_chunks[chunk.id].take() { Some(cached_brackets) => cached_brackets, None => { + // Sequential IDs are needed to determine the color of the bracket pair. + let mut next_id = match tree_sitter_data.chunks.previous_chunk(chunk) { + Some(previous_chunk) => tree_sitter_data.brackets_by_chunks + [previous_chunk.id] + .as_ref() + .and_then(|previous_brackets| previous_brackets.last()) + // Try to continue previous sequence of IDs. + .map(|bracket| bracket.id + 1) + // If not possible, start another sequence: pick it far enough to avoid overlaps. + // + // This for sure will introduce the gaps between chunks' bracket IDs, + // but this will only potentially skip `mod(accents_number)` colors between chunks. + .unwrap_or_else(|| { + (usize::MAX / tree_sitter_data.chunks.len()) * chunk.id + 1 + }), + None => 0, + }; let mut matches = self.syntax .matches(chunk_range.clone(), &self.text, |grammar| { @@ -4202,9 +4219,6 @@ impl BufferSnapshot { .map(|grammar| grammar.brackets_config.as_ref().unwrap()) .collect::>(); - // todo! this seems like a wrong parameter: add bracket_id that will be used for each bracket - // this will require changing `depth` treatment during style application, we'll need to group brackets by their hsla - let mut depth = 0; let chunk_range = chunk_range.clone(); let new_matches = iter::from_fn(move || { while let Some(mat) = matches.peek() { @@ -4231,13 +4245,11 @@ impl BufferSnapshot { continue; } - depth += 1; - return Some(BracketMatch { open_range, close_range, newline_only: pattern.newline_only, - depth, + id: post_inc(&mut next_id), }); } None diff --git a/crates/language/src/buffer/row_chunk.rs b/crates/language/src/buffer/row_chunk.rs index 955676e557f69285f856a1df6db93f12e1590afa..fd1936ea39fec7512d1f6e27b3f7e177c3de069e 100644 --- a/crates/language/src/buffer/row_chunk.rs +++ b/crates/language/src/buffer/row_chunk.rs @@ -97,6 +97,14 @@ impl RowChunks { }; Some(self.snapshot.anchor_before(start)..self.snapshot.anchor_after(end)) } + + pub fn previous_chunk(&self, chunk: RowChunk) -> Option { + if chunk.id == 0 { + None + } else { + self.chunks.get(chunk.id - 1).copied() + } + } } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]