Fix error in follower when leader creates pending selections
Co-Authored-By: Nathan Sobo <nathan@zed.dev>
This commit is contained in:
parent
10f176073d
commit
0b3a63b843
2 changed files with 75 additions and 2 deletions
|
@ -4903,6 +4903,55 @@ impl Editor {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_selections_from_remote(
|
||||||
|
&mut self,
|
||||||
|
mut selections: Vec<Selection<Anchor>>,
|
||||||
|
cx: &mut ViewContext<Self>,
|
||||||
|
) {
|
||||||
|
let buffer = self.buffer.read(cx);
|
||||||
|
let buffer = buffer.read(cx);
|
||||||
|
selections.sort_by(|a, b| {
|
||||||
|
a.start
|
||||||
|
.cmp(&b.start, &*buffer)
|
||||||
|
.unwrap()
|
||||||
|
.then_with(|| b.end.cmp(&a.end, &*buffer).unwrap())
|
||||||
|
});
|
||||||
|
|
||||||
|
// Merge overlapping selections
|
||||||
|
let mut i = 1;
|
||||||
|
while i < selections.len() {
|
||||||
|
if selections[i - 1]
|
||||||
|
.end
|
||||||
|
.cmp(&selections[i].start, &*buffer)
|
||||||
|
.unwrap()
|
||||||
|
.is_ge()
|
||||||
|
{
|
||||||
|
let removed = selections.remove(i);
|
||||||
|
if removed
|
||||||
|
.start
|
||||||
|
.cmp(&selections[i - 1].start, &*buffer)
|
||||||
|
.unwrap()
|
||||||
|
.is_lt()
|
||||||
|
{
|
||||||
|
selections[i - 1].start = removed.start;
|
||||||
|
}
|
||||||
|
if removed
|
||||||
|
.end
|
||||||
|
.cmp(&selections[i - 1].end, &*buffer)
|
||||||
|
.unwrap()
|
||||||
|
.is_gt()
|
||||||
|
{
|
||||||
|
selections[i - 1].end = removed.end;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
drop(buffer);
|
||||||
|
self.set_selections(selections.into(), None, false, cx);
|
||||||
|
}
|
||||||
|
|
||||||
/// Compute new ranges for any selections that were located in excerpts that have
|
/// Compute new ranges for any selections that were located in excerpts that have
|
||||||
/// since been removed.
|
/// since been removed.
|
||||||
///
|
///
|
||||||
|
@ -9109,6 +9158,29 @@ mod tests {
|
||||||
assert!(follower.autoscroll_request.is_some());
|
assert!(follower.autoscroll_request.is_some());
|
||||||
});
|
});
|
||||||
assert_eq!(follower.read(cx).selected_ranges(cx), vec![0..0]);
|
assert_eq!(follower.read(cx).selected_ranges(cx), vec![0..0]);
|
||||||
|
|
||||||
|
// Creating a pending selection that precedes another selection
|
||||||
|
leader.update(cx, |leader, cx| {
|
||||||
|
leader.select_ranges([1..1], None, cx);
|
||||||
|
leader.begin_selection(DisplayPoint::new(0, 0), true, 1, cx);
|
||||||
|
});
|
||||||
|
follower.update(cx, |follower, cx| {
|
||||||
|
follower
|
||||||
|
.apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
|
||||||
|
.unwrap();
|
||||||
|
});
|
||||||
|
assert_eq!(follower.read(cx).selected_ranges(cx), vec![0..0, 1..1]);
|
||||||
|
|
||||||
|
// Extend the pending selection so that it surrounds another selection
|
||||||
|
leader.update(cx, |leader, cx| {
|
||||||
|
leader.extend_selection(DisplayPoint::new(0, 2), 1, cx);
|
||||||
|
});
|
||||||
|
follower.update(cx, |follower, cx| {
|
||||||
|
follower
|
||||||
|
.apply_update_proto(pending_update.borrow_mut().take().unwrap(), cx)
|
||||||
|
.unwrap();
|
||||||
|
});
|
||||||
|
assert_eq!(follower.read(cx).selected_ranges(cx), vec![0..2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -65,7 +65,7 @@ impl FollowableItem for Editor {
|
||||||
})
|
})
|
||||||
.collect::<Result<Vec<_>>>()?;
|
.collect::<Result<Vec<_>>>()?;
|
||||||
if !selections.is_empty() {
|
if !selections.is_empty() {
|
||||||
editor.set_selections(selections.into(), None, false, cx);
|
editor.set_selections_from_remote(selections.into(), cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(anchor) = state.scroll_top_anchor {
|
if let Some(anchor) = state.scroll_top_anchor {
|
||||||
|
@ -173,8 +173,9 @@ impl FollowableItem for Editor {
|
||||||
deserialize_selection(&excerpt_id, buffer_id, selection)
|
deserialize_selection(&excerpt_id, buffer_id, selection)
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
if !selections.is_empty() {
|
if !selections.is_empty() {
|
||||||
self.set_selections(selections.into(), None, false, cx);
|
self.set_selections_from_remote(selections, cx);
|
||||||
self.request_autoscroll_remotely(Autoscroll::Newest, cx);
|
self.request_autoscroll_remotely(Autoscroll::Newest, cx);
|
||||||
} else {
|
} else {
|
||||||
if let Some(anchor) = message.scroll_top_anchor {
|
if let Some(anchor) = message.scroll_top_anchor {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue