Detailed changes
@@ -3600,7 +3600,7 @@ impl Editor {
refresh_linked_ranges(self, window, cx);
self.refresh_selected_text_highlights(false, window, cx);
- self.refresh_matching_bracket_highlights(window, cx);
+ self.refresh_matching_bracket_highlights(&display_map, cx);
self.refresh_outline_symbols(cx);
self.update_visible_edit_prediction(window, cx);
self.edit_prediction_requires_modifier_in_indent_conflict = true;
@@ -20265,22 +20265,46 @@ impl Editor {
}
pub fn fold_buffer(&mut self, buffer_id: BufferId, cx: &mut Context<Self>) {
- if self.buffer().read(cx).is_singleton() || self.is_buffer_folded(buffer_id, cx) {
+ self.fold_buffers([buffer_id], cx);
+ }
+
+ pub fn fold_buffers(
+ &mut self,
+ buffer_ids: impl IntoIterator<Item = BufferId>,
+ cx: &mut Context<Self>,
+ ) {
+ if self.buffer().read(cx).is_singleton() {
return;
}
- let folded_excerpts = self.buffer().read(cx).excerpts_for_buffer(buffer_id, cx);
+ let ids_to_fold: Vec<BufferId> = buffer_ids
+ .into_iter()
+ .filter(|id| !self.is_buffer_folded(*id, cx))
+ .collect();
+
+ if ids_to_fold.is_empty() {
+ return;
+ }
+
+ let mut all_folded_excerpt_ids = Vec::new();
+ for buffer_id in &ids_to_fold {
+ let folded_excerpts = self.buffer().read(cx).excerpts_for_buffer(*buffer_id, cx);
+ all_folded_excerpt_ids.extend(folded_excerpts.into_iter().map(|(id, _)| id));
+ }
+
self.display_map.update(cx, |display_map, cx| {
- display_map.fold_buffers([buffer_id], cx)
+ display_map.fold_buffers(ids_to_fold.clone(), cx)
});
let snapshot = self.display_snapshot(cx);
self.selections.change_with(&snapshot, |selections| {
- selections.remove_selections_from_buffer(buffer_id);
+ for buffer_id in ids_to_fold {
+ selections.remove_selections_from_buffer(buffer_id);
+ }
});
cx.emit(EditorEvent::BufferFoldToggled {
- ids: folded_excerpts.iter().map(|&(id, _)| id).collect(),
+ ids: all_folded_excerpt_ids,
folded: true,
});
cx.notify();
@@ -23856,9 +23880,10 @@ impl Editor {
self.refresh_active_diagnostics(cx);
self.refresh_code_actions(window, cx);
self.refresh_single_line_folds(window, cx);
- self.refresh_matching_bracket_highlights(window, cx);
+ let snapshot = self.snapshot(window, cx);
+ self.refresh_matching_bracket_highlights(&snapshot, cx);
self.refresh_outline_symbols(cx);
- self.refresh_sticky_headers(&self.snapshot(window, cx), cx);
+ self.refresh_sticky_headers(&snapshot, cx);
if self.has_active_edit_prediction() {
self.update_visible_edit_prediction(window, cx);
}
@@ -1,5 +1,5 @@
-use crate::{Editor, HighlightKey, RangeToAnchorExt};
-use gpui::{AppContext, Context, HighlightStyle, Window};
+use crate::{Editor, HighlightKey, RangeToAnchorExt, display_map::DisplaySnapshot};
+use gpui::{AppContext, Context, HighlightStyle};
use language::CursorShape;
use multi_buffer::MultiBufferOffset;
use theme::ActiveTheme;
@@ -8,12 +8,11 @@ impl Editor {
#[ztracing::instrument(skip_all)]
pub fn refresh_matching_bracket_highlights(
&mut self,
- window: &Window,
+ snapshot: &DisplaySnapshot,
cx: &mut Context<Editor>,
) {
self.clear_highlights(HighlightKey::MatchingBracket, cx);
- let snapshot = self.snapshot(window, cx);
let newest_selection = self.selections.newest::<MultiBufferOffset>(&snapshot);
// Don't highlight brackets if the selection isn't empty
if !newest_selection.is_empty() {
@@ -39,29 +38,31 @@ impl Editor {
let buffer_snapshot = buffer_snapshot.clone();
async move { buffer_snapshot.innermost_enclosing_bracket_ranges(head..tail, None) }
});
- self.refresh_matching_bracket_highlights_task = cx.spawn(async move |editor, cx| {
- if let Some((opening_range, closing_range)) = task.await {
- let buffer_snapshot = snapshot.buffer_snapshot();
- editor
- .update(cx, |editor, cx| {
- editor.highlight_text(
- HighlightKey::MatchingBracket,
- vec![
- opening_range.to_anchors(&buffer_snapshot),
- closing_range.to_anchors(&buffer_snapshot),
- ],
- HighlightStyle {
- background_color: Some(
- cx.theme()
- .colors()
- .editor_document_highlight_bracket_background,
- ),
- ..Default::default()
- },
- cx,
- )
- })
- .ok();
+ self.refresh_matching_bracket_highlights_task = cx.spawn({
+ let buffer_snapshot = buffer_snapshot.clone();
+ async move |editor, cx| {
+ if let Some((opening_range, closing_range)) = task.await {
+ editor
+ .update(cx, |editor, cx| {
+ editor.highlight_text(
+ HighlightKey::MatchingBracket,
+ vec![
+ opening_range.to_anchors(&buffer_snapshot),
+ closing_range.to_anchors(&buffer_snapshot),
+ ],
+ HighlightStyle {
+ background_color: Some(
+ cx.theme()
+ .colors()
+ .editor_document_highlight_bracket_background,
+ ),
+ ..Default::default()
+ },
+ cx,
+ )
+ })
+ .ok();
+ }
}
});
}
@@ -362,9 +362,7 @@ impl CommitView {
});
if !binary_buffer_ids.is_empty() {
this.editor.update(cx, |editor, cx| {
- for buffer_id in binary_buffer_ids {
- editor.fold_buffer(buffer_id, cx);
- }
+ editor.fold_buffers(binary_buffer_ids, cx);
});
}
})?;
@@ -24,7 +24,7 @@ use gpui::{
Action, AnyElement, App, AppContext as _, AsyncWindowContext, Entity, EventEmitter,
FocusHandle, Focusable, Render, Subscription, Task, WeakEntity, actions,
};
-use language::{Anchor, Buffer, Capability, OffsetRangeExt};
+use language::{Anchor, Buffer, BufferId, Capability, OffsetRangeExt};
use multi_buffer::{MultiBuffer, PathKey};
use project::{
Project, ProjectPath,
@@ -608,7 +608,7 @@ impl ProjectDiff {
diff: Entity<BufferDiff>,
window: &mut Window,
cx: &mut Context<Self>,
- ) {
+ ) -> Option<BufferId> {
let subscription = cx.subscribe_in(&diff, window, move |this, _, _, window, cx| {
this._task = window.spawn(cx, {
let this = cx.weak_entity();
@@ -653,6 +653,8 @@ impl ProjectDiff {
}
};
+ let mut needs_fold = None;
+
let (was_empty, is_excerpt_newly_added) = self.editor.update(cx, |editor, cx| {
let was_empty = editor.rhs_editor().read(cx).buffer().read(cx).is_empty();
let (_, is_newly_added) = editor.set_excerpts_for_path(
@@ -685,7 +687,7 @@ impl ProjectDiff {
|| (file_status.is_untracked()
&& GitPanelSettings::get_global(cx).collapse_untracked_diff))
{
- editor.fold_buffer(snapshot.text.remote_id(), cx)
+ needs_fold = Some(snapshot.text.remote_id());
}
})
});
@@ -706,6 +708,8 @@ impl ProjectDiff {
if self.pending_scroll.as_ref() == Some(&path_key) {
self.move_to_path(path_key, window, cx);
}
+
+ needs_fold
}
#[instrument(skip_all)]
@@ -761,6 +765,8 @@ impl ProjectDiff {
buffers_to_load
})?;
+ let mut buffers_to_fold = Vec::new();
+
for (entry, path_key) in buffers_to_load.into_iter().zip(path_keys.into_iter()) {
if let Some((buffer, diff)) = entry.load.await.log_err() {
// We might be lagging behind enough that all future entry.load futures are no longer pending.
@@ -780,14 +786,16 @@ impl ProjectDiff {
RefreshReason::StatusesChanged => false,
};
if !skip {
- this.register_buffer(
+ if let Some(buffer_id) = this.register_buffer(
path_key,
entry.file_status,
buffer,
diff,
window,
cx,
- )
+ ) {
+ buffers_to_fold.push(buffer_id);
+ }
}
})
.ok();
@@ -795,6 +803,13 @@ impl ProjectDiff {
}
}
this.update(cx, |this, cx| {
+ if !buffers_to_fold.is_empty() {
+ this.editor.update(cx, |editor, cx| {
+ editor
+ .rhs_editor()
+ .update(cx, |editor, cx| editor.fold_buffers(buffers_to_fold, cx));
+ });
+ }
this.pending_scroll.take();
cx.notify();
})?;