mirror of
https://github.com/zed-industries/zed.git
synced 2024-11-08 07:35:01 +03:00
WIP
This commit is contained in:
parent
3597305fe3
commit
e8a9eee84f
@ -1498,16 +1498,12 @@ impl Buffer {
|
||||
Operation::UpdateSelections { selections, .. } => {
|
||||
if let Some(selections) = selections {
|
||||
selections.iter().all(|selection| {
|
||||
let contains_start = match selection.start {
|
||||
Anchor::Middle { insertion_id, .. } => {
|
||||
self.version.observed(insertion_id)
|
||||
}
|
||||
let contains_start = match &selection.start {
|
||||
Anchor::Middle { version, .. } => self.version >= *version,
|
||||
_ => true,
|
||||
};
|
||||
let contains_end = match selection.end {
|
||||
Anchor::Middle { insertion_id, .. } => {
|
||||
self.version.observed(insertion_id)
|
||||
}
|
||||
let contains_end = match &selection.end {
|
||||
Anchor::Middle { version, .. } => self.version >= *version,
|
||||
_ => true,
|
||||
};
|
||||
contains_start && contains_end
|
||||
@ -1980,62 +1976,15 @@ impl Buffer {
|
||||
let max_offset = self.len();
|
||||
assert!(offset <= max_offset, "offset is out of range");
|
||||
|
||||
let seek_bias;
|
||||
match bias {
|
||||
AnchorBias::Left => {
|
||||
if offset == 0 {
|
||||
return Anchor::Start;
|
||||
} 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()),
|
||||
if offset == 0 && bias == AnchorBias::Left {
|
||||
Anchor::Start
|
||||
} else if offset == max_offset && bias == AnchorBias::Right {
|
||||
Anchor::End
|
||||
} else {
|
||||
Anchor::Middle {
|
||||
insertion_id,
|
||||
offset,
|
||||
bias,
|
||||
..
|
||||
} => {
|
||||
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)
|
||||
version: self.version(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2045,31 +1994,44 @@ impl Buffer {
|
||||
Anchor::Start => TextSummary::default(),
|
||||
Anchor::End => self.text_summary(),
|
||||
Anchor::Middle {
|
||||
insertion_id,
|
||||
offset,
|
||||
bias,
|
||||
version,
|
||||
} => {
|
||||
let seek_bias = match bias {
|
||||
AnchorBias::Left => SeekBias::Left,
|
||||
AnchorBias::Right => SeekBias::Right,
|
||||
};
|
||||
let mut cursor = self
|
||||
.fragments
|
||||
.filter::<_, usize>(|summary| !(*version >= summary.max_version), &());
|
||||
|
||||
let splits = self
|
||||
.insertion_splits
|
||||
.get(&insertion_id)
|
||||
.expect("split does not exist for insertion id");
|
||||
let mut splits_cursor = splits.cursor::<usize, ()>();
|
||||
splits_cursor.seek(offset, seek_bias, &());
|
||||
let split = splits_cursor.item().expect("split offset is out of range");
|
||||
let mut old_offset = 0;
|
||||
let mut new_offset = 0;
|
||||
while let Some(fragment) = cursor.item() {
|
||||
let bytes_since_last_fragment = *cursor.start() - new_offset;
|
||||
let comparison = offset.cmp(&(old_offset + bytes_since_last_fragment));
|
||||
if comparison == cmp::Ordering::Greater
|
||||
|| (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>();
|
||||
fragments_cursor.seek(&FragmentIdRef::new(&split.fragment_id), SeekBias::Left, &());
|
||||
let fragment = fragments_cursor.item().expect("fragment id does not exist");
|
||||
|
||||
let mut ix = *fragments_cursor.start();
|
||||
if fragment.visible {
|
||||
ix += offset - fragment.range_in_insertion.start;
|
||||
if fragment.was_visible(version, &self.undo_map) {
|
||||
let comparison = offset.cmp(&(old_offset + fragment.visible_len()));
|
||||
if comparison == cmp::Ordering::Greater
|
||||
|| (comparison == cmp::Ordering::Equal
|
||||
&& *bias == AnchorBias::Right)
|
||||
{
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
@ -1,17 +1,16 @@
|
||||
use super::Buffer;
|
||||
use super::{Buffer, ToOffset};
|
||||
use crate::time;
|
||||
use anyhow::Result;
|
||||
use std::cmp::Ordering;
|
||||
use std::ops::Range;
|
||||
use std::{cmp::Ordering, ops::Range};
|
||||
|
||||
#[derive(Clone, Eq, PartialEq, Debug, Hash)]
|
||||
pub enum Anchor {
|
||||
Start,
|
||||
End,
|
||||
Middle {
|
||||
insertion_id: time::Local,
|
||||
offset: usize,
|
||||
bias: AnchorBias,
|
||||
version: time::Global,
|
||||
},
|
||||
}
|
||||
|
||||
@ -55,18 +54,22 @@ impl Anchor {
|
||||
Anchor::Middle {
|
||||
offset: self_offset,
|
||||
bias: self_bias,
|
||||
..
|
||||
version: self_version,
|
||||
},
|
||||
Anchor::Middle {
|
||||
offset: other_offset,
|
||||
bias: other_bias,
|
||||
..
|
||||
version: other_version,
|
||||
},
|
||||
) => buffer
|
||||
.fragment_id_for_anchor(self)?
|
||||
.cmp(buffer.fragment_id_for_anchor(other)?)
|
||||
.then_with(|| self_offset.cmp(other_offset))
|
||||
.then_with(|| self_bias.cmp(other_bias)),
|
||||
) => {
|
||||
let offset_comparison = if self_version == other_version {
|
||||
self_offset.cmp(other_offset)
|
||||
} else {
|
||||
self.to_offset(buffer).cmp(&other.to_offset(buffer))
|
||||
};
|
||||
|
||||
offset_comparison.then_with(|| self_bias.cmp(other_bias))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -1027,11 +1027,34 @@ mod tests {
|
||||
|
||||
for _ in 0..operations {
|
||||
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) {
|
||||
0..=34 => {
|
||||
let buffer = buffer.read(cx);
|
||||
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 start = buffer.clip_offset(rng.gen_range(0..=end), Left);
|
||||
to_fold.push(start..end);
|
||||
|
@ -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]>);
|
||||
|
||||
impl Global {
|
||||
|
Loading…
Reference in New Issue
Block a user