Improve range-based selection queries to only resolve the requested selections
This commit is contained in:
parent
09a53a0c64
commit
d249618ee6
4 changed files with 59 additions and 39 deletions
|
@ -210,14 +210,14 @@ impl<T> AnchorRangeMap<T> {
|
||||||
.zip(self.entries.iter().map(|e| &e.1))
|
.zip(self.entries.iter().map(|e| &e.1))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn intersecting_ranges<'a, D, T>(
|
pub fn intersecting_ranges<'a, D, I>(
|
||||||
&'a self,
|
&'a self,
|
||||||
range: Range<(T, Bias)>,
|
range: Range<(I, Bias)>,
|
||||||
content: impl Into<Content<'a>> + 'a,
|
content: impl Into<Content<'a>> + 'a,
|
||||||
) -> impl Iterator<Item = (Range<D>, &'a T)> + 'a
|
) -> impl Iterator<Item = (Range<D>, &'a T)> + 'a
|
||||||
where
|
where
|
||||||
D: 'a + TextDimension<'a>,
|
D: 'a + TextDimension<'a>,
|
||||||
T: ToOffset,
|
I: ToOffset,
|
||||||
{
|
{
|
||||||
let content = content.into();
|
let content = content.into();
|
||||||
let range = content.anchor_at(range.start.0, range.start.1)
|
let range = content.anchor_at(range.start.0, range.start.1)
|
||||||
|
@ -229,10 +229,20 @@ impl<T> AnchorRangeMap<T> {
|
||||||
version: self.version.clone(),
|
version: self.version.clone(),
|
||||||
};
|
};
|
||||||
let start_ix = self.entries.binary_search_by(|probe| {
|
let start_ix = self.entries.binary_search_by(|probe| {
|
||||||
probe_anchor.full_offset = probe.0.start;
|
probe_anchor.full_offset = probe.0.end;
|
||||||
probe_anchor.cmp(&range.start, &content).unwrap()
|
probe_anchor.cmp(&range.start, &content).unwrap()
|
||||||
});
|
});
|
||||||
std::iter::empty()
|
|
||||||
|
match start_ix {
|
||||||
|
Ok(start_ix) | Err(start_ix) => content
|
||||||
|
.summaries_for_anchor_ranges(
|
||||||
|
self.version.clone(),
|
||||||
|
self.start_bias,
|
||||||
|
self.end_bias,
|
||||||
|
self.entries[start_ix..].iter().map(|e| &e.0),
|
||||||
|
)
|
||||||
|
.zip(self.entries.iter().map(|e| &e.1)),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn full_offset_ranges(&self) -> impl Iterator<Item = &(Range<FullOffset>, T)> {
|
pub fn full_offset_ranges(&self) -> impl Iterator<Item = &(Range<FullOffset>, T)> {
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
use sum_tree::Bias;
|
||||||
|
|
||||||
use crate::rope::TextDimension;
|
use crate::rope::TextDimension;
|
||||||
|
|
||||||
use super::{AnchorRangeMap, Buffer, Content, Point, ToOffset, ToPoint};
|
use super::{AnchorRangeMap, Buffer, Content, Point, ToOffset, ToPoint};
|
||||||
|
@ -117,6 +119,27 @@ impl SelectionSet {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn intersecting_selections<'a, D, I, C>(
|
||||||
|
&'a self,
|
||||||
|
range: Range<(I, Bias)>,
|
||||||
|
content: C,
|
||||||
|
) -> impl 'a + Iterator<Item = Selection<D>>
|
||||||
|
where
|
||||||
|
D: 'a + TextDimension<'a>,
|
||||||
|
I: 'a + ToOffset,
|
||||||
|
C: 'a + Into<Content<'a>>,
|
||||||
|
{
|
||||||
|
self.selections
|
||||||
|
.intersecting_ranges(range, content)
|
||||||
|
.map(|(range, state)| Selection {
|
||||||
|
id: state.id,
|
||||||
|
start: range.start,
|
||||||
|
end: range.end,
|
||||||
|
reversed: state.reversed,
|
||||||
|
goal: state.goal,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
pub fn oldest_selection<'a, D, C>(&'a self, content: C) -> Option<Selection<D>>
|
pub fn oldest_selection<'a, D, C>(&'a self, content: C) -> Option<Selection<D>>
|
||||||
where
|
where
|
||||||
D: 'a + TextDimension<'a>,
|
D: 'a + TextDimension<'a>,
|
||||||
|
|
|
@ -748,11 +748,13 @@ impl Element for EditorElement {
|
||||||
self.update_view(cx.app, |view, cx| {
|
self.update_view(cx.app, |view, cx| {
|
||||||
highlighted_row = view.highlighted_row();
|
highlighted_row = view.highlighted_row();
|
||||||
for selection_set_id in view.active_selection_sets(cx).collect::<Vec<_>>() {
|
for selection_set_id in view.active_selection_sets(cx).collect::<Vec<_>>() {
|
||||||
let replica_selections = view.selections_in_range(
|
let replica_selections = view
|
||||||
selection_set_id,
|
.intersecting_selections(
|
||||||
DisplayPoint::new(start_row, 0)..DisplayPoint::new(end_row, 0),
|
selection_set_id,
|
||||||
cx,
|
DisplayPoint::new(start_row, 0)..DisplayPoint::new(end_row, 0),
|
||||||
);
|
cx,
|
||||||
|
)
|
||||||
|
.collect::<Vec<_>>();
|
||||||
for selection in &replica_selections {
|
for selection in &replica_selections {
|
||||||
if selection_set_id == view.selection_set_id {
|
if selection_set_id == view.selection_set_id {
|
||||||
let is_empty = selection.start == selection.end;
|
let is_empty = selection.start == selection.end;
|
||||||
|
|
|
@ -3017,23 +3017,15 @@ impl Editor {
|
||||||
.map(|(set_id, _)| *set_id)
|
.map(|(set_id, _)| *set_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn selections_in_range<'a>(
|
pub fn intersecting_selections<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
set_id: SelectionSetId,
|
set_id: SelectionSetId,
|
||||||
range: Range<DisplayPoint>,
|
range: Range<DisplayPoint>,
|
||||||
cx: &'a mut MutableAppContext,
|
cx: &'a mut MutableAppContext,
|
||||||
) -> Vec<Selection<DisplayPoint>> {
|
) -> impl 'a + Iterator<Item = Selection<DisplayPoint>> {
|
||||||
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
|
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
|
||||||
let buffer = self.buffer.read(cx);
|
let buffer = self.buffer.read(cx);
|
||||||
let selections = self
|
|
||||||
.buffer
|
|
||||||
.read(cx)
|
|
||||||
.selection_set(set_id)
|
|
||||||
.unwrap()
|
|
||||||
.selections::<Point, _>(buffer)
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
let start = range.start.to_point(&display_map);
|
|
||||||
let start_index = self.selection_insertion_index(&selections, start);
|
|
||||||
let pending_selection = if set_id == self.selection_set_id {
|
let pending_selection = if set_id == self.selection_set_id {
|
||||||
self.pending_selection.as_ref().and_then(|pending| {
|
self.pending_selection.as_ref().and_then(|pending| {
|
||||||
let selection_start = pending.selection.start.to_display_point(&display_map);
|
let selection_start = pending.selection.start.to_display_point(&display_map);
|
||||||
|
@ -3053,9 +3045,17 @@ impl Editor {
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let range = (range.start.to_offset(&display_map, Bias::Left), Bias::Left)
|
||||||
|
..(range.end.to_offset(&display_map, Bias::Left), Bias::Right);
|
||||||
|
let selections = self
|
||||||
|
.buffer
|
||||||
|
.read(cx)
|
||||||
|
.selection_set(set_id)
|
||||||
|
.unwrap()
|
||||||
|
.intersecting_selections::<Point, _, _>(range, buffer);
|
||||||
|
|
||||||
selections
|
selections
|
||||||
.into_iter()
|
|
||||||
.skip(start_index)
|
|
||||||
.map(move |s| Selection {
|
.map(move |s| Selection {
|
||||||
id: s.id,
|
id: s.id,
|
||||||
start: s.start.to_display_point(&display_map),
|
start: s.start.to_display_point(&display_map),
|
||||||
|
@ -3063,22 +3063,7 @@ impl Editor {
|
||||||
reversed: s.reversed,
|
reversed: s.reversed,
|
||||||
goal: s.goal,
|
goal: s.goal,
|
||||||
})
|
})
|
||||||
.take_while(move |r| r.start <= range.end || r.end <= range.end)
|
|
||||||
.chain(pending_selection)
|
.chain(pending_selection)
|
||||||
.collect()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn selection_insertion_index(&self, selections: &[Selection<Point>], start: Point) -> usize {
|
|
||||||
match selections.binary_search_by_key(&start, |probe| probe.start) {
|
|
||||||
Ok(index) => index,
|
|
||||||
Err(index) => {
|
|
||||||
if index > 0 && selections[index - 1].end > start {
|
|
||||||
index - 1
|
|
||||||
} else {
|
|
||||||
index
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn selections<'a, D>(&self, cx: &'a AppContext) -> impl 'a + Iterator<Item = Selection<D>>
|
pub fn selections<'a, D>(&self, cx: &'a AppContext) -> impl 'a + Iterator<Item = Selection<D>>
|
||||||
|
@ -5694,7 +5679,7 @@ mod tests {
|
||||||
|
|
||||||
impl Editor {
|
impl Editor {
|
||||||
fn selection_ranges(&self, cx: &mut MutableAppContext) -> Vec<Range<DisplayPoint>> {
|
fn selection_ranges(&self, cx: &mut MutableAppContext) -> Vec<Range<DisplayPoint>> {
|
||||||
self.selections_in_range(
|
self.intersecting_selections(
|
||||||
self.selection_set_id,
|
self.selection_set_id,
|
||||||
DisplayPoint::zero()..self.max_point(cx),
|
DisplayPoint::zero()..self.max_point(cx),
|
||||||
cx,
|
cx,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue