mirror of
https://github.com/zed-industries/zed.git
synced 2024-11-08 07:35:01 +03:00
Introduce Content::anchor_range_multimap
This commit is contained in:
parent
5dc47c625e
commit
e8a2885721
@ -31,26 +31,26 @@ pub struct AnchorRangeMap<T> {
|
||||
pub struct AnchorRangeSet(pub(crate) AnchorRangeMap<()>);
|
||||
|
||||
pub struct AnchorRangeMultimap<T: Clone> {
|
||||
entries: SumTree<AnchorRangeMultimapEntry<T>>,
|
||||
pub(crate) entries: SumTree<AnchorRangeMultimapEntry<T>>,
|
||||
pub(crate) version: clock::Global,
|
||||
pub(crate) start_bias: Bias,
|
||||
pub(crate) end_bias: Bias,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct AnchorRangeMultimapEntry<T> {
|
||||
range: FullOffsetRange,
|
||||
value: T,
|
||||
pub(crate) struct AnchorRangeMultimapEntry<T> {
|
||||
pub(crate) range: FullOffsetRange,
|
||||
pub(crate) value: T,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
struct FullOffsetRange {
|
||||
start: usize,
|
||||
end: usize,
|
||||
pub(crate) struct FullOffsetRange {
|
||||
pub(crate) start: usize,
|
||||
pub(crate) end: usize,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
struct AnchorRangeMultimapSummary {
|
||||
pub(crate) struct AnchorRangeMultimapSummary {
|
||||
start: usize,
|
||||
end: usize,
|
||||
min_start: usize,
|
||||
@ -165,46 +165,61 @@ impl AnchorRangeSet {
|
||||
}
|
||||
|
||||
impl<T: Clone> AnchorRangeMultimap<T> {
|
||||
fn intersecting_point_ranges<'a, O: ToOffset>(
|
||||
fn intersecting_point_ranges<'a>(
|
||||
&'a self,
|
||||
range: Range<O>,
|
||||
content: impl Into<Content<'a>>,
|
||||
range: Range<Anchor>,
|
||||
content: &'a Content<'a>,
|
||||
inclusive: bool,
|
||||
) -> impl Iterator<Item = (usize, Range<Point>, &T)> + 'a {
|
||||
use super::ToPoint as _;
|
||||
|
||||
let content = content.into();
|
||||
let start = range.start.to_full_offset(&content, self.start_bias);
|
||||
let end = range.end.to_full_offset(&content, self.end_bias);
|
||||
let mut cursor = self.entries.filter::<_, usize>(
|
||||
move |summary: &AnchorRangeMultimapSummary| {
|
||||
if inclusive {
|
||||
start <= summary.max_end && end >= summary.min_start
|
||||
} else {
|
||||
start < summary.max_end && end > summary.min_start
|
||||
{
|
||||
let mut endpoint = Anchor {
|
||||
full_offset: 0,
|
||||
bias: Bias::Right,
|
||||
version: self.version.clone(),
|
||||
};
|
||||
move |summary: &AnchorRangeMultimapSummary| {
|
||||
endpoint.full_offset = summary.max_end;
|
||||
endpoint.bias = self.end_bias;
|
||||
let start_cmp = range.start.cmp(&endpoint, content).unwrap();
|
||||
|
||||
endpoint.full_offset = summary.min_start;
|
||||
endpoint.bias = self.start_bias;
|
||||
let end_cmp = range.end.cmp(&endpoint, content).unwrap();
|
||||
|
||||
if inclusive {
|
||||
start_cmp <= Ordering::Equal && end_cmp >= Ordering::Equal
|
||||
} else {
|
||||
start_cmp == Ordering::Less && end_cmp == Ordering::Greater
|
||||
}
|
||||
}
|
||||
},
|
||||
&(),
|
||||
);
|
||||
let mut anchor = Anchor {
|
||||
full_offset: 0,
|
||||
bias: Bias::Left,
|
||||
version: self.version.clone(),
|
||||
};
|
||||
std::iter::from_fn(move || {
|
||||
if let Some(item) = cursor.item() {
|
||||
let ix = *cursor.start();
|
||||
anchor.full_offset = item.range.start;
|
||||
anchor.bias = self.start_bias;
|
||||
let start = anchor.to_point(&content);
|
||||
anchor.full_offset = item.range.end;
|
||||
anchor.bias = self.end_bias;
|
||||
let end = anchor.to_point(&content);
|
||||
let value = &item.value;
|
||||
cursor.next(&());
|
||||
Some((ix, start..end, value))
|
||||
} else {
|
||||
None
|
||||
|
||||
std::iter::from_fn({
|
||||
let mut endpoint = Anchor {
|
||||
full_offset: 0,
|
||||
bias: Bias::Left,
|
||||
version: self.version.clone(),
|
||||
};
|
||||
move || {
|
||||
if let Some(item) = cursor.item() {
|
||||
let ix = *cursor.start();
|
||||
endpoint.full_offset = item.range.start;
|
||||
endpoint.bias = self.start_bias;
|
||||
let start = endpoint.to_point(content);
|
||||
endpoint.full_offset = item.range.end;
|
||||
endpoint.bias = self.end_bias;
|
||||
let end = endpoint.to_point(content);
|
||||
let value = &item.value;
|
||||
cursor.next(&());
|
||||
Some((ix, start..end, value))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ use rpc::proto;
|
||||
pub use selection::*;
|
||||
use std::{
|
||||
cmp,
|
||||
collections::{BTreeMap, BTreeSet},
|
||||
convert::{TryFrom, TryInto},
|
||||
iter::Iterator,
|
||||
ops::Range,
|
||||
@ -315,7 +316,7 @@ impl UndoMap {
|
||||
}
|
||||
}
|
||||
|
||||
struct Edits<'a, F: Fn(&FragmentSummary) -> bool> {
|
||||
struct Edits<'a, F: FnMut(&FragmentSummary) -> bool> {
|
||||
visible_text: &'a Rope,
|
||||
deleted_text: &'a Rope,
|
||||
cursor: Option<FilterCursor<'a, F, Fragment, FragmentTextSummary>>,
|
||||
@ -1836,6 +1837,56 @@ impl<'a> Content<'a> {
|
||||
AnchorRangeSet(self.anchor_range_map(entries.into_iter().map(|range| (range, ()))))
|
||||
}
|
||||
|
||||
pub fn anchor_range_multimap<T, E, O>(
|
||||
&self,
|
||||
start_bias: Bias,
|
||||
end_bias: Bias,
|
||||
entries: E,
|
||||
) -> AnchorRangeMultimap<T>
|
||||
where
|
||||
T: Clone,
|
||||
E: IntoIterator<Item = (Range<O>, T)>,
|
||||
O: ToOffset,
|
||||
{
|
||||
let mut items = Vec::new();
|
||||
let mut endpoints = BTreeMap::new();
|
||||
for (ix, (range, value)) in entries.into_iter().enumerate() {
|
||||
items.push(AnchorRangeMultimapEntry {
|
||||
range: FullOffsetRange { start: 0, end: 0 },
|
||||
value,
|
||||
});
|
||||
endpoints
|
||||
.entry((range.start.to_offset(self), start_bias))
|
||||
.or_insert(Vec::new())
|
||||
.push((ix, true));
|
||||
endpoints
|
||||
.entry((range.end.to_offset(self), end_bias))
|
||||
.or_insert(Vec::new())
|
||||
.push((ix, false));
|
||||
}
|
||||
|
||||
let mut cursor = self.fragments.cursor::<FragmentTextSummary>();
|
||||
for ((endpoint, bias), item_ixs) in endpoints {
|
||||
cursor.seek_forward(&endpoint, bias, &None);
|
||||
let full_offset = cursor.start().deleted + endpoint;
|
||||
for (item_ix, is_start) in item_ixs {
|
||||
if is_start {
|
||||
items[item_ix].range.start = full_offset;
|
||||
} else {
|
||||
items[item_ix].range.end = full_offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
items.sort_unstable_by_key(|i| (i.range.start, i.range.end));
|
||||
|
||||
AnchorRangeMultimap {
|
||||
entries: SumTree::from_iter(items, &()),
|
||||
version: self.version.clone(),
|
||||
start_bias,
|
||||
end_bias,
|
||||
}
|
||||
}
|
||||
|
||||
fn full_offset_for_anchor(&self, anchor: &Anchor) -> usize {
|
||||
let cx = Some(anchor.version.clone());
|
||||
let mut cursor = self
|
||||
@ -1917,7 +1968,7 @@ impl<'a> RopeBuilder<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, F: Fn(&FragmentSummary) -> bool> Iterator for Edits<'a, F> {
|
||||
impl<'a, F: FnMut(&FragmentSummary) -> bool> Iterator for Edits<'a, F> {
|
||||
type Item = Edit;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
|
@ -720,7 +720,7 @@ fn intersecting_folds<'a, T>(
|
||||
folds: &'a SumTree<Fold>,
|
||||
range: Range<T>,
|
||||
inclusive: bool,
|
||||
) -> FilterCursor<'a, impl 'a + Fn(&FoldSummary) -> bool, Fold, usize>
|
||||
) -> FilterCursor<'a, impl 'a + FnMut(&FoldSummary) -> bool, Fold, usize>
|
||||
where
|
||||
T: ToOffset,
|
||||
{
|
||||
|
@ -1190,7 +1190,6 @@ impl LocalWorktree {
|
||||
diagnostics: lsp::PublishDiagnosticsParams,
|
||||
cx: &mut ModelContext<Worktree>,
|
||||
) {
|
||||
//
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -184,9 +184,9 @@ where
|
||||
self.next_internal(|_| true, cx)
|
||||
}
|
||||
|
||||
fn next_internal<F>(&mut self, filter_node: F, cx: &<T::Summary as Summary>::Context)
|
||||
fn next_internal<F>(&mut self, mut filter_node: F, cx: &<T::Summary as Summary>::Context)
|
||||
where
|
||||
F: Fn(&T::Summary) -> bool,
|
||||
F: FnMut(&T::Summary) -> bool,
|
||||
{
|
||||
let mut descend = false;
|
||||
|
||||
@ -509,24 +509,24 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub struct FilterCursor<'a, F: Fn(&T::Summary) -> bool, T: Item, D> {
|
||||
pub struct FilterCursor<'a, F: FnMut(&T::Summary) -> bool, T: Item, D> {
|
||||
cursor: Cursor<'a, T, D>,
|
||||
filter_node: F,
|
||||
}
|
||||
|
||||
impl<'a, F, T, D> FilterCursor<'a, F, T, D>
|
||||
where
|
||||
F: Fn(&T::Summary) -> bool,
|
||||
F: FnMut(&T::Summary) -> bool,
|
||||
T: Item,
|
||||
D: Dimension<'a, T::Summary>,
|
||||
{
|
||||
pub fn new(
|
||||
tree: &'a SumTree<T>,
|
||||
filter_node: F,
|
||||
mut filter_node: F,
|
||||
cx: &<T::Summary as Summary>::Context,
|
||||
) -> Self {
|
||||
let mut cursor = tree.cursor::<D>();
|
||||
cursor.next_internal(&filter_node, cx);
|
||||
cursor.next_internal(&mut filter_node, cx);
|
||||
Self {
|
||||
cursor,
|
||||
filter_node,
|
||||
@ -542,7 +542,7 @@ where
|
||||
}
|
||||
|
||||
pub fn next(&mut self, cx: &<T::Summary as Summary>::Context) {
|
||||
self.cursor.next_internal(&self.filter_node, cx);
|
||||
self.cursor.next_internal(&mut self.filter_node, cx);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -163,7 +163,7 @@ impl<T: Item> SumTree<T> {
|
||||
cx: &<T::Summary as Summary>::Context,
|
||||
) -> FilterCursor<F, T, U>
|
||||
where
|
||||
F: Fn(&T::Summary) -> bool,
|
||||
F: FnMut(&T::Summary) -> bool,
|
||||
U: Dimension<'a, T::Summary>,
|
||||
{
|
||||
FilterCursor::new(self, filter_node, cx)
|
||||
|
Loading…
Reference in New Issue
Block a user