mirror of
https://github.com/zed-industries/zed.git
synced 2025-02-05 02:20:10 +00:00
Implement Snapshot::interpolate
This commit is contained in:
parent
b66de06d0e
commit
3d8c59af31
2 changed files with 93 additions and 31 deletions
|
@ -261,6 +261,12 @@ impl OutputPoint {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<super::Point> for OutputPoint {
|
||||||
|
fn from(point: super::Point) -> Self {
|
||||||
|
Self(point)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl AddAssign<Self> for OutputPoint {
|
impl AddAssign<Self> for OutputPoint {
|
||||||
fn add_assign(&mut self, rhs: Self) {
|
fn add_assign(&mut self, rhs: Self) {
|
||||||
self.0 += &rhs.0;
|
self.0 += &rhs.0;
|
||||||
|
|
|
@ -62,7 +62,6 @@ impl Sub<Self> for OutputPoint {
|
||||||
pub struct Snapshot {
|
pub struct Snapshot {
|
||||||
transforms: SumTree<Transform>,
|
transforms: SumTree<Transform>,
|
||||||
input: InputSnapshot,
|
input: InputSnapshot,
|
||||||
version: usize,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Snapshot {
|
impl Snapshot {
|
||||||
|
@ -78,11 +77,67 @@ impl Snapshot {
|
||||||
},
|
},
|
||||||
&(),
|
&(),
|
||||||
),
|
),
|
||||||
version: input.version(),
|
|
||||||
input,
|
input,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn interpolate(&mut self, new_snapshot: InputSnapshot, edits: &[InputEdit]) {
|
||||||
|
if edits.is_empty() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut new_transforms;
|
||||||
|
{
|
||||||
|
let mut old_cursor = self.transforms.cursor::<InputPoint, ()>();
|
||||||
|
let mut edits = edits.into_iter().peekable();
|
||||||
|
new_transforms =
|
||||||
|
old_cursor.slice(&edits.peek().unwrap().old_lines.start, Bias::Right, &());
|
||||||
|
|
||||||
|
while let Some(edit) = edits.next() {
|
||||||
|
if edit.new_lines.start > InputPoint::from(new_transforms.summary().input.lines) {
|
||||||
|
let summary = new_snapshot.text_summary_for_range(
|
||||||
|
InputPoint::from(new_transforms.summary().input.lines)
|
||||||
|
..edit.new_lines.start,
|
||||||
|
);
|
||||||
|
new_transforms.push_or_extend(Transform::isomorphic(summary));
|
||||||
|
}
|
||||||
|
|
||||||
|
new_transforms.push_or_extend(Transform::isomorphic(
|
||||||
|
new_snapshot.text_summary_for_range(edit.new_lines.clone()),
|
||||||
|
));
|
||||||
|
|
||||||
|
old_cursor.seek_forward(&edit.old_lines.end, Bias::Right, &());
|
||||||
|
if let Some(next_edit) = edits.peek() {
|
||||||
|
if next_edit.old_lines.start > old_cursor.seek_end(&()) {
|
||||||
|
if old_cursor.seek_end(&()) > edit.old_lines.end {
|
||||||
|
let summary = self.input.text_summary_for_range(
|
||||||
|
edit.old_lines.end..old_cursor.seek_end(&()),
|
||||||
|
);
|
||||||
|
new_transforms.push_or_extend(Transform::isomorphic(summary));
|
||||||
|
}
|
||||||
|
old_cursor.next(&());
|
||||||
|
new_transforms.push_tree(
|
||||||
|
old_cursor.slice(&next_edit.old_lines.start, Bias::Right, &()),
|
||||||
|
&(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if old_cursor.seek_end(&()) > edit.old_lines.end {
|
||||||
|
let summary = self
|
||||||
|
.input
|
||||||
|
.text_summary_for_range(edit.old_lines.end..old_cursor.seek_end(&()));
|
||||||
|
new_transforms.push_or_extend(Transform::isomorphic(summary));
|
||||||
|
}
|
||||||
|
old_cursor.next(&());
|
||||||
|
new_transforms.push_tree(old_cursor.suffix(&()), &());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.transforms = new_transforms;
|
||||||
|
self.input = new_snapshot;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn chunks_at(&self, point: OutputPoint) -> Chunks {
|
pub fn chunks_at(&self, point: OutputPoint) -> Chunks {
|
||||||
let mut transforms = self.transforms.cursor();
|
let mut transforms = self.transforms.cursor();
|
||||||
transforms.seek(&point, Bias::Right, &());
|
transforms.seek(&point, Bias::Right, &());
|
||||||
|
@ -145,7 +200,6 @@ impl<'a> Iterator for Chunks<'a> {
|
||||||
|
|
||||||
struct State {
|
struct State {
|
||||||
snapshot: Snapshot,
|
snapshot: Snapshot,
|
||||||
interpolated_version: usize,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
@ -179,10 +233,7 @@ impl WrapMap {
|
||||||
};
|
};
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
state: Mutex::new(State {
|
state: Mutex::new(State { snapshot }),
|
||||||
interpolated_version: snapshot.version,
|
|
||||||
snapshot,
|
|
||||||
}),
|
|
||||||
edits_tx,
|
edits_tx,
|
||||||
background_snapshots: background_snapshots_rx,
|
background_snapshots: background_snapshots_rx,
|
||||||
_background_task: background_task,
|
_background_task: background_task,
|
||||||
|
@ -190,7 +241,10 @@ impl WrapMap {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sync(&self, input: InputSnapshot, edits: Vec<InputEdit>) -> Snapshot {
|
pub fn sync(&self, input: InputSnapshot, edits: Vec<InputEdit>) -> Snapshot {
|
||||||
// TODO: interpolate
|
self.state
|
||||||
|
.lock()
|
||||||
|
.snapshot
|
||||||
|
.interpolate(input.clone(), &edits);
|
||||||
self.edits_tx.try_send((input, edits)).unwrap();
|
self.edits_tx.try_send((input, edits)).unwrap();
|
||||||
self.state.lock().snapshot.clone()
|
self.state.lock().snapshot.clone()
|
||||||
}
|
}
|
||||||
|
@ -378,30 +432,8 @@ impl BackgroundWrapper {
|
||||||
|
|
||||||
self.snapshot = Snapshot {
|
self.snapshot = Snapshot {
|
||||||
transforms: new_transforms,
|
transforms: new_transforms,
|
||||||
version: new_snapshot.version(),
|
|
||||||
input: new_snapshot,
|
input: new_snapshot,
|
||||||
};
|
};
|
||||||
self.check_invariants();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn check_invariants(&self) {
|
|
||||||
#[cfg(debug_assertions)]
|
|
||||||
{
|
|
||||||
let summary = self.snapshot.transforms.summary();
|
|
||||||
assert_eq!(
|
|
||||||
InputPoint::new(summary.input.lines.row, summary.input.lines.column),
|
|
||||||
self.snapshot.input.max_point()
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut transforms = self.snapshot.transforms.cursor::<(), ()>().peekable();
|
|
||||||
while let Some(transform) = transforms.next() {
|
|
||||||
let next_transform = transforms.peek();
|
|
||||||
assert!(
|
|
||||||
!transform.is_isomorphic()
|
|
||||||
|| next_transform.map_or(true, |t| !t.is_isomorphic())
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -613,10 +645,14 @@ mod tests {
|
||||||
unwrapped_text
|
unwrapped_text
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let mut interpolated_snapshot = wrapper.snapshot.clone();
|
||||||
for _i in 0..operations {
|
for _i in 0..operations {
|
||||||
buffer.update(cx, |buffer, cx| buffer.randomly_mutate(&mut rng, cx));
|
buffer.update(cx, |buffer, cx| buffer.randomly_mutate(&mut rng, cx));
|
||||||
let (snapshot, edits) = fold_map.read(cx.as_ref());
|
let (snapshot, edits) = fold_map.read(cx.as_ref());
|
||||||
let (snapshot, edits) = tab_map.sync(snapshot, edits);
|
let (snapshot, edits) = tab_map.sync(snapshot, edits);
|
||||||
|
interpolated_snapshot.interpolate(snapshot.clone(), &edits);
|
||||||
|
interpolated_snapshot.check_invariants();
|
||||||
|
|
||||||
let unwrapped_text = snapshot.text();
|
let unwrapped_text = snapshot.text();
|
||||||
let expected_text = wrap_text(
|
let expected_text = wrap_text(
|
||||||
&unwrapped_text,
|
&unwrapped_text,
|
||||||
|
@ -625,7 +661,7 @@ mod tests {
|
||||||
font_system.as_ref(),
|
font_system.as_ref(),
|
||||||
);
|
);
|
||||||
wrapper.sync(snapshot, edits);
|
wrapper.sync(snapshot, edits);
|
||||||
|
wrapper.snapshot.check_invariants();
|
||||||
let actual_text = wrapper
|
let actual_text = wrapper
|
||||||
.snapshot
|
.snapshot
|
||||||
.chunks_at(OutputPoint::zero())
|
.chunks_at(OutputPoint::zero())
|
||||||
|
@ -635,6 +671,8 @@ mod tests {
|
||||||
"unwrapped text is: {:?}",
|
"unwrapped text is: {:?}",
|
||||||
unwrapped_text
|
unwrapped_text
|
||||||
);
|
);
|
||||||
|
|
||||||
|
interpolated_snapshot = wrapper.snapshot.clone();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -661,4 +699,22 @@ mod tests {
|
||||||
}
|
}
|
||||||
wrapped_text
|
wrapped_text
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Snapshot {
|
||||||
|
fn check_invariants(&self) {
|
||||||
|
assert_eq!(
|
||||||
|
InputPoint::from(self.transforms.summary().input.lines),
|
||||||
|
self.input.max_point()
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut transforms = self.transforms.cursor::<(), ()>().peekable();
|
||||||
|
while let Some(transform) = transforms.next() {
|
||||||
|
let next_transform = transforms.peek();
|
||||||
|
assert!(
|
||||||
|
!transform.is_isomorphic()
|
||||||
|
|| next_transform.map_or(true, |t| !t.is_isomorphic())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue