This commit is contained in:
Antonio Scandurra
2021-05-31 16:57:15 +02:00
parent 3597305fe3
commit e8a9eee84f
4 changed files with 81 additions and 93 deletions
+42 -80
View File
@@ -1498,16 +1498,12 @@ impl Buffer {
Operation::UpdateSelections { selections, .. } => { Operation::UpdateSelections { selections, .. } => {
if let Some(selections) = selections { if let Some(selections) = selections {
selections.iter().all(|selection| { selections.iter().all(|selection| {
let contains_start = match selection.start { let contains_start = match &selection.start {
Anchor::Middle { insertion_id, .. } => { Anchor::Middle { version, .. } => self.version >= *version,
self.version.observed(insertion_id)
}
_ => true, _ => true,
}; };
let contains_end = match selection.end { let contains_end = match &selection.end {
Anchor::Middle { insertion_id, .. } => { Anchor::Middle { version, .. } => self.version >= *version,
self.version.observed(insertion_id)
}
_ => true, _ => true,
}; };
contains_start && contains_end contains_start && contains_end
@@ -1980,62 +1976,15 @@ impl Buffer {
let max_offset = self.len(); let max_offset = self.len();
assert!(offset <= max_offset, "offset is out of range"); assert!(offset <= max_offset, "offset is out of range");
let seek_bias; if offset == 0 && bias == AnchorBias::Left {
match bias { Anchor::Start
AnchorBias::Left => { } else if offset == max_offset && bias == AnchorBias::Right {
if offset == 0 { Anchor::End
return Anchor::Start; } else {
} else {
seek_bias = SeekBias::Left;
}
}
AnchorBias::Right => {
if offset == max_offset {
return Anchor::End;
} else {
seek_bias = SeekBias::Right;
}
}
};
let mut cursor = self.fragments.cursor::<usize, usize>();
cursor.seek(&offset, seek_bias, &());
let fragment = cursor.item().unwrap();
let offset_in_fragment = offset - cursor.start();
let offset_in_insertion = fragment.range_in_insertion.start + offset_in_fragment;
let anchor = Anchor::Middle {
insertion_id: fragment.insertion.id,
offset: offset_in_insertion,
bias,
};
anchor
}
fn fragment_id_for_anchor(&self, anchor: &Anchor) -> Result<&FragmentId> {
match anchor {
Anchor::Start => Ok(FragmentId::max_value()),
Anchor::End => Ok(FragmentId::min_value()),
Anchor::Middle { Anchor::Middle {
insertion_id,
offset, offset,
bias, bias,
.. version: self.version(),
} => {
let seek_bias = match bias {
AnchorBias::Left => SeekBias::Left,
AnchorBias::Right => SeekBias::Right,
};
let splits = self
.insertion_splits
.get(&insertion_id)
.ok_or_else(|| anyhow!("split does not exist for insertion id"))?;
let mut splits_cursor = splits.cursor::<usize, ()>();
splits_cursor.seek(offset, seek_bias, &());
splits_cursor
.item()
.ok_or_else(|| anyhow!("split offset is out of range"))
.map(|split| &split.fragment_id)
} }
} }
} }
@@ -2045,31 +1994,44 @@ impl Buffer {
Anchor::Start => TextSummary::default(), Anchor::Start => TextSummary::default(),
Anchor::End => self.text_summary(), Anchor::End => self.text_summary(),
Anchor::Middle { Anchor::Middle {
insertion_id,
offset, offset,
bias, bias,
version,
} => { } => {
let seek_bias = match bias { let mut cursor = self
AnchorBias::Left => SeekBias::Left, .fragments
AnchorBias::Right => SeekBias::Right, .filter::<_, usize>(|summary| !(*version >= summary.max_version), &());
};
let splits = self let mut old_offset = 0;
.insertion_splits let mut new_offset = 0;
.get(&insertion_id) while let Some(fragment) = cursor.item() {
.expect("split does not exist for insertion id"); let bytes_since_last_fragment = *cursor.start() - new_offset;
let mut splits_cursor = splits.cursor::<usize, ()>(); let comparison = offset.cmp(&(old_offset + bytes_since_last_fragment));
splits_cursor.seek(offset, seek_bias, &()); if comparison == cmp::Ordering::Greater
let split = splits_cursor.item().expect("split offset is out of range"); || (comparison == cmp::Ordering::Equal && *bias == AnchorBias::Right)
{
old_offset += bytes_since_last_fragment;
new_offset += bytes_since_last_fragment;
let mut fragments_cursor = self.fragments.cursor::<FragmentIdRef, usize>(); if fragment.was_visible(version, &self.undo_map) {
fragments_cursor.seek(&FragmentIdRef::new(&split.fragment_id), SeekBias::Left, &()); let comparison = offset.cmp(&(old_offset + fragment.visible_len()));
let fragment = fragments_cursor.item().expect("fragment id does not exist"); if comparison == cmp::Ordering::Greater
|| (comparison == cmp::Ordering::Equal
let mut ix = *fragments_cursor.start(); && *bias == AnchorBias::Right)
if fragment.visible { {
ix += offset - fragment.range_in_insertion.start; old_offset += fragment.len();
} else {
break;
}
}
new_offset += fragment.visible_len();
cursor.next(&());
} else {
break;
}
} }
let ix = new_offset + offset.saturating_sub(old_offset);
self.text_summary_for_range(0..ix) self.text_summary_for_range(0..ix)
} }
} }
+14 -11
View File
@@ -1,17 +1,16 @@
use super::Buffer; use super::{Buffer, ToOffset};
use crate::time; use crate::time;
use anyhow::Result; use anyhow::Result;
use std::cmp::Ordering; use std::{cmp::Ordering, ops::Range};
use std::ops::Range;
#[derive(Clone, Eq, PartialEq, Debug, Hash)] #[derive(Clone, Eq, PartialEq, Debug, Hash)]
pub enum Anchor { pub enum Anchor {
Start, Start,
End, End,
Middle { Middle {
insertion_id: time::Local,
offset: usize, offset: usize,
bias: AnchorBias, bias: AnchorBias,
version: time::Global,
}, },
} }
@@ -55,18 +54,22 @@ impl Anchor {
Anchor::Middle { Anchor::Middle {
offset: self_offset, offset: self_offset,
bias: self_bias, bias: self_bias,
.. version: self_version,
}, },
Anchor::Middle { Anchor::Middle {
offset: other_offset, offset: other_offset,
bias: other_bias, bias: other_bias,
.. version: other_version,
}, },
) => buffer ) => {
.fragment_id_for_anchor(self)? let offset_comparison = if self_version == other_version {
.cmp(buffer.fragment_id_for_anchor(other)?) self_offset.cmp(other_offset)
.then_with(|| self_offset.cmp(other_offset)) } else {
.then_with(|| self_bias.cmp(other_bias)), self.to_offset(buffer).cmp(&other.to_offset(buffer))
};
offset_comparison.then_with(|| self_bias.cmp(other_bias))
}
}) })
} }
+24 -1
View File
@@ -1027,11 +1027,34 @@ mod tests {
for _ in 0..operations { for _ in 0..operations {
log::info!("text: {:?}", buffer.read(cx).text()); log::info!("text: {:?}", buffer.read(cx).text());
{
let buffer = buffer.read(cx);
let mut cursor = map.folds.cursor::<(), ()>();
cursor.next(buffer);
let mut prev_fold: Option<&Fold> = None;
while let Some(fold) = cursor.item() {
if let Some(prev_fold) = prev_fold {
let prev_fold = prev_fold.0.start.to_offset(buffer)
..prev_fold.0.end.to_offset(buffer);
let fold = fold.0.start.to_offset(buffer)..fold.0.end.to_offset(buffer);
assert!(
fold.start > prev_fold.start
|| (fold.start == prev_fold.start && fold.end <= prev_fold.end),
"prev fold {:?}\ncurr fold {:?}",
prev_fold,
fold
);
}
prev_fold = Some(fold);
cursor.next(buffer);
}
}
match rng.gen_range(0..=100) { match rng.gen_range(0..=100) {
0..=34 => { 0..=34 => {
let buffer = buffer.read(cx); let buffer = buffer.read(cx);
let mut to_fold = Vec::new(); let mut to_fold = Vec::new();
for _ in 0..rng.gen_range(1..=5) { for _ in 0..rng.gen_range(1..=2) {
let end = buffer.clip_offset(rng.gen_range(0..=buffer.len()), Right); let end = buffer.clip_offset(rng.gen_range(0..=buffer.len()), Right);
let start = buffer.clip_offset(rng.gen_range(0..=end), Left); let start = buffer.clip_offset(rng.gen_range(0..=end), Left);
to_fold.push(start..end); to_fold.push(start..end);
+1 -1
View File
@@ -54,7 +54,7 @@ impl<'a> AddAssign<&'a Local> for Local {
} }
} }
#[derive(Clone, Debug, Default, Eq, PartialEq)] #[derive(Clone, Debug, Default, Hash, Eq, PartialEq)]
pub struct Global(SmallVec<[Local; 3]>); pub struct Global(SmallVec<[Local; 3]>);
impl Global { impl Global {