From e903742d52b8b9495298cd890265ae16c39a0fdd Mon Sep 17 00:00:00 2001 From: Bennet Bo Fenner Date: Thu, 23 May 2024 17:44:31 +0200 Subject: [PATCH] indent guides: Cache active indent range (#12204) Caching the active indent range allows us to not re-compute the indent range when it is not necessary Release Notes: - N/A --- crates/editor/src/indent_guides.rs | 57 +++++++++++++++++++++++++++--- 1 file changed, 52 insertions(+), 5 deletions(-) diff --git a/crates/editor/src/indent_guides.rs b/crates/editor/src/indent_guides.rs index eb63050f70991c0d742ccbb39264b6cf370e6708..377fd25a25049bd8a2eb71678a49d152006976f4 100644 --- a/crates/editor/src/indent_guides.rs +++ b/crates/editor/src/indent_guides.rs @@ -25,8 +25,8 @@ pub struct ActiveIndentGuidesState { } impl ActiveIndentGuidesState { - pub fn should_refresh(&self, cursor_row: MultiBufferRow) -> bool { - self.pending_refresh.is_none() && (self.cursor_row != cursor_row || self.dirty) + pub fn should_refresh(&self) -> bool { + self.pending_refresh.is_none() && self.dirty } } @@ -56,12 +56,27 @@ impl Editor { let cursor_row = MultiBufferRow(selection.head().row); let state = &mut self.active_indent_guides_state; - if state.cursor_row != cursor_row { - state.cursor_row = cursor_row; + + if state + .active_indent_range + .as_ref() + .map(|active_indent_range| { + should_recalculate_indented_range( + state.cursor_row, + cursor_row, + active_indent_range, + snapshot, + ) + }) + .unwrap_or(true) + { state.dirty = true; + } else { + state.cursor_row = cursor_row; } - if state.should_refresh(cursor_row) { + if state.should_refresh() { + state.cursor_row = cursor_row; let snapshot = snapshot.clone(); state.dirty = false; @@ -159,3 +174,35 @@ async fn resolve_indented_range( buffer_id, }) } + +fn should_recalculate_indented_range( + prev_row: MultiBufferRow, + new_row: MultiBufferRow, + current_indent_range: &ActiveIndentedRange, + snapshot: &DisplaySnapshot, +) -> bool { + if prev_row.0 == new_row.0 { + return false; + } + if let Some((_, _, snapshot)) = snapshot.buffer_snapshot.as_singleton() { + if !current_indent_range.row_range.contains(&new_row.0) { + return true; + } + + let (old_indent, old_is_blank) = snapshot.line_indent_for_row(prev_row.0); + let (new_indent, new_is_blank) = snapshot.line_indent_for_row(new_row.0); + + if old_is_blank + || new_is_blank + || old_indent != new_indent + || snapshot.max_point().row == new_row.0 + { + return true; + } + + let (next_line_indent, next_line_is_blank) = snapshot.line_indent_for_row(new_row.0 + 1); + next_line_is_blank || next_line_indent != old_indent + } else { + true + } +}