Add Buffer::anchored_edits_since method

This method returns the anchor range associated with each edit. The
anchor ranges allow you to determine how each edit interacts with
an existing anchor range that the edit has touched.
This commit is contained in:
Max Brunsfeld 2022-08-29 16:51:31 -07:00
parent 1746ec573a
commit 74fd348d22

View file

@ -382,6 +382,7 @@ struct Edits<'a, D: TextDimension, F: FnMut(&FragmentSummary) -> bool> {
old_end: D, old_end: D,
new_end: D, new_end: D,
range: Range<(&'a Locator, usize)>, range: Range<(&'a Locator, usize)>,
buffer_id: u64,
} }
#[derive(Clone, Debug, Default, Eq, PartialEq)] #[derive(Clone, Debug, Default, Eq, PartialEq)]
@ -1917,11 +1918,33 @@ impl BufferSnapshot {
self.edits_since_in_range(since, Anchor::MIN..Anchor::MAX) self.edits_since_in_range(since, Anchor::MIN..Anchor::MAX)
} }
pub fn anchored_edits_since<'a, D>(
&'a self,
since: &'a clock::Global,
) -> impl 'a + Iterator<Item = (Edit<D>, Range<Anchor>)>
where
D: TextDimension + Ord,
{
self.anchored_edits_since_in_range(since, Anchor::MIN..Anchor::MAX)
}
pub fn edits_since_in_range<'a, D>( pub fn edits_since_in_range<'a, D>(
&'a self, &'a self,
since: &'a clock::Global, since: &'a clock::Global,
range: Range<Anchor>, range: Range<Anchor>,
) -> impl 'a + Iterator<Item = Edit<D>> ) -> impl 'a + Iterator<Item = Edit<D>>
where
D: TextDimension + Ord,
{
self.anchored_edits_since_in_range(since, range)
.map(|item| item.0)
}
pub fn anchored_edits_since_in_range<'a, D>(
&'a self,
since: &'a clock::Global,
range: Range<Anchor>,
) -> impl 'a + Iterator<Item = (Edit<D>, Range<Anchor>)>
where where
D: TextDimension + Ord, D: TextDimension + Ord,
{ {
@ -1961,6 +1984,7 @@ impl BufferSnapshot {
old_end: Default::default(), old_end: Default::default(),
new_end: Default::default(), new_end: Default::default(),
range: (start_fragment_id, range.start.offset)..(end_fragment_id, range.end.offset), range: (start_fragment_id, range.start.offset)..(end_fragment_id, range.end.offset),
buffer_id: self.remote_id,
} }
} }
} }
@ -2019,10 +2043,10 @@ impl<'a> RopeBuilder<'a> {
} }
impl<'a, D: TextDimension + Ord, F: FnMut(&FragmentSummary) -> bool> Iterator for Edits<'a, D, F> { impl<'a, D: TextDimension + Ord, F: FnMut(&FragmentSummary) -> bool> Iterator for Edits<'a, D, F> {
type Item = Edit<D>; type Item = (Edit<D>, Range<Anchor>);
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
let mut pending_edit: Option<Edit<D>> = None; let mut pending_edit: Option<Self::Item> = None;
let cursor = self.fragments_cursor.as_mut()?; let cursor = self.fragments_cursor.as_mut()?;
while let Some(fragment) = cursor.item() { while let Some(fragment) = cursor.item() {
@ -2041,11 +2065,25 @@ impl<'a, D: TextDimension + Ord, F: FnMut(&FragmentSummary) -> bool> Iterator fo
if pending_edit if pending_edit
.as_ref() .as_ref()
.map_or(false, |change| change.new.end < self.new_end) .map_or(false, |(change, _)| change.new.end < self.new_end)
{ {
break; break;
} }
let timestamp = fragment.insertion_timestamp.local();
let start_anchor = Anchor {
timestamp,
offset: fragment.insertion_offset,
bias: Bias::Right,
buffer_id: Some(self.buffer_id),
};
let end_anchor = Anchor {
timestamp,
offset: fragment.insertion_offset + fragment.len,
bias: Bias::Left,
buffer_id: Some(self.buffer_id),
};
if !fragment.was_visible(self.since, self.undos) && fragment.visible { if !fragment.was_visible(self.since, self.undos) && fragment.visible {
let mut visible_end = cursor.end(&None).visible; let mut visible_end = cursor.end(&None).visible;
if fragment.id == *self.range.end.0 { if fragment.id == *self.range.end.0 {
@ -2058,13 +2096,17 @@ impl<'a, D: TextDimension + Ord, F: FnMut(&FragmentSummary) -> bool> Iterator fo
let fragment_summary = self.visible_cursor.summary(visible_end); let fragment_summary = self.visible_cursor.summary(visible_end);
let mut new_end = self.new_end.clone(); let mut new_end = self.new_end.clone();
new_end.add_assign(&fragment_summary); new_end.add_assign(&fragment_summary);
if let Some(pending_edit) = pending_edit.as_mut() { if let Some((edit, range)) = pending_edit.as_mut() {
pending_edit.new.end = new_end.clone(); edit.new.end = new_end.clone();
range.end = end_anchor;
} else { } else {
pending_edit = Some(Edit { pending_edit = Some((
old: self.old_end.clone()..self.old_end.clone(), Edit {
new: self.new_end.clone()..new_end.clone(), old: self.old_end.clone()..self.old_end.clone(),
}); new: self.new_end.clone()..new_end.clone(),
},
start_anchor..end_anchor,
));
} }
self.new_end = new_end; self.new_end = new_end;
@ -2083,13 +2125,17 @@ impl<'a, D: TextDimension + Ord, F: FnMut(&FragmentSummary) -> bool> Iterator fo
let fragment_summary = self.deleted_cursor.summary(deleted_end); let fragment_summary = self.deleted_cursor.summary(deleted_end);
let mut old_end = self.old_end.clone(); let mut old_end = self.old_end.clone();
old_end.add_assign(&fragment_summary); old_end.add_assign(&fragment_summary);
if let Some(pending_edit) = pending_edit.as_mut() { if let Some((edit, range)) = pending_edit.as_mut() {
pending_edit.old.end = old_end.clone(); edit.old.end = old_end.clone();
range.end = end_anchor;
} else { } else {
pending_edit = Some(Edit { pending_edit = Some((
old: self.old_end.clone()..old_end.clone(), Edit {
new: self.new_end.clone()..self.new_end.clone(), old: self.old_end.clone()..old_end.clone(),
}); new: self.new_end.clone()..self.new_end.clone(),
},
start_anchor..end_anchor,
));
} }
self.old_end = old_end; self.old_end = old_end;