Change fold_map::Edit to return DisplayOffsets

This is needed so that we can translate display offsets into display
points in the `WrapMap`.
This commit is contained in:
Antonio Scandurra 2021-07-19 11:34:47 +02:00
parent 38dffc310f
commit 7a86a2c831
2 changed files with 95 additions and 52 deletions

View file

@ -34,9 +34,10 @@ impl<'a> FoldMapWriter<'a> {
if range.start != range.end {
let fold = Fold(buffer.anchor_after(range.start)..buffer.anchor_before(range.end));
folds.push(fold);
edits.push(Edit {
edits.push(buffer::Edit {
old_bytes: range.clone(),
new_bytes: range.clone(),
..Default::default()
});
}
}
@ -54,7 +55,7 @@ impl<'a> FoldMapWriter<'a> {
new_tree
};
consolidate_edits(&mut edits);
consolidate_buffer_edits(&mut edits);
let edits = self.0.apply_edits(edits, cx);
let snapshot = Snapshot {
transforms: self.0.transforms.lock().clone(),
@ -78,9 +79,10 @@ impl<'a> FoldMapWriter<'a> {
let mut folds_cursor = intersecting_folds(&buffer, &self.0.folds, range);
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 {
edits.push(buffer::Edit {
old_bytes: offset_range.clone(),
new_bytes: offset_range,
..Default::default()
});
fold_ixs_to_delete.push(*folds_cursor.start());
folds_cursor.next(&buffer);
@ -101,7 +103,7 @@ impl<'a> FoldMapWriter<'a> {
folds
};
consolidate_edits(&mut edits);
consolidate_buffer_edits(&mut edits);
let edits = self.0.apply_edits(edits, cx);
let snapshot = Snapshot {
transforms: self.0.transforms.lock().clone(),
@ -185,16 +187,16 @@ impl FoldMap {
}
}
fn apply_edits(&self, mut edits: Vec<Edit>, cx: &AppContext) -> Vec<Edit> {
fn apply_edits(&self, buffer_edits: Vec<buffer::Edit>, cx: &AppContext) -> Vec<Edit> {
let buffer = self.buffer.read(cx).snapshot();
let mut edits_iter = edits.iter().cloned().peekable();
let mut buffer_edits_iter = buffer_edits.iter().cloned().peekable();
let mut new_transforms = SumTree::new();
let mut transforms = self.transforms.lock();
let mut cursor = transforms.cursor::<usize, ()>();
cursor.seek(&0, Bias::Right, &());
while let Some(mut edit) = edits_iter.next() {
while let Some(mut edit) = buffer_edits_iter.next() {
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();
@ -206,12 +208,12 @@ impl FoldMap {
loop {
edit.old_bytes.end = *cursor.seek_start();
if let Some(next_edit) = edits_iter.peek() {
if let Some(next_edit) = buffer_edits_iter.peek() {
if next_edit.old_bytes.start > edit.old_bytes.end {
break;
}
let next_edit = edits_iter.next().unwrap();
let next_edit = buffer_edits_iter.next().unwrap();
delta += next_edit.delta();
if next_edit.old_bytes.end >= edit.old_bytes.end {
@ -334,16 +336,17 @@ impl FoldMap {
drop(cursor);
let mut display_edits = Vec::with_capacity(buffer_edits.len());
{
let mut old_transforms = transforms.cursor::<usize, DisplayOffset>();
let mut new_transforms = new_transforms.cursor::<usize, DisplayOffset>();
for edit in &mut edits {
for mut edit in buffer_edits {
old_transforms.seek(&edit.old_bytes.start, Bias::Left, &());
if old_transforms.item().map_or(false, |t| t.is_fold()) {
edit.old_bytes.start = *old_transforms.seek_start();
}
edit.old_bytes.start = old_transforms.sum_start().0
let old_start = old_transforms.sum_start().0
+ (edit.old_bytes.start - old_transforms.seek_start());
old_transforms.seek_forward(&edit.old_bytes.end, Bias::Right, &());
@ -351,14 +354,14 @@ impl FoldMap {
old_transforms.next(&());
edit.old_bytes.end = *old_transforms.seek_start();
}
edit.old_bytes.end = old_transforms.sum_start().0
let old_end = old_transforms.sum_start().0
+ (edit.old_bytes.end - old_transforms.seek_start());
new_transforms.seek(&edit.new_bytes.start, Bias::Left, &());
if new_transforms.item().map_or(false, |t| t.is_fold()) {
edit.new_bytes.start = *new_transforms.seek_start();
}
edit.new_bytes.start = new_transforms.sum_start().0
let new_start = new_transforms.sum_start().0
+ (edit.new_bytes.start - new_transforms.seek_start());
new_transforms.seek_forward(&edit.new_bytes.end, Bias::Right, &());
@ -366,16 +369,21 @@ impl FoldMap {
new_transforms.next(&());
edit.new_bytes.end = *new_transforms.seek_start();
}
edit.new_bytes.end = new_transforms.sum_start().0
let new_end = new_transforms.sum_start().0
+ (edit.new_bytes.end - new_transforms.seek_start());
display_edits.push(Edit {
old_bytes: DisplayOffset(old_start)..DisplayOffset(old_end),
new_bytes: DisplayOffset(new_start)..DisplayOffset(new_end),
});
}
consolidate_edits(&mut edits);
consolidate_display_edits(&mut display_edits);
}
*transforms = new_transforms;
self.version.fetch_add(1, SeqCst);
edits
display_edits
}
}
@ -625,7 +633,30 @@ where
)
}
fn consolidate_edits(edits: &mut Vec<Edit>) {
fn consolidate_buffer_edits(edits: &mut Vec<buffer::Edit>) {
edits.sort_unstable_by(|a, b| {
a.old_bytes
.start
.cmp(&b.old_bytes.start)
.then_with(|| b.old_bytes.end.cmp(&a.old_bytes.end))
});
let mut i = 1;
while i < edits.len() {
let edit = edits[i].clone();
let prev_edit = &mut edits[i - 1];
if prev_edit.old_bytes.end >= edit.old_bytes.start {
prev_edit.old_bytes.end = prev_edit.old_bytes.end.max(edit.old_bytes.end);
prev_edit.new_bytes.start = prev_edit.new_bytes.start.min(edit.new_bytes.start);
prev_edit.new_bytes.end = prev_edit.new_bytes.end.max(edit.new_bytes.end);
edits.remove(i);
continue;
}
i += 1;
}
}
fn consolidate_display_edits(edits: &mut Vec<Edit>) {
edits.sort_unstable_by(|a, b| {
a.old_bytes
.start
@ -930,7 +961,24 @@ impl<'a> sum_tree::Dimension<'a, TransformSummary> for DisplayPoint {
}
#[derive(Copy, Clone, Debug, Default, Eq, Ord, PartialOrd, PartialEq)]
pub struct DisplayOffset(usize);
pub struct DisplayOffset(pub usize);
impl DisplayOffset {
pub fn to_display_point(&self, snapshot: &Snapshot) -> DisplayPoint {
let mut cursor = snapshot
.transforms
.cursor::<DisplayOffset, TransformSummary>();
cursor.seek(self, Bias::Right, &());
let overshoot = if cursor.item().map_or(true, |t| t.is_fold()) {
Point::new(0, (self.0 - cursor.seek_start().0) as u32)
} else {
let buffer_offset = cursor.sum_start().buffer.bytes + self.0 - cursor.seek_start().0;
let buffer_point = snapshot.buffer.to_point(buffer_offset);
buffer_point - cursor.sum_start().buffer.lines
};
DisplayPoint(cursor.sum_start().display.lines + overshoot)
}
}
impl<'a> sum_tree::Dimension<'a, TransformSummary> for DisplayOffset {
fn add_summary(&mut self, summary: &'a TransformSummary, _: &()) {
@ -952,8 +1000,8 @@ impl<'a> sum_tree::Dimension<'a, TransformSummary> for usize {
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Edit {
pub old_bytes: Range<usize>,
pub new_bytes: Range<usize>,
pub old_bytes: Range<DisplayOffset>,
pub new_bytes: Range<DisplayOffset>,
}
impl Edit {
@ -962,20 +1010,11 @@ impl Edit {
}
pub fn deleted_bytes(&self) -> usize {
self.old_bytes.len()
self.old_bytes.end.0 - self.old_bytes.start.0
}
pub fn inserted_bytes(&self) -> usize {
self.new_bytes.len()
}
}
impl From<buffer::Edit> for Edit {
fn from(edit: buffer::Edit) -> Self {
Self {
old_bytes: edit.old_bytes,
new_bytes: edit.new_bytes,
}
self.new_bytes.end.0 - self.new_bytes.start.0
}
}
@ -1004,12 +1043,12 @@ mod tests {
edits,
&[
Edit {
old_bytes: 2..16,
new_bytes: 2..5,
old_bytes: DisplayOffset(2)..DisplayOffset(16),
new_bytes: DisplayOffset(2)..DisplayOffset(5),
},
Edit {
old_bytes: 7..18,
new_bytes: 7..10
old_bytes: DisplayOffset(7)..DisplayOffset(18),
new_bytes: DisplayOffset(7)..DisplayOffset(10)
},
]
);
@ -1030,12 +1069,12 @@ mod tests {
edits,
&[
Edit {
old_bytes: 0..1,
new_bytes: 0..3,
old_bytes: DisplayOffset(0)..DisplayOffset(1),
new_bytes: DisplayOffset(0)..DisplayOffset(3),
},
Edit {
old_bytes: 8..8,
new_bytes: 8..11,
old_bytes: DisplayOffset(8)..DisplayOffset(8),
new_bytes: DisplayOffset(8)..DisplayOffset(11),
},
]
);
@ -1371,11 +1410,12 @@ mod tests {
for (snapshot, edits) in snapshot_edits.drain(..) {
let new_text = snapshot.text();
let mut delta = 0isize;
for mut edit in edits {
edit.old_bytes.start = ((edit.old_bytes.start as isize) + delta) as usize;
edit.old_bytes.end = ((edit.old_bytes.end as isize) + delta) as usize;
for edit in edits {
let old_bytes = ((edit.old_bytes.start.0 as isize) + delta) as usize
..((edit.old_bytes.end.0 as isize) + delta) as usize;
let new_bytes = edit.new_bytes.start.0..edit.new_bytes.end.0;
delta += edit.delta();
text.replace_range(edit.old_bytes, &new_text[edit.new_bytes]);
text.replace_range(old_bytes, &new_text[new_bytes]);
}
assert_eq!(text, new_text);

View file

@ -1,8 +1,10 @@
use std::sync::Arc;
use crate::{
editor::{display_map::fold_map, Point, TextSummary},
settings::Settings,
editor::{
display_map::fold_map::{self, DisplayOffset},
Point, TextSummary,
},
sum_tree::{self, SumTree},
util::Bias,
};
@ -108,8 +110,8 @@ impl BackgroundWrapper {
mut snapshots_tx: watch::Sender<Snapshot>,
) {
let edit = fold_map::Edit {
old_bytes: 0..0,
new_bytes: 0..snapshot.len(),
old_bytes: DisplayOffset(0)..DisplayOffset(0),
new_bytes: DisplayOffset(0)..DisplayOffset(snapshot.len()),
};
self.sync(snapshot, vec![edit]);
if snapshots_tx.send(self.snapshot.clone()).await.is_err() {
@ -179,9 +181,10 @@ impl<'a> sum_tree::Dimension<'a, TransformSummary> for Point {
#[cfg(test)]
mod tests {
use super::*;
use crate::editor::display_map::fold_map::FoldMap;
use crate::editor::{Buffer, ToPoint};
use crate::util::RandomCharIter;
use crate::{
editor::{display_map::fold_map::FoldMap, Buffer},
util::RandomCharIter,
};
use rand::prelude::*;
use std::env;
use Bias::{Left, Right};
@ -225,8 +228,8 @@ mod tests {
let mut wrapper =
BackgroundWrapper::new(config.clone(), font_cache.clone(), font_system.clone());
let edit = fold_map::Edit {
old_bytes: 0..0,
new_bytes: 0..snapshot.len(),
old_bytes: DisplayOffset(0)..DisplayOffset(0),
new_bytes: DisplayOffset(0)..DisplayOffset(snapshot.len()),
};
wrapper.sync(snapshot.clone(), vec![edit]);