Detailed changes
@@ -472,7 +472,6 @@ impl DisplayMap {
}
}
- // TODO(split-diff) figure out how to free the LHS from having to build a block map before this is called
pub(crate) fn set_companion(
&mut self,
companion: Option<(Entity<DisplayMap>, Entity<Companion>)>,
@@ -485,26 +484,31 @@ impl DisplayMap {
let Some((_, companion)) = self.companion.take() else {
return;
};
- let (snapshot, edits) = self.sync_through_wrap(cx);
- let edits = edits.compose([text::Edit {
- old: WrapRow(0)..snapshot.max_point().row(),
- new: WrapRow(0)..snapshot.max_point().row(),
+ assert_eq!(self.entity_id, companion.read(cx).rhs_display_map_id);
+ let (snapshot, _edits) = self.sync_through_wrap(cx);
+ let edits = Patch::new(vec![text::Edit {
+ old: WrapRow(0)
+ ..self.block_map.wrap_snapshot.borrow().max_point().row() + WrapRow(1),
+ new: WrapRow(0)..snapshot.max_point().row() + WrapRow(1),
}]);
- self.block_map.write(snapshot, edits, None).remove(
- companion
+ self.block_map.deferred_edits.set(edits);
+ self.block_map.retain_blocks_raw(|block| {
+ if companion
.read(cx)
.lhs_custom_block_to_balancing_block
.borrow()
.values()
- .copied()
- .collect(),
- );
+ .any(|id| *id == block.id)
+ {
+ return false;
+ }
+ true
+ });
return;
};
assert_eq!(self.entity_id, companion.read(cx).rhs_display_map_id);
- // Note, throwing away the wrap edits because we're going to recompute the maximal range for the block map regardless
- let old_max_row = self.block_map.wrap_snapshot.borrow().max_point().row();
+ // Note, throwing away the wrap edits because we defer spacer computation to the first render.
let snapshot = {
let edits = self.buffer_subscription.consume();
let snapshot = self.buffer.read(cx).snapshot(cx);
@@ -528,28 +532,16 @@ impl DisplayMap {
snapshot
};
- let (companion_wrap_snapshot, companion_wrap_edits) =
+ let (companion_wrap_snapshot, _companion_wrap_edits) =
companion_display_map.update(cx, |dm, cx| dm.sync_through_wrap(cx));
- let edits = Patch::new(
- [text::Edit {
- old: WrapRow(0)..old_max_row,
- new: WrapRow(0)..snapshot.max_point().row(),
- }]
- .into_iter()
- .collect(),
- );
+ let edits = Patch::new(vec![text::Edit {
+ old: WrapRow(0)..self.block_map.wrap_snapshot.borrow().max_point().row() + WrapRow(1),
+ new: WrapRow(0)..snapshot.max_point().row() + WrapRow(1),
+ }]);
+ self.block_map.deferred_edits.set(edits);
- let reader = self.block_map.read(
- snapshot.clone(),
- edits.clone(),
- Some(CompanionView::new(
- self.entity_id,
- &companion_wrap_snapshot,
- &companion_wrap_edits,
- companion.read(cx),
- )),
- );
+ let all_blocks: Vec<_> = self.block_map.blocks_raw().map(Clone::clone).collect();
companion_display_map.update(cx, |companion_display_map, cx| {
for my_buffer in self.folded_buffers() {
@@ -563,7 +555,7 @@ impl DisplayMap {
.folded_buffers
.insert(*their_buffer);
}
- for block in reader.blocks {
+ for block in all_blocks {
let Some(their_block) = block_map::balancing_block(
&block.properties(),
snapshot.buffer(),
@@ -583,16 +575,21 @@ impl DisplayMap {
.insert(block.id, their_id);
});
}
- companion_display_map.block_map.read(
- companion_wrap_snapshot,
- companion_wrap_edits,
- Some(CompanionView::new(
- companion_display_map.entity_id,
- &snapshot,
- &edits,
- companion.read(cx),
- )),
- );
+ let companion_edits = Patch::new(vec![text::Edit {
+ old: WrapRow(0)
+ ..companion_display_map
+ .block_map
+ .wrap_snapshot
+ .borrow()
+ .max_point()
+ .row()
+ + WrapRow(1),
+ new: WrapRow(0)..companion_wrap_snapshot.max_point().row() + WrapRow(1),
+ }]);
+ companion_display_map
+ .block_map
+ .deferred_edits
+ .set(companion_edits);
companion_display_map.companion = Some((this, companion.clone()));
});
@@ -16,7 +16,7 @@ use multi_buffer::{
};
use parking_lot::Mutex;
use std::{
- cell::RefCell,
+ cell::{Cell, RefCell},
cmp::{self, Ordering},
fmt::Debug,
ops::{Deref, DerefMut, Not, Range, RangeBounds, RangeInclusive},
@@ -45,6 +45,7 @@ pub struct BlockMap {
excerpt_header_height: u32,
pub(super) folded_buffers: HashSet<BufferId>,
buffers_with_disabled_headers: HashSet<BufferId>,
+ pub(super) deferred_edits: Cell<Patch<WrapRow>>,
}
pub struct BlockMapReader<'a> {
@@ -620,6 +621,7 @@ impl BlockMap {
wrap_snapshot: RefCell::new(wrap_snapshot.clone()),
buffer_header_height,
excerpt_header_height,
+ deferred_edits: Cell::default(),
};
map.sync(
&wrap_snapshot,
@@ -747,6 +749,11 @@ impl BlockMap {
.retain(|id, _| !ids_to_remove.contains(id));
}
+ // Warning: doesn't sync the block map, use advisedly
+ pub(crate) fn blocks_raw(&self) -> impl Iterator<Item = &Arc<CustomBlock>> {
+ self.custom_blocks.iter()
+ }
+
#[ztracing::instrument(skip_all, fields(edits = ?edits))]
fn sync(
&self,
@@ -756,6 +763,8 @@ impl BlockMap {
) {
let buffer = wrap_snapshot.buffer_snapshot();
+ edits = self.deferred_edits.take().compose(edits);
+
// Handle changing the last excerpt if it is empty.
if buffer.trailing_excerpt_update_count()
!= self
@@ -20682,11 +20682,7 @@ impl Editor {
fn toggle_single_diff_hunk(&mut self, range: Range<Anchor>, cx: &mut Context<Self>) {
self.buffer.update(cx, |buffer, cx| {
- let snapshot = buffer.snapshot(cx);
- let excerpt_id = range.end.excerpt_id;
- let point_range = range.to_point(&snapshot);
- let expand = !buffer.single_hunk_is_expanded(range, cx);
- buffer.expand_or_collapse_diff_hunks_inner([(point_range, excerpt_id)], expand, cx);
+ buffer.toggle_single_diff_hunk(range, cx);
})
}
@@ -2682,7 +2682,25 @@ impl MultiBuffer {
pub fn set_show_deleted_hunks(&mut self, show: bool, cx: &mut Context<Self>) {
self.snapshot.get_mut().show_deleted_hunks = show;
- self.expand_or_collapse_diff_hunks(vec![Anchor::min()..Anchor::max()], true, cx);
+
+ self.sync_mut(cx);
+
+ let old_len = self.snapshot.borrow().len();
+
+ let ranges = std::iter::once((Point::zero()..Point::MAX, ExcerptId::max()));
+ let _ = self.expand_or_collapse_diff_hunks_inner(ranges, true, cx);
+
+ let new_len = self.snapshot.borrow().len();
+
+ self.subscriptions.publish(vec![Edit {
+ old: MultiBufferOffset(0)..old_len,
+ new: MultiBufferOffset(0)..new_len,
+ }]);
+
+ cx.emit(Event::DiffHunksToggled);
+ cx.emit(Event::Edited {
+ edited_buffer: None,
+ });
}
pub fn set_use_extended_diff_range(&mut self, use_extended: bool, _cx: &mut Context<Self>) {
@@ -2740,9 +2758,9 @@ impl MultiBuffer {
ranges: impl IntoIterator<Item = (Range<Point>, ExcerptId)>,
expand: bool,
cx: &mut Context<Self>,
- ) {
+ ) -> Vec<Edit<MultiBufferOffset>> {
if self.snapshot.borrow().all_diff_hunks_expanded && !expand {
- return;
+ return Vec::new();
}
self.sync_mut(cx);
let mut snapshot = self.snapshot.get_mut();
@@ -2768,18 +2786,11 @@ impl MultiBuffer {
}
}
- let edits = Self::sync_diff_transforms(
+ Self::sync_diff_transforms(
&mut snapshot,
excerpt_edits,
DiffChangeKind::ExpandOrCollapseHunks { expand },
- );
- if !edits.is_empty() {
- self.subscriptions.publish(edits);
- }
- cx.emit(Event::DiffHunksToggled);
- cx.emit(Event::Edited {
- edited_buffer: None,
- });
+ )
}
pub fn expand_or_collapse_diff_hunks(
@@ -2798,7 +2809,14 @@ impl MultiBuffer {
};
(range.start..peek_end, end_excerpt_id)
});
- self.expand_or_collapse_diff_hunks_inner(ranges, expand, cx);
+ let edits = self.expand_or_collapse_diff_hunks_inner(ranges, expand, cx);
+ if !edits.is_empty() {
+ self.subscriptions.publish(edits);
+ }
+ cx.emit(Event::DiffHunksToggled);
+ cx.emit(Event::Edited {
+ edited_buffer: None,
+ });
}
pub fn resize_excerpt(
@@ -3601,6 +3619,22 @@ impl MultiBuffer {
);
did_extend
}
+
+ pub fn toggle_single_diff_hunk(&mut self, range: Range<Anchor>, cx: &mut Context<Self>) {
+ let snapshot = self.snapshot(cx);
+ let excerpt_id = range.end.excerpt_id;
+ let point_range = range.to_point(&snapshot);
+ let expand = !self.single_hunk_is_expanded(range, cx);
+ let edits =
+ self.expand_or_collapse_diff_hunks_inner([(point_range, excerpt_id)], expand, cx);
+ if !edits.is_empty() {
+ self.subscriptions.publish(edits);
+ }
+ cx.emit(Event::DiffHunksToggled);
+ cx.emit(Event::Edited {
+ edited_buffer: None,
+ });
+ }
}
fn build_excerpt_ranges(