Calculate an old_lines range in Edits iterator

This commit is contained in:
Antonio Scandurra 2021-07-15 10:11:24 +02:00
parent c2e7460fcd
commit be954872d0
3 changed files with 96 additions and 81 deletions

View file

@ -372,28 +372,39 @@ impl UndoMap {
}
struct Edits<'a, F: Fn(&FragmentSummary) -> bool> {
visible_text: &'a Rope,
deleted_text: &'a Rope,
cursor: FilterCursor<'a, F, Fragment, FragmentTextSummary>,
undos: &'a UndoMap,
since: time::Global,
delta: isize,
old_offset: usize,
new_offset: usize,
old_point: Point,
new_point: Point,
}
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct Edit {
pub old_range: Range<usize>,
pub new_range: Range<usize>,
pub old_lines: Point,
pub old_bytes: Range<usize>,
pub new_bytes: Range<usize>,
pub old_lines: Range<Point>,
}
impl Edit {
pub fn delta(&self) -> isize {
(self.new_range.end - self.new_range.start) as isize
- (self.old_range.end - self.old_range.start) as isize
self.inserted_bytes() as isize - self.deleted_bytes() as isize
}
pub fn old_extent(&self) -> usize {
self.old_range.end - self.old_range.start
pub fn deleted_bytes(&self) -> usize {
self.old_bytes.end - self.old_bytes.start
}
pub fn inserted_bytes(&self) -> usize {
self.new_bytes.end - self.new_bytes.start
}
pub fn deleted_lines(&self) -> Point {
self.old_lines.end - self.old_lines.start
}
}
@ -776,25 +787,21 @@ impl Buffer {
if let Some(syntax_tree) = self.syntax_tree.lock().as_mut() {
let mut edited = false;
let mut delta = 0_isize;
for Edit {
old_range,
new_range,
old_lines,
} in self.edits_since(syntax_tree.version.clone())
{
let start_offset = (old_range.start as isize + delta) as usize;
for edit in self.edits_since(syntax_tree.version.clone()) {
let start_offset = (edit.old_bytes.start as isize + delta) as usize;
let start_point = self.visible_text.to_point(start_offset);
let old_bytes = old_range.end - old_range.start;
let new_bytes = new_range.end - new_range.start;
syntax_tree.tree.edit(&InputEdit {
start_byte: start_offset,
old_end_byte: start_offset + old_bytes,
new_end_byte: start_offset + new_bytes,
old_end_byte: start_offset + edit.deleted_bytes(),
new_end_byte: start_offset + edit.inserted_bytes(),
start_position: start_point.into(),
old_end_position: (start_point + old_lines).into(),
new_end_position: self.visible_text.to_point(start_offset + new_bytes).into(),
old_end_position: (start_point + edit.deleted_lines()).into(),
new_end_position: self
.visible_text
.to_point(start_offset + edit.inserted_bytes())
.into(),
});
delta += new_bytes as isize - old_bytes as isize;
delta += edit.inserted_bytes() as isize - edit.deleted_bytes() as isize;
edited = true;
}
syntax_tree.parsed &= !edited;
@ -1051,11 +1058,15 @@ impl Buffer {
);
Edits {
visible_text: &self.visible_text,
deleted_text: &self.deleted_text,
cursor,
undos: &self.undo_map,
since,
delta: 0,
old_offset: 0,
new_offset: 0,
old_point: Point::zero(),
new_point: Point::zero(),
}
}
@ -2089,45 +2100,53 @@ impl<'a, F: Fn(&FragmentSummary) -> bool> Iterator for Edits<'a, F> {
let mut change: Option<Edit> = None;
while let Some(fragment) = self.cursor.item() {
let new_offset = self.cursor.start().visible;
let old_offset = (new_offset as isize - self.delta) as usize;
let bytes = self.cursor.start().visible - self.new_offset;
let lines = self.visible_text.to_point(self.cursor.start().visible) - self.new_point;
self.old_offset += bytes;
self.old_point += &lines;
self.new_offset += bytes;
self.new_point += &lines;
if !fragment.was_visible(&self.since, &self.undos) && fragment.visible {
let fragment_lines =
self.visible_text.to_point(self.new_offset + fragment.len) - self.new_point;
if let Some(ref mut change) = change {
if change.new_range.end == new_offset {
change.new_range.end += fragment.len;
self.delta += fragment.len as isize;
if change.new_bytes.end == self.new_offset {
change.new_bytes.end += fragment.len;
} else {
break;
}
} else {
change = Some(Edit {
old_range: old_offset..old_offset,
new_range: new_offset..new_offset + fragment.len,
old_lines: Point::zero(),
old_bytes: self.old_offset..self.old_offset,
new_bytes: self.new_offset..self.new_offset + fragment.len,
old_lines: self.old_point..self.old_point,
});
self.delta += fragment.len as isize;
}
self.new_offset += fragment.len;
self.new_point += &fragment_lines;
} else if fragment.was_visible(&self.since, &self.undos) && !fragment.visible {
let deleted_start = self.cursor.start().deleted;
let old_lines = self.deleted_text.to_point(deleted_start + fragment.len)
let fragment_lines = self.deleted_text.to_point(deleted_start + fragment.len)
- self.deleted_text.to_point(deleted_start);
if let Some(ref mut change) = change {
if change.new_range.end == new_offset {
change.old_range.end += fragment.len;
change.old_lines += &old_lines;
self.delta -= fragment.len as isize;
if change.new_bytes.end == self.new_offset {
change.old_bytes.end += fragment.len;
change.old_lines.end += &fragment_lines;
} else {
break;
}
} else {
change = Some(Edit {
old_range: old_offset..old_offset + fragment.len,
new_range: new_offset..new_offset,
old_lines,
old_bytes: self.old_offset..self.old_offset + fragment.len,
new_bytes: self.new_offset..self.new_offset,
old_lines: self.old_point..self.old_point + &fragment_lines,
});
self.delta -= fragment.len as isize;
}
self.old_offset += fragment.len;
self.old_point += &fragment_lines;
}
self.cursor.next(&None);
@ -2898,19 +2917,16 @@ mod tests {
);
let mut delta = 0_isize;
for Edit {
old_range,
new_range,
..
} in edits
{
let old_len = old_range.end - old_range.start;
let new_len = new_range.end - new_range.start;
let old_start = (old_range.start as isize + delta) as usize;
let new_text: String = buffer.text_for_range(new_range).collect();
old_buffer.edit(Some(old_start..old_start + old_len), new_text, cx);
delta += new_len as isize - old_len as isize;
for edit in edits {
let old_start = (edit.old_bytes.start as isize + delta) as usize;
let new_text: String =
buffer.text_for_range(edit.new_bytes.clone()).collect();
old_buffer.edit(
Some(old_start..old_start + edit.deleted_bytes()),
new_text,
cx,
);
delta += edit.delta();
}
assert_eq!(old_buffer.text(), buffer.text());
}

View file

@ -106,8 +106,8 @@ impl FoldMap {
let fold = Fold(buffer.anchor_after(range.start)..buffer.anchor_before(range.end));
folds.push(fold);
edits.push(Edit {
old_range: range.clone(),
new_range: range.clone(),
old_bytes: range.clone(),
new_bytes: range.clone(),
..Default::default()
});
}
@ -115,10 +115,10 @@ impl FoldMap {
folds.sort_unstable_by(|a, b| sum_tree::SeekDimension::cmp(a, b, buffer));
edits.sort_unstable_by(|a, b| {
a.old_range
a.old_bytes
.start
.cmp(&b.old_range.start)
.then_with(|| b.old_range.end.cmp(&a.old_range.end))
.cmp(&b.old_bytes.start)
.then_with(|| b.old_bytes.end.cmp(&a.old_bytes.end))
});
self.folds = {
@ -151,8 +151,8 @@ impl FoldMap {
while let Some(fold) = folds_cursor.item() {
let offset_range = fold.0.start.to_offset(buffer)..fold.0.end.to_offset(buffer);
edits.push(Edit {
old_range: offset_range.clone(),
new_range: offset_range,
old_bytes: offset_range.clone(),
new_bytes: offset_range,
..Default::default()
});
fold_ixs_to_delete.push(*folds_cursor.start());
@ -163,10 +163,10 @@ impl FoldMap {
fold_ixs_to_delete.sort_unstable();
fold_ixs_to_delete.dedup();
edits.sort_unstable_by(|a, b| {
a.old_range
a.old_bytes
.start
.cmp(&b.old_range.start)
.then_with(|| b.old_range.end.cmp(&a.old_range.end))
.cmp(&b.old_bytes.start)
.then_with(|| b.old_bytes.end.cmp(&a.old_bytes.end))
});
self.folds = {
@ -278,28 +278,28 @@ impl FoldMap {
cursor.seek(&0, Bias::Right, &());
while let Some(mut edit) = edits.next() {
new_transforms.push_tree(cursor.slice(&edit.old_range.start, Bias::Left, &()), &());
edit.new_range.start -= edit.old_range.start - cursor.seek_start();
edit.old_range.start = *cursor.seek_start();
new_transforms.push_tree(cursor.slice(&edit.old_bytes.start, Bias::Left, &()), &());
edit.new_bytes.start -= edit.old_bytes.start - cursor.seek_start();
edit.old_bytes.start = *cursor.seek_start();
cursor.seek(&edit.old_range.end, Bias::Right, &());
cursor.seek(&edit.old_bytes.end, Bias::Right, &());
cursor.next(&());
let mut delta = edit.delta();
loop {
edit.old_range.end = *cursor.seek_start();
edit.old_bytes.end = *cursor.seek_start();
if let Some(next_edit) = edits.peek() {
if next_edit.old_range.start > edit.old_range.end {
if next_edit.old_bytes.start > edit.old_bytes.end {
break;
}
let next_edit = edits.next().unwrap();
delta += next_edit.delta();
if next_edit.old_range.end >= edit.old_range.end {
edit.old_range.end = next_edit.old_range.end;
cursor.seek(&edit.old_range.end, Bias::Right, &());
if next_edit.old_bytes.end >= edit.old_bytes.end {
edit.old_bytes.end = next_edit.old_bytes.end;
cursor.seek(&edit.old_bytes.end, Bias::Right, &());
cursor.next(&());
}
} else {
@ -307,10 +307,10 @@ impl FoldMap {
}
}
edit.new_range.end =
((edit.new_range.start + edit.old_extent()) as isize + delta) as usize;
edit.new_bytes.end =
((edit.new_bytes.start + edit.deleted_bytes()) as isize + delta) as usize;
let anchor = buffer.anchor_before(edit.new_range.start);
let anchor = buffer.anchor_before(edit.new_bytes.start);
let mut folds_cursor = self.folds.cursor::<_, ()>();
folds_cursor.seek(&Fold(anchor..Anchor::max()), Bias::Left, buffer);
let mut folds = iter::from_fn(move || {
@ -324,7 +324,7 @@ impl FoldMap {
while folds
.peek()
.map_or(false, |fold| fold.start < edit.new_range.end)
.map_or(false, |fold| fold.start < edit.new_bytes.end)
{
let mut fold = folds.next().unwrap();
let sum = new_transforms.summary();
@ -380,9 +380,9 @@ impl FoldMap {
}
let sum = new_transforms.summary();
if sum.buffer.bytes < edit.new_range.end {
if sum.buffer.bytes < edit.new_bytes.end {
let text_summary =
buffer.text_summary_for_range(sum.buffer.bytes..edit.new_range.end);
buffer.text_summary_for_range(sum.buffer.bytes..edit.new_bytes.end);
new_transforms.push(
Transform {
summary: TransformSummary {

View file

@ -117,9 +117,8 @@ impl BackgroundWrapper {
{
let mut old_cursor = self.snapshot.transforms.cursor::<Point, ()>();
for edit in buffer.edits_since(self.snapshot.version.clone()) {
// TODO: old lines gives us an extent but we really want to park ourselves at the start of the line.
new_transforms.push_tree(
old_cursor.slice(&Point::new(edit.old_lines.row, 0), Bias::Left, &()),
old_cursor.slice(&Point::new(edit.old_lines.start.row, 0), Bias::Left, &()),
&(),
);
}