Co-Authored-By: Nathan Sobo <nathan@zed.dev>
This commit is contained in:
Antonio Scandurra
2021-07-19 19:34:41 +02:00
co-authored by Nathan Sobo
parent 631a6a2f45
commit 5a33612f0f
2 changed files with 116 additions and 92 deletions
+20 -21
View File
@@ -5,7 +5,10 @@ use super::fold_map::{
OutputOffset as InputOffset, OutputPoint as InputPoint, Snapshot as InputSnapshot,
};
use crate::{settings::StyleId, util::Bias};
use std::{mem, ops::Range};
use std::{
mem,
ops::{AddAssign, Range},
};
pub struct TabMap(Mutex<Snapshot>);
@@ -27,11 +30,15 @@ impl TabMap {
let mut output_edits = Vec::with_capacity(input_edits.len());
for input_edit in input_edits {
let old_start = input_edit.old_bytes.start.to_point(&old_snapshot.input);
let old_end = input_edit.old_bytes.end.to_point(&old_snapshot.input);
let new_start = input_edit.new_bytes.start.to_point(&new_snapshot.input);
let new_end = input_edit.new_bytes.end.to_point(&new_snapshot.input);
output_edits.push(Edit {
old_bytes: old_snapshot.to_output_offset(input_edit.old_bytes.start)
..old_snapshot.to_output_offset(input_edit.old_bytes.end),
new_bytes: new_snapshot.to_output_offset(input_edit.new_bytes.start)
..new_snapshot.to_output_offset(input_edit.new_bytes.end),
old_lines: old_snapshot.to_output_point(old_start)
..old_snapshot.to_output_point(old_end),
new_lines: new_snapshot.to_output_point(new_start)
..new_snapshot.to_output_point(new_end),
});
}
@@ -253,24 +260,16 @@ impl OutputPoint {
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Edit {
pub old_bytes: Range<OutputOffset>,
pub new_bytes: Range<OutputOffset>,
impl AddAssign<Self> for OutputPoint {
fn add_assign(&mut self, rhs: Self) {
self.0 += rhs.0;
}
}
impl Edit {
pub fn delta(&self) -> isize {
self.inserted_bytes() as isize - self.deleted_bytes() as isize
}
pub fn deleted_bytes(&self) -> usize {
self.old_bytes.end.0 - self.old_bytes.start.0
}
pub fn inserted_bytes(&self) -> usize {
self.new_bytes.end.0 - self.new_bytes.start.0
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Edit {
pub old_lines: Range<OutputPoint>,
pub new_lines: Range<OutputPoint>,
}
#[derive(Clone, Debug, Default, Eq, PartialEq)]
+96 -71
View File
@@ -1,15 +1,17 @@
use super::tab_map::{
Edit as InputEdit, OutputOffset as InputOffset, Snapshot as InputSnapshot, TextSummary,
Edit as InputEdit, OutputOffset as InputOffset, OutputPoint as InputPoint,
Snapshot as InputSnapshot, TextSummary,
};
use crate::{
editor::Point,
sum_tree::{self, SumTree},
util::Bias,
};
use gpui::{font_cache::FamilyId, AppContext, FontCache, FontSystem, Task};
use parking_lot::Mutex;
use postage::{prelude::Sink, watch};
use smol::channel;
use std::sync::Arc;
use std::{ops::Range, sync::Arc};
#[derive(Copy, Clone, Debug, Default, Eq, Ord, PartialOrd, PartialEq)]
pub struct OutputPoint(super::Point);
@@ -148,8 +150,8 @@ impl BackgroundWrapper {
mut snapshots_tx: watch::Sender<Snapshot>,
) {
let edit = InputEdit {
old_bytes: InputOffset(0)..InputOffset(0),
new_bytes: InputOffset(0)..snapshot.len(),
old_lines: Default::default()..Default::default(),
new_lines: Default::default()..snapshot.max_point(),
};
self.sync(snapshot, vec![edit]);
if snapshots_tx.send(self.snapshot.clone()).await.is_err() {
@@ -164,85 +166,108 @@ impl BackgroundWrapper {
}
}
fn sync(&mut self, snapshot: InputSnapshot, edits: Vec<InputEdit>) {
fn sync(&mut self, new_snapshot: InputSnapshot, edits: Vec<InputEdit>) {
if edits.is_empty() {
return;
}
let font_id = self
.font_cache
.select_font(self.config.font_family, &Default::default());
.select_font(self.config.font_family, &Default::default())
.unwrap();
let font_size = self.config.font_size;
let wrap_width = self.config.wrap_width;
let mut new_transforms = SumTree::new();
let mut new_transforms;
{
// let mut old_cursor = self.snapshot.transforms.cursor::<DisplayPoint, ()>();
// let mut position = DisplayPoint::zero();
// for edit in edits {
// let old_start = DisplayPoint::new(
// edit.old_bytes.start.to_display_point(&self.snapshot).row(),
// 0,
// );
// let old_end = DisplayPoint::new(
// edit.old_bytes.end.to_display_point(&self.snapshot).row() + 1,
// 0,
// );
// let new_start =
// DisplayPoint::new(edit.new_bytes.start.to_display_point(&snapshot).row(), 0);
// let new_end =
// DisplayPoint::new(edit.new_bytes.end.to_display_point(&snapshot).row() + 1, 0);
struct RowEdit {
old_rows: Range<u32>,
new_rows: Range<u32>,
}
// if position > old_cursor.seek_start() && old_start >= old_cursor.seek_end(&()) {
// old_cursor.next(&());
// }
let mut edits = edits
.into_iter()
.map(|edit| RowEdit {
old_rows: edit.old_lines.start.row()..edit.old_lines.end.row() + 1,
new_rows: edit.new_lines.start.row()..edit.new_lines.end.row() + 1,
})
.peekable();
let mut old_cursor = self.snapshot.transforms.cursor::<InputPoint, ()>();
// let prefix = old_cursor.slice(&old_start, Bias::Right, &());
// new_transforms.push_tree(prefix, &());
// new_transforms.push(
// Transform::isomorphic(
// self.snapshot
// .folds_snapshot
// .text_summary_for_range(position..old_start),
// ),
// &(),
// );
new_transforms = old_cursor.slice(
&InputPoint::new(edits.peek().unwrap().old_rows.start, 0),
Bias::Right,
&(),
);
// let mut row = new_start.row();
// let mut line = String::new();
// 'outer: for chunk in snapshot.chunks_at(snapshot.to_display_offset(new_start)) {
// for (ix, line_chunk) in chunk.split('\n').enumerate() {
// if ix > 0 {
// let mut prev_boundary_ix = 0;
// for boundary_ix in self
// .font_system
// .wrap_line(&line, font_id, font_size, wrap_width)
// {
// let wrapped = &line[prev_boundary_ix..boundary_ix];
// new_transforms
// .push(Transform::isomorphic(TextSummary::from(wrapped)));
// new_transforms.push(Transform::newline());
// prev_boundary_ix = boundary_ix;
// }
for edit in edits {
if edit.new_rows.start > new_transforms.summary().input.row() {
new_transforms.push(
Transform::isomorphic(new_snapshot.input.text_summary_for_rows(
new_transforms.summary().input.row()..edit.new_rows.start,
)),
&(),
);
}
// line.clear();
// row += 1;
// if row == new_end.row() {
// break 'outer;
// }
// }
let mut row = edit.new_rows.start;
let mut line = String::new();
'outer: for chunk in new_snapshot.chunks_at(InputPoint::new(row, 0)) {
for (ix, line_chunk) in chunk.split('\n').enumerate() {
if ix > 0 {
let mut prev_boundary_ix = 0;
for boundary_ix in self
.font_system
.wrap_line(&line, font_id, font_size, wrap_width)
{
let wrapped = &line[prev_boundary_ix..boundary_ix];
new_transforms
.push(Transform::isomorphic(TextSummary::from(wrapped)), &());
new_transforms.push(Transform::newline(), &());
prev_boundary_ix = boundary_ix;
}
// line.push_str(line_chunk);
// }
// }
line.clear();
row += 1;
if row == edit.new_rows.end {
break 'outer;
}
}
// old_cursor.seek_forward(&old_end, Bias::Right, &());
// position = old_end;
// }
line.push_str(line_chunk);
}
}
// if position > old_cursor.seek_start() && old_start >= old_cursor.seek_end(&()) {
// old_cursor.next(&());
// }
old_cursor.seek_forward(&edit.old_rows.end, Bias::Right, &());
if let Some(next_edit) = edits.peek() {
if next_edit.old_rows.start > old_cursor.seek_end(&()).row() {
new_transforms.push(
Transform::isomorphic(self.snapshot.input.text_summary_for_rows(
edit.old_rows.end..old_cursor.seek_end(&()).row(),
)),
&(),
);
old_cursor.next(&());
new_transforms.push_tree(
old_cursor.slice(&next_edit.old_rows.start, Bias::Right, &()),
&(),
);
}
} else {
new_transforms.push(
Transform::isomorphic(self.snapshot.input.text_summary_for_rows(
edit.old_rows.end..old_cursor.seek_end(&()).row(),
)),
&(),
);
old_cursor.next(&());
new_transforms.push_tree(old_cursor.suffix(&()), &());
}
}
}
self.snapshot.transforms = new_transforms;
self.snapshot.version = snapshot.version();
self.snapshot.version = new_snapshot.version();
}
}
@@ -303,9 +328,9 @@ impl sum_tree::Summary for TransformSummary {
}
}
impl<'a> sum_tree::Dimension<'a, TransformSummary> for Point {
impl<'a> sum_tree::Dimension<'a, TransformSummary> for InputPoint {
fn add_summary(&mut self, summary: &'a TransformSummary, _: &()) {
*self += &summary.input.lines;
*self += &InputPoint(summary.input.lines);
}
}
@@ -367,8 +392,8 @@ mod tests {
font_system.clone(),
);
let edit = InputEdit {
old_bytes: InputOffset(0)..InputOffset(0),
new_bytes: InputOffset(0)..tabs_snapshot.len(),
old_lines: Default::default()..Default::default(),
new_lines: Default::default()..tabs_snapshot.max_point(),
};
wrapper.sync(tabs_snapshot.clone(), vec![edit]);