Fix excerpt jumps using selections, not the match data (#20491)
Fixes https://github.com/zed-industries/zed/pull/20469#issuecomment-2466805325 Release Notes: - N/A --------- Co-authored-by: Bennet <bennet@zed.dev>
This commit is contained in:
parent
1460249a70
commit
f4024cc602
2 changed files with 152 additions and 70 deletions
|
@ -1748,6 +1748,15 @@ pub(crate) struct FocusedBlock {
|
|||
focus_handle: WeakFocusHandle,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct JumpData {
|
||||
excerpt_id: ExcerptId,
|
||||
position: Point,
|
||||
anchor: text::Anchor,
|
||||
path: Option<project::ProjectPath>,
|
||||
line_offset_from_top: u32,
|
||||
}
|
||||
|
||||
impl Editor {
|
||||
pub fn single_line(cx: &mut ViewContext<Self>) -> Self {
|
||||
let buffer = cx.new_model(|cx| Buffer::local("", cx));
|
||||
|
@ -12584,47 +12593,83 @@ impl Editor {
|
|||
}
|
||||
|
||||
pub fn open_excerpts_in_split(&mut self, _: &OpenExcerptsSplit, cx: &mut ViewContext<Self>) {
|
||||
self.open_excerpts_common(true, cx)
|
||||
self.open_excerpts_common(None, true, cx)
|
||||
}
|
||||
|
||||
pub fn open_excerpts(&mut self, _: &OpenExcerpts, cx: &mut ViewContext<Self>) {
|
||||
self.open_excerpts_common(false, cx)
|
||||
self.open_excerpts_common(None, false, cx)
|
||||
}
|
||||
|
||||
fn open_excerpts_common(&mut self, split: bool, cx: &mut ViewContext<Self>) {
|
||||
let selections = self.selections.all::<usize>(cx);
|
||||
let buffer = self.buffer.read(cx);
|
||||
if buffer.is_singleton() {
|
||||
cx.propagate();
|
||||
return;
|
||||
}
|
||||
|
||||
fn open_excerpts_common(
|
||||
&mut self,
|
||||
jump_data: Option<JumpData>,
|
||||
split: bool,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) {
|
||||
let Some(workspace) = self.workspace() else {
|
||||
cx.propagate();
|
||||
return;
|
||||
};
|
||||
|
||||
let mut new_selections_by_buffer = HashMap::default();
|
||||
for selection in selections {
|
||||
for (mut buffer_handle, mut range, _) in
|
||||
buffer.range_to_buffer_ranges(selection.range(), cx)
|
||||
{
|
||||
// When editing branch buffers, jump to the corresponding location
|
||||
// in their base buffer.
|
||||
let buffer = buffer_handle.read(cx);
|
||||
if let Some(base_buffer) = buffer.diff_base_buffer() {
|
||||
range = buffer.range_to_version(range, &base_buffer.read(cx).version());
|
||||
buffer_handle = base_buffer;
|
||||
}
|
||||
if self.buffer.read(cx).is_singleton() {
|
||||
cx.propagate();
|
||||
return;
|
||||
}
|
||||
|
||||
if selection.reversed {
|
||||
mem::swap(&mut range.start, &mut range.end);
|
||||
let mut new_selections_by_buffer = HashMap::default();
|
||||
match &jump_data {
|
||||
Some(jump_data) => {
|
||||
let multi_buffer_snapshot = self.buffer.read(cx).snapshot(cx);
|
||||
if let Some(buffer) = multi_buffer_snapshot
|
||||
.buffer_id_for_excerpt(jump_data.excerpt_id)
|
||||
.and_then(|buffer_id| self.buffer.read(cx).buffer(buffer_id))
|
||||
{
|
||||
let buffer_snapshot = buffer.read(cx).snapshot();
|
||||
let jump_to_point = if buffer_snapshot.can_resolve(&jump_data.anchor) {
|
||||
language::ToPoint::to_point(&jump_data.anchor, &buffer_snapshot)
|
||||
} else {
|
||||
buffer_snapshot.clip_point(jump_data.position, Bias::Left)
|
||||
};
|
||||
let jump_to_offset = buffer_snapshot.point_to_offset(jump_to_point);
|
||||
new_selections_by_buffer.insert(
|
||||
buffer,
|
||||
(
|
||||
vec![jump_to_offset..jump_to_offset],
|
||||
Some(jump_data.line_offset_from_top),
|
||||
),
|
||||
);
|
||||
}
|
||||
new_selections_by_buffer
|
||||
.entry(buffer_handle)
|
||||
.or_insert(Vec::new())
|
||||
.push(range)
|
||||
}
|
||||
None => {
|
||||
let selections = self.selections.all::<usize>(cx);
|
||||
let buffer = self.buffer.read(cx);
|
||||
for selection in selections {
|
||||
for (mut buffer_handle, mut range, _) in
|
||||
buffer.range_to_buffer_ranges(selection.range(), cx)
|
||||
{
|
||||
// When editing branch buffers, jump to the corresponding location
|
||||
// in their base buffer.
|
||||
let buffer = buffer_handle.read(cx);
|
||||
if let Some(base_buffer) = buffer.diff_base_buffer() {
|
||||
range = buffer.range_to_version(range, &base_buffer.read(cx).version());
|
||||
buffer_handle = base_buffer;
|
||||
}
|
||||
|
||||
if selection.reversed {
|
||||
mem::swap(&mut range.start, &mut range.end);
|
||||
}
|
||||
new_selections_by_buffer
|
||||
.entry(buffer_handle)
|
||||
.or_insert((Vec::new(), None))
|
||||
.0
|
||||
.push(range)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if new_selections_by_buffer.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
// We defer the pane interaction because we ourselves are a workspace item
|
||||
|
@ -12638,13 +12683,19 @@ impl Editor {
|
|||
workspace.active_pane().clone()
|
||||
};
|
||||
|
||||
for (buffer, ranges) in new_selections_by_buffer {
|
||||
for (buffer, (ranges, scroll_offset)) in new_selections_by_buffer {
|
||||
let editor =
|
||||
workspace.open_project_item::<Self>(pane.clone(), buffer, true, true, cx);
|
||||
editor.update(cx, |editor, cx| {
|
||||
editor.change_selections(Some(Autoscroll::newest()), cx, |s| {
|
||||
let autoscroll = match scroll_offset {
|
||||
Some(scroll_offset) => Autoscroll::top_relative(scroll_offset as usize),
|
||||
None => Autoscroll::newest(),
|
||||
};
|
||||
let nav_history = editor.nav_history.take();
|
||||
editor.change_selections(Some(autoscroll), cx, |s| {
|
||||
s.select_ranges(ranges);
|
||||
});
|
||||
editor.nav_history = nav_history;
|
||||
});
|
||||
}
|
||||
})
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue