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 { if range.start != range.end {
let fold = Fold(buffer.anchor_after(range.start)..buffer.anchor_before(range.end)); let fold = Fold(buffer.anchor_after(range.start)..buffer.anchor_before(range.end));
folds.push(fold); folds.push(fold);
edits.push(Edit { edits.push(buffer::Edit {
old_bytes: range.clone(), old_bytes: range.clone(),
new_bytes: range.clone(), new_bytes: range.clone(),
..Default::default()
}); });
} }
} }
@ -54,7 +55,7 @@ impl<'a> FoldMapWriter<'a> {
new_tree new_tree
}; };
consolidate_edits(&mut edits); consolidate_buffer_edits(&mut edits);
let edits = self.0.apply_edits(edits, cx); let edits = self.0.apply_edits(edits, cx);
let snapshot = Snapshot { let snapshot = Snapshot {
transforms: self.0.transforms.lock().clone(), 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); let mut folds_cursor = intersecting_folds(&buffer, &self.0.folds, range);
while let Some(fold) = folds_cursor.item() { while let Some(fold) = folds_cursor.item() {
let offset_range = fold.0.start.to_offset(&buffer)..fold.0.end.to_offset(&buffer); 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(), old_bytes: offset_range.clone(),
new_bytes: offset_range, new_bytes: offset_range,
..Default::default()
}); });
fold_ixs_to_delete.push(*folds_cursor.start()); fold_ixs_to_delete.push(*folds_cursor.start());
folds_cursor.next(&buffer); folds_cursor.next(&buffer);
@ -101,7 +103,7 @@ impl<'a> FoldMapWriter<'a> {
folds folds
}; };
consolidate_edits(&mut edits); consolidate_buffer_edits(&mut edits);
let edits = self.0.apply_edits(edits, cx); let edits = self.0.apply_edits(edits, cx);
let snapshot = Snapshot { let snapshot = Snapshot {
transforms: self.0.transforms.lock().clone(), 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 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 new_transforms = SumTree::new();
let mut transforms = self.transforms.lock(); let mut transforms = self.transforms.lock();
let mut cursor = transforms.cursor::<usize, ()>(); let mut cursor = transforms.cursor::<usize, ()>();
cursor.seek(&0, Bias::Right, &()); 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, &()), &()); new_transforms.push_tree(cursor.slice(&edit.old_bytes.start, Bias::Left, &()), &());
edit.new_bytes.start -= edit.old_bytes.start - cursor.seek_start(); edit.new_bytes.start -= edit.old_bytes.start - cursor.seek_start();
edit.old_bytes.start = *cursor.seek_start(); edit.old_bytes.start = *cursor.seek_start();
@ -206,12 +208,12 @@ impl FoldMap {
loop { loop {
edit.old_bytes.end = *cursor.seek_start(); 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 { if next_edit.old_bytes.start > edit.old_bytes.end {
break; break;
} }
let next_edit = edits_iter.next().unwrap(); let next_edit = buffer_edits_iter.next().unwrap();
delta += next_edit.delta(); delta += next_edit.delta();
if next_edit.old_bytes.end >= edit.old_bytes.end { if next_edit.old_bytes.end >= edit.old_bytes.end {
@ -334,16 +336,17 @@ impl FoldMap {
drop(cursor); drop(cursor);
let mut display_edits = Vec::with_capacity(buffer_edits.len());
{ {
let mut old_transforms = transforms.cursor::<usize, DisplayOffset>(); let mut old_transforms = transforms.cursor::<usize, DisplayOffset>();
let mut new_transforms = new_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, &()); old_transforms.seek(&edit.old_bytes.start, Bias::Left, &());
if old_transforms.item().map_or(false, |t| t.is_fold()) { 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.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()); + (edit.old_bytes.start - old_transforms.seek_start());
old_transforms.seek_forward(&edit.old_bytes.end, Bias::Right, &()); old_transforms.seek_forward(&edit.old_bytes.end, Bias::Right, &());
@ -351,14 +354,14 @@ impl FoldMap {
old_transforms.next(&()); old_transforms.next(&());
edit.old_bytes.end = *old_transforms.seek_start(); 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()); + (edit.old_bytes.end - old_transforms.seek_start());
new_transforms.seek(&edit.new_bytes.start, Bias::Left, &()); new_transforms.seek(&edit.new_bytes.start, Bias::Left, &());
if new_transforms.item().map_or(false, |t| t.is_fold()) { 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.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()); + (edit.new_bytes.start - new_transforms.seek_start());
new_transforms.seek_forward(&edit.new_bytes.end, Bias::Right, &()); new_transforms.seek_forward(&edit.new_bytes.end, Bias::Right, &());
@ -366,16 +369,21 @@ impl FoldMap {
new_transforms.next(&()); new_transforms.next(&());
edit.new_bytes.end = *new_transforms.seek_start(); 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()); + (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; *transforms = new_transforms;
self.version.fetch_add(1, SeqCst); 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| { edits.sort_unstable_by(|a, b| {
a.old_bytes a.old_bytes
.start .start
@ -930,7 +961,24 @@ impl<'a> sum_tree::Dimension<'a, TransformSummary> for DisplayPoint {
} }
#[derive(Copy, Clone, Debug, Default, Eq, Ord, PartialOrd, PartialEq)] #[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 { impl<'a> sum_tree::Dimension<'a, TransformSummary> for DisplayOffset {
fn add_summary(&mut self, summary: &'a TransformSummary, _: &()) { 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)] #[derive(Clone, Debug, PartialEq, Eq)]
pub struct Edit { pub struct Edit {
pub old_bytes: Range<usize>, pub old_bytes: Range<DisplayOffset>,
pub new_bytes: Range<usize>, pub new_bytes: Range<DisplayOffset>,
} }
impl Edit { impl Edit {
@ -962,20 +1010,11 @@ impl Edit {
} }
pub fn deleted_bytes(&self) -> usize { 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 { pub fn inserted_bytes(&self) -> usize {
self.new_bytes.len() self.new_bytes.end.0 - self.new_bytes.start.0
}
}
impl From<buffer::Edit> for Edit {
fn from(edit: buffer::Edit) -> Self {
Self {
old_bytes: edit.old_bytes,
new_bytes: edit.new_bytes,
}
} }
} }
@ -1004,12 +1043,12 @@ mod tests {
edits, edits,
&[ &[
Edit { Edit {
old_bytes: 2..16, old_bytes: DisplayOffset(2)..DisplayOffset(16),
new_bytes: 2..5, new_bytes: DisplayOffset(2)..DisplayOffset(5),
}, },
Edit { Edit {
old_bytes: 7..18, old_bytes: DisplayOffset(7)..DisplayOffset(18),
new_bytes: 7..10 new_bytes: DisplayOffset(7)..DisplayOffset(10)
}, },
] ]
); );
@ -1030,12 +1069,12 @@ mod tests {
edits, edits,
&[ &[
Edit { Edit {
old_bytes: 0..1, old_bytes: DisplayOffset(0)..DisplayOffset(1),
new_bytes: 0..3, new_bytes: DisplayOffset(0)..DisplayOffset(3),
}, },
Edit { Edit {
old_bytes: 8..8, old_bytes: DisplayOffset(8)..DisplayOffset(8),
new_bytes: 8..11, new_bytes: DisplayOffset(8)..DisplayOffset(11),
}, },
] ]
); );
@ -1371,11 +1410,12 @@ mod tests {
for (snapshot, edits) in snapshot_edits.drain(..) { for (snapshot, edits) in snapshot_edits.drain(..) {
let new_text = snapshot.text(); let new_text = snapshot.text();
let mut delta = 0isize; let mut delta = 0isize;
for mut edit in edits { for edit in edits {
edit.old_bytes.start = ((edit.old_bytes.start as isize) + delta) as usize; let old_bytes = ((edit.old_bytes.start.0 as isize) + delta) as usize
edit.old_bytes.end = ((edit.old_bytes.end 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(); 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); assert_eq!(text, new_text);

View file

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