Detailed changes
@@ -14,7 +14,7 @@ use text::BufferId;
/// A multibuffer anchor derived from an anchor into a specific excerpted buffer.
#[derive(Clone, Copy, Eq, PartialEq, Hash)]
-pub(crate) struct ExcerptAnchor {
+pub struct ExcerptAnchor {
/// The position within the excerpt's underlying buffer. This is a stable
/// reference that remains valid as the buffer text is edited.
pub(crate) timestamp: clock::Lamport,
@@ -190,6 +190,7 @@ impl ExcerptAnchor {
}
}
+ #[track_caller]
pub(crate) fn in_buffer(path: PathKeyIndex, text_anchor: text::Anchor) -> Self {
let Some(buffer_id) = text_anchor.buffer_id else {
panic!("text_anchor must have a buffer_id");
@@ -101,6 +101,12 @@ pub struct ExcerptInfo {
range: ExcerptRange<text::Anchor>,
}
+impl ExcerptInfo {
+ pub fn end_anchor(&self) -> Anchor {
+ Anchor::in_buffer(self.path_key_index, self.range.context.end)
+ }
+}
+
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Event {
BufferUpdated {
@@ -624,7 +630,6 @@ struct BufferStateSnapshot {
pub struct MultiBufferSnapshot {
excerpts: SumTree<Excerpt>,
buffers: TreeMap<BufferId, BufferStateSnapshot>,
- path_keys_by_buffer: TreeMap<BufferId, PathKey>,
path_keys_by_index: TreeMap<PathKeyIndex, PathKey>,
diffs: TreeMap<BufferId, DiffStateSnapshot>,
diff_transforms: SumTree<DiffTransform>,
@@ -1749,7 +1754,6 @@ impl MultiBuffer {
show_deleted_hunks: _,
use_extended_diff_range: _,
show_headers: _,
- path_keys_by_buffer: _,
path_keys_by_index: _,
buffers,
} = self.snapshot.get_mut();
@@ -1800,12 +1804,13 @@ impl MultiBuffer {
.cursor::<Dimensions<ExcerptPoint, OutputDimension<Point>>>(());
diff_transforms.next();
let mut result = Vec::new();
- let Some(path_key) = snapshot.path_keys_by_buffer.get(&buffer_id) else {
+ let Some(buffer_state) = snapshot.buffers.get(&buffer_id) else {
return result;
};
+ let path_key = buffer_state.path_key.clone();
while let Some(excerpt) = excerpts.item()
- && &excerpt.path_key == path_key
+ && excerpt.path_key == path_key
{
let excerpt_start = excerpts.start().1;
let excerpt_end = excerpt_start + excerpt.text_summary.lines;
@@ -2456,7 +2461,7 @@ impl MultiBuffer {
let snapshot = self.snapshot.borrow().clone();
let ranges = ranges.iter().map(move |range| {
let excerpt_end = snapshot
- .excerpt_at(range.end)
+ .excerpt_containing(range.end..range.end)
.map(|excerpt| excerpt.end_anchor().into())
.unwrap_or(Anchor::Max);
let range = range.to_point(&snapshot);
@@ -2500,6 +2505,7 @@ impl MultiBuffer {
return snapshot;
}
let edits = Self::sync_from_buffer_changes(snapshot, &self.buffers, &self.diffs, cx);
+ dbg!(&edits);
if !edits.is_empty() {
self.subscriptions.publish(edits);
@@ -2518,7 +2524,6 @@ impl MultiBuffer {
excerpts,
diffs: buffer_diff,
buffers: buffer_snapshots,
- path_keys_by_buffer,
path_keys_by_index: _,
diff_transforms: _,
non_text_state_update_count,
@@ -2579,13 +2584,15 @@ impl MultiBuffer {
let buffer_edited =
current_version.changed_since(last_snapshot.buffer_snapshot.version());
+ dbg!(
+ ¤t_version,
+ last_snapshot.buffer_snapshot.version().clone()
+ );
let buffer_non_text_state_updated = non_text_state_update_count
> last_snapshot.buffer_snapshot.non_text_state_update_count();
- if (buffer_edited || buffer_non_text_state_updated)
- && let Some(path_key) = path_keys_by_buffer.get(&buffer.remote_id())
- {
+ if buffer_edited || buffer_non_text_state_updated {
paths_to_edit.push((
- path_key.clone(),
+ last_snapshot.path_key.clone(),
buffer_state.buffer.clone(),
if buffer_edited {
Some(last_snapshot.buffer_snapshot.version().clone())
@@ -2617,6 +2624,7 @@ impl MultiBuffer {
let mut cursor = excerpts.cursor::<ExcerptSummary>(());
for (path, buffer, prev_version) in paths_to_edit {
+ dbg!(&prev_version, buffer.read(cx).version());
new_excerpts.append(cursor.slice(&path, Bias::Left), ());
let old_excerpt = cursor.item().unwrap();
let buffer = buffer.read(cx);
@@ -2635,9 +2643,10 @@ impl MultiBuffer {
buffer
.edits_since_in_range::<usize>(
&prev_version,
- old_excerpt.range.context.clone(),
+ dbg!(old_excerpt.range.context.clone()),
)
.map(|edit| {
+ dbg!(&edit);
let excerpt_old_start = cursor.start().len();
let excerpt_new_start =
ExcerptDimension(new_excerpts.summary().text.len);
@@ -2679,6 +2688,7 @@ impl MultiBuffer {
excerpt_edits: Vec<text::Edit<ExcerptOffset>>,
change_kind: DiffChangeKind,
) -> Vec<Edit<MultiBufferOffset>> {
+ dbg!(&excerpt_edits);
if excerpt_edits.is_empty() {
return vec![];
}
@@ -3121,7 +3131,7 @@ impl MultiBuffer {
pub fn toggle_single_diff_hunk(&mut self, range: Range<Anchor>, cx: &mut Context<Self>) {
let snapshot = self.snapshot(cx);
let excerpt_end = snapshot
- .excerpt_at(range.end)
+ .excerpt_containing(range.end..range.end)
.map(|excerpt| excerpt.end_anchor().into())
.unwrap_or(Anchor::Max);
let point_range = range.to_point(&snapshot);
@@ -3316,10 +3326,11 @@ impl MultiBuffer {
let path_key = self
.snapshot
.borrow()
- .path_keys_by_buffer
+ .buffers
.get(&buffer_ids.choose(rng).unwrap())
- .cloned()
- .unwrap();
+ .unwrap()
+ .path_key
+ .clone();
log::info!("Removing excerpts {:?}", path_key);
self.remove_excerpts_for_path(path_key, cx);
}
@@ -3588,7 +3599,8 @@ impl MultiBufferSnapshot {
let mut same_buffer_anchors =
anchors.peeking_take_while(|a| a.buffer_id.is_some_and(|b| buffer_id == b));
- if let Some(path) = self.path_keys_by_buffer.get(&buffer_id) {
+ if let Some(buffer) = self.buffers.get(&buffer_id) {
+ let path = &buffer.path_key;
let Some(mut next) = same_buffer_anchors.next() else {
continue 'anchors;
};
@@ -3664,6 +3676,7 @@ impl MultiBufferSnapshot {
})
}
+ // todo!() can we make this not RangeBounds
pub fn range_to_buffer_ranges<R, T>(
&self,
range: R,
@@ -4219,6 +4232,7 @@ impl MultiBufferSnapshot {
}
pub fn row_infos(&self, start_row: MultiBufferRow) -> MultiBufferRows<'_> {
+ dbg!(self.diff_transforms.is_empty());
let mut cursor = self.cursor::<Point, Point>();
cursor.seek(&Point::new(start_row.0, 0));
let mut result = MultiBufferRows {
@@ -5184,12 +5198,13 @@ impl MultiBufferSnapshot {
}
fn excerpts_for_buffer(&self, buffer_id: BufferId) -> impl Iterator<Item = &Excerpt> {
- if let Some(path_key) = self.path_keys_by_buffer.get(&buffer_id) {
+ if let Some(buffer_state) = self.buffers.get(&buffer_id) {
+ let path_key = buffer_state.path_key.clone();
let mut cursor = self.excerpts.cursor::<PathKey>(());
- cursor.seek_forward(path_key, Bias::Left);
+ cursor.seek_forward(&path_key, Bias::Left);
Some(iter::from_fn(move || {
let excerpt = cursor.item()?;
- if &excerpt.path_key != path_key {
+ if excerpt.path_key != path_key {
return None;
}
cursor.next();
@@ -6262,7 +6277,7 @@ impl MultiBufferSnapshot {
}
pub fn path_for_buffer(&self, buffer_id: BufferId) -> Option<&PathKey> {
- self.path_keys_by_buffer.get(&buffer_id)
+ Some(&self.buffers.get(&buffer_id)?.path_key)
}
pub fn path_key_index_for_buffer(&self, buffer_id: BufferId) -> Option<PathKeyIndex> {
@@ -6271,8 +6286,8 @@ impl MultiBufferSnapshot {
}
pub fn first_excerpt_for_buffer(&self, buffer_id: BufferId) -> Option<&Excerpt> {
- let path_key = self.path_keys_by_buffer.get(&buffer_id)?;
- self.first_excerpt_for_path(&path_key)
+ let path_key = &self.buffers.get(&buffer_id)?.path_key;
+ self.first_excerpt_for_path(path_key)
}
pub fn first_excerpt_for_path(&self, path_key: &PathKey) -> Option<&Excerpt> {
@@ -6283,7 +6298,7 @@ impl MultiBufferSnapshot {
}
pub fn buffer_for_id(&self, id: BufferId) -> Option<&BufferSnapshot> {
- self.buffer_for_path(self.path_keys_by_buffer.get(&id)?)
+ self.buffer_for_path(self.path_for_buffer(id)?)
}
fn try_path_for_anchor(&self, anchor: ExcerptAnchor) -> Option<PathKey> {
@@ -6327,11 +6342,6 @@ impl MultiBufferSnapshot {
// }
}
- // todo!() sort out excerpt_containing etc.
- fn excerpt_at(&self, _position: impl ToOffset) -> Option<&Excerpt> {
- todo!()
- }
-
/// Returns the excerpt containing range and its offset start within the multibuffer or none if `range` spans multiple excerpts
pub fn excerpt_containing<T: ToOffset>(
&self,
@@ -6545,7 +6555,8 @@ impl MultiBufferSnapshot {
fn check_invariants(&self) {
let excerpts = self.excerpts.items(());
- let all_buffer_path_keys = HashSet::from_iter(self.path_keys_by_buffer.values().cloned());
+ let all_buffer_path_keys =
+ HashSet::from_iter(self.buffers.values().map(|b| b.path_key.clone()));
let all_excerpt_path_keys = HashSet::from_iter(excerpts.iter().map(|e| e.path_key.clone()));
for (ix, excerpt) in excerpts.iter().enumerate() {
@@ -6644,7 +6655,8 @@ where
}
self.excerpts.seek(&excerpt_position, Bias::Right);
- if self.excerpts.item().is_none() && excerpt_position == *self.excerpts.start() {
+ if self.excerpts.item().is_none() && dbg!(excerpt_position) == *self.excerpts.start() {
+ dbg!("NONE");
self.excerpts.prev();
}
}
@@ -6813,6 +6825,7 @@ where
fn build_region(&self) -> Option<MultiBufferRegion<'a, MBD, BD>> {
let excerpt = self.excerpts.item()?;
+ dbg!("GOT EXCERPT");
match self.diff_transforms.item()? {
DiffTransform::DeletedHunk {
buffer_id,
@@ -6945,6 +6958,7 @@ impl Excerpt {
range: ExcerptRange<text::Anchor>,
has_trailing_newline: bool,
) -> Self {
+ dbg!(&path_key, &range, has_trailing_newline);
Excerpt {
path_key,
path_key_index,
@@ -7059,11 +7073,11 @@ impl Excerpt {
}
fn start_anchor(&self) -> ExcerptAnchor {
- todo!()
+ ExcerptAnchor::in_buffer(self.path_key_index, self.range.context.start)
}
fn end_anchor(&self) -> ExcerptAnchor {
- todo!()
+ ExcerptAnchor::in_buffer(self.path_key_index, self.range.context.end)
}
}
@@ -7604,11 +7618,13 @@ impl Iterator for MultiBufferRows<'_> {
}
let mut region = self.cursor.region()?.clone();
+ dbg!("REGION");
while self.point >= region.range.end {
self.cursor.next();
if let Some(next_region) = self.cursor.region() {
region = next_region.clone();
- } else if self.point == self.cursor.diff_transforms.end().output_dimension.0 {
+ } else if dbg!(self.point) == dbg!(self.cursor.diff_transforms.end().output_dimension.0)
+ {
let multibuffer_row = MultiBufferRow(self.point.row);
let last_excerpt = self
.cursor
@@ -1109,6 +1109,7 @@ fn test_singleton_multibuffer_anchors(cx: &mut App) {
buffer.edit([(0..0, "X")], None, cx);
buffer.edit([(5..5, "Y")], None, cx);
});
+ dbg!("-------");
let new_snapshot = multibuffer.read(cx).snapshot(cx);
assert_eq!(old_snapshot.text(), "abcd");
@@ -2279,7 +2280,7 @@ struct ReferenceExcerpt {
range: Range<text::Anchor>,
}
-#[derive(Debug)]
+#[derive(Clone, Debug)]
struct ReferenceRegion {
buffer_id: Option<BufferId>,
range: Range<usize>,
@@ -2293,7 +2294,7 @@ impl ReferenceExcerpt {
ExcerptInfo {
path_key_index: self.path_key_index,
buffer_id: self.buffer.read(cx).remote_id(),
- range: self.range.clone(),
+ range: ExcerptRange::new(self.range.clone()),
}
}
}
@@ -2321,32 +2322,6 @@ impl ReferenceMultibuffer {
}
}
- fn remove_excerpt(&mut self, info: ExcerptInfo, cx: &App) {
- let ix = self
- .excerpts
- .iter()
- .position(|excerpt| excerpt.info(cx) == info)
- .unwrap();
- let excerpt = self.excerpts.remove(ix);
- let buffer = excerpt.buffer.read(cx);
- let buffer_id = buffer.remote_id();
- log::info!(
- "Removing excerpt {}: {:?}",
- ix,
- buffer
- .text_for_range(excerpt.range.to_offset(buffer))
- .collect::<String>(),
- );
- if !self
- .excerpts
- .iter()
- .any(|excerpt| excerpt.buffer.read(cx).remote_id() == buffer_id)
- {
- self.diffs.remove(&buffer_id);
- self.inverted_diffs.remove(&buffer_id);
- }
- }
-
fn set_excerpts(
&mut self,
path_key: PathKey,
@@ -2631,7 +2606,7 @@ impl ReferenceMultibuffer {
.iter()
.position(|region| region.range.contains(&ix))
.map_or(RowInfo::default(), |region_ix| {
- let region = ®ions[region_ix];
+ let region = regions[region_ix].clone();
let buffer_row = region.buffer_range.as_ref().map(|buffer_range| {
buffer_range.start.row
+ text[region.range.start..ix].matches('\n').count() as u32
@@ -2639,7 +2614,7 @@ impl ReferenceMultibuffer {
let main_buffer = self
.excerpts
.iter()
- .find(|e| e.info(cx) == region.excerpt_info.unwrap())
+ .find(|e| e.info(cx) == region.excerpt_info.clone().unwrap())
.map(|e| e.buffer.clone());
let is_excerpt_start = region_ix == 0
|| ®ions[region_ix - 1].excerpt_info != ®ion.excerpt_info
@@ -2811,9 +2786,9 @@ async fn test_random_set_ranges(cx: &mut TestAppContext, mut rng: StdRng) {
let mut last_end = None;
let mut seen_ranges = Vec::default();
- for (_, buf, range) in snapshot.excerpts() {
- let start = range.context.start.to_point(buf);
- let end = range.context.end.to_point(buf);
+ for (buf, info) in snapshot.excerpts() {
+ let start = info.range.context.start.to_point(buf);
+ let end = info.range.context.end.to_point(buf);
seen_ranges.push(start..end);
if let Some(last_end) = last_end.take() {
@@ -3228,23 +3203,30 @@ fn check_multibuffer(
.unwrap()
+ 1
);
- let reference_ranges = reference
- .excerpts
- .iter()
- .map(|excerpt| {
- (
- excerpt.id,
- excerpt.range.to_offset(&excerpt.buffer.read(cx).snapshot()),
- )
- })
- .collect::<HashMap<_, _>>();
+ // let reference_ranges = reference
+ // .excerpts
+ // .iter()
+ // .map(|excerpt| {
+ // (
+ // excerpt.info(cx),
+ // excerpt.range.to_offset(&excerpt.buffer.read(cx).snapshot()),
+ // )
+ // })
+ // .collect::<Vec<_>>();
for i in 0..snapshot.len().0 {
+ // todo!() this seems not useful
let excerpt = snapshot
.excerpt_containing(MultiBufferOffset(i)..MultiBufferOffset(i))
.unwrap();
+ let reference_range = reference
+ .excerpts
+ .iter()
+ .find(|reference_excerpt| reference_excerpt.info(cx) == excerpt.excerpt.info())
+ .map(|excerpt| excerpt.range.to_offset(&excerpt.buffer.read(cx).snapshot()))
+ .expect("corresponding excerpt should exist in reference multibuffer");
assert_eq!(
- excerpt.buffer_range().start.0..excerpt.buffer_range().end.0,
- reference_ranges[&excerpt.id()]
+ excerpt.buffer_range(&snapshot).start.0..excerpt.buffer_range(&snapshot).end.0,
+ reference_range
);
}
@@ -3641,7 +3623,6 @@ async fn test_summaries_for_anchors(cx: &mut TestAppContext) {
});
cx.run_until_parked();
- let mut ids = vec![];
let multibuffer = cx.new(|cx| {
let mut multibuffer = MultiBuffer::new(Capability::ReadWrite);
multibuffer.set_all_diff_hunks_expanded(cx);
@@ -3661,7 +3642,6 @@ async fn test_summaries_for_anchors(cx: &mut TestAppContext) {
);
multibuffer.add_diff(diff_1.clone(), cx);
multibuffer.add_diff(diff_2.clone(), cx);
- ids = multibuffer.excerpt_ids();
multibuffer
});
@@ -3685,11 +3665,27 @@ async fn test_summaries_for_anchors(cx: &mut TestAppContext) {
),
);
- let anchor_1 = Anchor::text(ids[0], text::Anchor::MIN);
+ let anchor_1 = multibuffer.read_with(cx, |multibuffer, cx| {
+ multibuffer
+ .buffer_anchor_to_anchor(
+ &buffer_1,
+ text::Anchor::min_for_buffer(buffer_1.read(cx).remote_id()),
+ cx,
+ )
+ .unwrap()
+ });
let point_1 = snapshot.summaries_for_anchors::<Point, _>([&anchor_1])[0];
assert_eq!(point_1, Point::new(0, 0));
- let anchor_2 = Anchor::text(ids[1], text::Anchor::MIN);
+ let anchor_2 = multibuffer.read_with(cx, |multibuffer, cx| {
+ multibuffer
+ .buffer_anchor_to_anchor(
+ &buffer_2,
+ text::Anchor::min_for_buffer(buffer_2.read(cx).remote_id()),
+ cx,
+ )
+ .unwrap()
+ });
let point_2 = snapshot.summaries_for_anchors::<Point, _>([&anchor_2])[0];
assert_eq!(point_2, Point::new(3, 0));
}
@@ -3748,7 +3744,7 @@ async fn test_trailing_deletion_without_newline(cx: &mut TestAppContext) {
let (_, translated_offset) = snapshot.point_to_buffer_offset(Point::new(2, 0)).unwrap();
assert_eq!(translated_offset.0, "one\n".len());
- let (_, translated_point, _) = snapshot.point_to_buffer_point(Point::new(2, 0)).unwrap();
+ let (_, translated_point) = snapshot.point_to_buffer_point(Point::new(2, 0)).unwrap();
assert_eq!(translated_point, Point::new(1, 0));
// The same, for an excerpt that's not at the end of the multibuffer.
@@ -3791,7 +3787,7 @@ async fn test_trailing_deletion_without_newline(cx: &mut TestAppContext) {
let (buffer, translated_offset) = snapshot.point_to_buffer_offset(Point::new(2, 0)).unwrap();
assert_eq!(buffer.remote_id(), buffer_1_id);
assert_eq!(translated_offset.0, "one\n".len());
- let (buffer, translated_point, _) = snapshot.point_to_buffer_point(Point::new(2, 0)).unwrap();
+ let (buffer, translated_point) = snapshot.point_to_buffer_point(Point::new(2, 0)).unwrap();
assert_eq!(buffer.remote_id(), buffer_1_id);
assert_eq!(translated_point, Point::new(1, 0));
}
@@ -3831,6 +3827,7 @@ fn format_diff(
};
let expand = info
.expand_info
+ .as_ref()
.map(|expand_info| match expand_info.direction {
ExpandExcerptDirection::Up => " [↑]",
ExpandExcerptDirection::Down => " [↓]",
@@ -4174,9 +4171,9 @@ fn assert_excerpts_match(
) {
let mut output = String::new();
multibuffer.read_with(cx, |multibuffer, cx| {
- for (_, buffer, range) in multibuffer.snapshot(cx).excerpts() {
+ for (buffer, info) in multibuffer.snapshot(cx).excerpts() {
output.push_str("-----\n");
- output.extend(buffer.text_for_range(range.context));
+ output.extend(buffer.text_for_range(info.range.context));
if !output.ends_with('\n') {
output.push('\n');
}
@@ -4396,7 +4393,7 @@ fn assert_position_translation(snapshot: &MultiBufferSnapshot) {
fn assert_line_indents(snapshot: &MultiBufferSnapshot) {
let max_row = snapshot.max_point().row;
- let buffer_id = snapshot.excerpts().next().unwrap().1.remote_id();
+ let buffer_id = snapshot.excerpts().next().unwrap().1.buffer_id;
let text = text::Buffer::new(ReplicaId::LOCAL, buffer_id, snapshot.text());
let mut line_indents = text
.line_indents_in_row_range(0..max_row + 1)
@@ -4584,7 +4581,7 @@ fn test_random_chunk_bitmaps_with_diffs(cx: &mut App, mut rng: StdRng) {
let mut diffs = Vec::new();
multibuffer.update(cx, |multibuffer, cx| {
- for buffer_id in multibuffer.excerpt_buffer_ids() {
+ for buffer_id in multibuffer.all_buffer_ids() {
if rng.random_bool(0.7) {
if let Some(buffer_handle) = multibuffer.buffer(buffer_id) {
let buffer_text = buffer_handle.read(cx).text();
@@ -4976,7 +4973,7 @@ fn test_range_to_buffer_ranges_with_range_bounds(cx: &mut App) {
let buffer_2 = cx.new(|cx| Buffer::local("ccc", cx));
let multibuffer = cx.new(|_| MultiBuffer::new(Capability::ReadWrite));
- let (excerpt_1_id, excerpt_2_id) = multibuffer.update(cx, |multibuffer, cx| {
+ multibuffer.update(cx, |multibuffer, cx| {
multibuffer.set_excerpts_for_path(
PathKey::sorted(0),
buffer_1.clone(),
@@ -4992,10 +4989,6 @@ fn test_range_to_buffer_ranges_with_range_bounds(cx: &mut App) {
0,
cx,
);
-
- let excerpt_ids = multibuffer.excerpt_ids();
-
- (excerpt_ids[0], excerpt_ids[1])
});
let snapshot = multibuffer.read(cx).snapshot(cx);
@@ -5009,7 +5002,7 @@ fn test_range_to_buffer_ranges_with_range_bounds(cx: &mut App) {
1,
"Half-open range ending at excerpt start should EXCLUDE that excerpt"
);
- assert_eq!(ranges_half_open[0].2, excerpt_1_id);
+ assert_eq!(ranges_half_open[0].1, BufferOffset(0)..BufferOffset(7));
let ranges_inclusive = snapshot.range_to_buffer_ranges(Point::zero()..=excerpt_2_start);
assert_eq!(
@@ -5017,8 +5010,16 @@ fn test_range_to_buffer_ranges_with_range_bounds(cx: &mut App) {
2,
"Inclusive range ending at excerpt start should INCLUDE that excerpt"
);
- assert_eq!(ranges_inclusive[0].2, excerpt_1_id);
- assert_eq!(ranges_inclusive[1].2, excerpt_2_id);
+ assert_eq!(ranges_half_open[0].1, BufferOffset(0)..BufferOffset(7));
+ assert_eq!(
+ ranges_half_open[0].0.remote_id(),
+ buffer_1.read(cx).remote_id()
+ );
+ assert_eq!(ranges_half_open[1].1, BufferOffset(0)..BufferOffset(0));
+ assert_eq!(
+ ranges_half_open[1].0.remote_id(),
+ buffer_2.read(cx).remote_id()
+ );
let ranges_unbounded =
snapshot.range_to_buffer_ranges((Bound::Included(Point::zero()), Bound::Unbounded));
@@ -5027,8 +5028,16 @@ fn test_range_to_buffer_ranges_with_range_bounds(cx: &mut App) {
2,
"Unbounded end should include all excerpts"
);
- assert_eq!(ranges_unbounded[0].2, excerpt_1_id);
- assert_eq!(ranges_unbounded[1].2, excerpt_2_id);
+ assert_eq!(ranges_half_open[0].1, BufferOffset(0)..BufferOffset(7));
+ assert_eq!(
+ ranges_half_open[0].0.remote_id(),
+ buffer_1.read(cx).remote_id()
+ );
+ assert_eq!(ranges_half_open[1].1, BufferOffset(0)..BufferOffset(3));
+ assert_eq!(
+ ranges_half_open[1].0.remote_id(),
+ buffer_2.read(cx).remote_id()
+ );
let ranges_excluded_end = snapshot.range_to_buffer_ranges((
Bound::Included(Point::zero()),
@@ -5039,7 +5048,11 @@ fn test_range_to_buffer_ranges_with_range_bounds(cx: &mut App) {
1,
"Excluded end bound should exclude excerpt starting at that point"
);
- assert_eq!(ranges_excluded_end[0].2, excerpt_1_id);
+ assert_eq!(ranges_half_open[0].1, BufferOffset(0)..BufferOffset(7));
+ assert_eq!(
+ ranges_half_open[0].0.remote_id(),
+ buffer_1.read(cx).remote_id()
+ );
let buffer_empty = cx.new(|cx| Buffer::local("", cx));
let multibuffer_trailing_empty = cx.new(|_| MultiBuffer::new(Capability::ReadWrite));
@@ -278,8 +278,10 @@ impl MultiBuffer {
let anchor_ranges = new
.into_iter()
.map(|r| ExcerptRange {
- context: buffer_snapshot.anchor_range_around(r.context),
- primary: buffer_snapshot.anchor_range_around(r.primary),
+ context: buffer_snapshot.anchor_before(r.context.start)
+ ..buffer_snapshot.anchor_after(r.context.end),
+ primary: buffer_snapshot.anchor_before(r.primary.start)
+ ..buffer_snapshot.anchor_after(r.primary.end),
})
.collect::<Vec<_>>();
self.update_path_excerpts(path, buffer, buffer_snapshot, &anchor_ranges, cx)
@@ -335,26 +337,13 @@ impl MultiBuffer {
let buffer_id = buffer_snapshot.remote_id();
- self.buffers.entry(buffer_id).or_insert_with(|| {
- self.buffer_changed_since_sync.replace(true);
- buffer.update(cx, |buffer, _| {
- buffer.record_changes(Rc::downgrade(&self.buffer_changed_since_sync));
- });
- BufferState {
- _subscriptions: [
- cx.observe(&buffer, |_, _, cx| cx.notify()),
- cx.subscribe(&buffer, Self::on_buffer_event),
- ],
- buffer: buffer.clone(),
- }
- });
-
let mut snapshot = self.snapshot.get_mut();
let mut cursor = snapshot
.excerpts
.cursor::<Dimensions<PathKey, ExcerptOffset>>(());
let mut new_excerpts = SumTree::new(());
+ let new_ranges = to_insert.clone();
let mut to_insert = to_insert.iter().peekable();
let mut patch = Patch::empty();
let mut added_new_excerpt = false;
@@ -410,18 +399,19 @@ impl MultiBuffer {
let next_excerpt = to_insert.next().unwrap();
added_new_excerpt = true;
let before = new_excerpts.summary().len();
+ new_excerpts.update_last(|excerpt| excerpt.has_trailing_newline = true, ());
new_excerpts.push(
Excerpt::new(
path_key.clone(),
path_key_index,
&buffer_snapshot,
next_excerpt.clone(),
- to_insert.peek().is_some(),
+ to_insert.peek().is_some() || cursor.item().is_some(),
),
(),
);
let after = new_excerpts.summary().len();
- patch.push(Edit {
+ patch.push_maybe_empty(Edit {
old: cursor.position.1..cursor.position.1,
new: before..after,
});
@@ -437,6 +427,27 @@ impl MultiBuffer {
new: new_excerpts.summary().len()..new_excerpts.summary().len(),
});
+ while let Some(next_excerpt) = to_insert.next() {
+ added_new_excerpt = true;
+ let before = new_excerpts.summary().len();
+ new_excerpts.update_last(|excerpt| excerpt.has_trailing_newline = true, ());
+ new_excerpts.push(
+ Excerpt::new(
+ path_key.clone(),
+ path_key_index,
+ &buffer_snapshot,
+ next_excerpt.clone(),
+ to_insert.peek().is_some() || cursor.item().is_some(),
+ ),
+ (),
+ );
+ let after = new_excerpts.summary().len();
+ patch.push_maybe_empty(Edit {
+ old: cursor.position.1..cursor.position.1,
+ new: before..after,
+ });
+ }
+
let suffix = cursor.suffix();
let changed_trailing_excerpt = suffix.is_empty();
new_excerpts.append(suffix, ());
@@ -449,13 +460,28 @@ impl MultiBuffer {
buffer_snapshot: buffer_snapshot.clone(),
},
);
+
+ self.buffers.entry(buffer_id).or_insert_with(|| {
+ self.buffer_changed_since_sync.replace(true);
+ buffer.update(cx, |buffer, _| {
+ buffer.record_changes(Rc::downgrade(&self.buffer_changed_since_sync));
+ });
+ BufferState {
+ _subscriptions: [
+ cx.observe(&buffer, |_, _, cx| cx.notify()),
+ cx.subscribe(&buffer, Self::on_buffer_event),
+ ],
+ buffer: buffer.clone(),
+ }
+ });
+
if changed_trailing_excerpt {
snapshot.trailing_excerpt_update_count += 1;
}
let edits = Self::sync_diff_transforms(
&mut snapshot,
- patch.into_inner(),
+ dbg!(patch.into_inner()),
DiffChangeKind::BufferEdited,
);
if !edits.is_empty() {
@@ -468,7 +494,7 @@ impl MultiBuffer {
cx.emit(Event::BufferUpdated {
buffer,
path_key: path_key.clone(),
- ranges: to_insert,
+ ranges: new_ranges,
});
cx.notify();
@@ -333,6 +333,7 @@ impl MultiBuffer {
let Some(excerpt) = snapshot.first_excerpt_for_buffer(*buffer_id) else {
continue;
};
+ let buffer_snapshot = buffer.read(cx).snapshot();
for range in buffer
.read(cx)
@@ -340,11 +341,11 @@ impl MultiBuffer {
{
buffer_anchors.push(Anchor::in_buffer(
excerpt.path_key_index,
- excerpt.buffer_snapshot.anchor_at(range.start, Bias::Left),
+ buffer_snapshot.anchor_at(range.start, Bias::Left),
));
buffer_anchors.push(Anchor::in_buffer(
excerpt.path_key_index,
- excerpt.buffer_snapshot.anchor_at(range.end, Bias::Right),
+ buffer_snapshot.anchor_at(range.end, Bias::Right),
));
}
}
@@ -56,7 +56,10 @@ where
if edit.is_empty() {
return;
}
+ self.push_maybe_empty(edit);
+ }
+ pub fn push_maybe_empty(&mut self, edit: Edit<T>) {
if let Some(last) = self.0.last_mut() {
if last.old.end >= edit.old.start {
last.old.end = edit.old.end;
@@ -2509,11 +2509,13 @@ impl BufferSnapshot {
}
/// Returns an anchor range for the given input position range that is anchored to the text in the range.
+ /// todo!() this name seems misleading
pub fn anchor_range_around<T: ToOffset>(&self, position: Range<T>) -> Range<Anchor> {
self.anchor_after(position.start)..self.anchor_before(position.end)
}
/// Returns an anchor range for the given input position range that is anchored to the text before and after.
+ /// todo!() this name seems misleading
pub fn anchor_range_between<T: ToOffset>(&self, position: Range<T>) -> Range<Anchor> {
self.anchor_before(position.start)..self.anchor_after(position.end)
}