diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index eab88c24d0..d5035299fa 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -426,6 +426,11 @@ struct ClipboardSelection { is_entire_line: bool, } +pub struct NavigationData { + anchor: Anchor, + offset: usize, +} + impl Editor { pub fn single_line(build_settings: BuildSettings, cx: &mut ViewContext) -> Self { let buffer = cx.add_model(|cx| Buffer::new(0, String::new(), cx)); @@ -2438,9 +2443,12 @@ impl Editor { fn push_to_navigation_history(&self, cx: &mut ViewContext) { if let Some(navigation) = &self.navigation { + let buffer = self.buffer.read(cx).read(cx); if let Some(last_selection) = self.selections.iter().max_by_key(|s| s.id) { - let cursor = last_selection.head(); - navigation.push(Some(cursor), cx); + let anchor = last_selection.head(); + let offset = anchor.to_offset(&buffer); + drop(buffer); + navigation.push(Some(NavigationData { anchor, offset }), cx); } } } diff --git a/crates/editor/src/items.rs b/crates/editor/src/items.rs index 5ff90201d5..13587495bc 100644 --- a/crates/editor/src/items.rs +++ b/crates/editor/src/items.rs @@ -1,10 +1,10 @@ -use crate::{Anchor, Autoscroll, Editor, Event, MultiBuffer, ToOffset, ToPoint as _}; +use crate::{Autoscroll, Editor, Event, MultiBuffer, NavigationData, ToOffset, ToPoint as _}; use anyhow::Result; use gpui::{ elements::*, AppContext, Entity, ModelContext, ModelHandle, MutableAppContext, RenderContext, Subscription, Task, View, ViewContext, ViewHandle, WeakModelHandle, }; -use language::{Buffer, Diagnostic, File as _}; +use language::{Bias, Buffer, Diagnostic, File as _}; use postage::watch; use project::{File, ProjectPath, Worktree}; use std::fmt::Write; @@ -106,8 +106,15 @@ impl ItemView for Editor { } fn navigate(&mut self, data: Box, cx: &mut ViewContext) { - if let Some(anchor) = data.downcast_ref::() { - let offset = anchor.to_offset(&self.buffer.read(cx).read(cx)); + if let Some(data) = data.downcast_ref::() { + let buffer = self.buffer.read(cx).read(cx); + let offset = if buffer.can_resolve(&data.anchor) { + data.anchor.to_offset(&buffer) + } else { + buffer.clip_offset(data.offset, Bias::Left) + }; + + drop(buffer); self.select_ranges([offset..offset], Some(Autoscroll::Fit), cx); } } diff --git a/crates/editor/src/multi_buffer.rs b/crates/editor/src/multi_buffer.rs index 30020a0d55..7ae7b56867 100644 --- a/crates/editor/src/multi_buffer.rs +++ b/crates/editor/src/multi_buffer.rs @@ -1545,6 +1545,18 @@ impl MultiBufferSnapshot { panic!("excerpt not found"); } + pub fn can_resolve(&self, anchor: &Anchor) -> bool { + if anchor.excerpt_id == ExcerptId::min() || anchor.excerpt_id == ExcerptId::max() { + true + } else if let Some((buffer_id, buffer_snapshot)) = + self.buffer_snapshot_for_excerpt(&anchor.excerpt_id) + { + anchor.buffer_id == buffer_id && buffer_snapshot.can_resolve(&anchor.text_anchor) + } else { + false + } + } + pub fn range_contains_excerpt_boundary(&self, range: Range) -> bool { let start = range.start.to_offset(self); let end = range.end.to_offset(self); diff --git a/crates/text/src/text.rs b/crates/text/src/text.rs index 895e6ad471..a762b1ca39 100644 --- a/crates/text/src/text.rs +++ b/crates/text/src/text.rs @@ -1131,12 +1131,6 @@ impl Buffer { } } - pub fn can_resolve(&self, anchor: &Anchor) -> bool { - *anchor == Anchor::min() - || *anchor == Anchor::max() - || self.version.observed(anchor.timestamp) - } - pub fn peek_undo_stack(&self) -> Option<&Transaction> { self.history.undo_stack.last() } @@ -1648,6 +1642,12 @@ impl BufferSnapshot { } } + pub fn can_resolve(&self, anchor: &Anchor) -> bool { + *anchor == Anchor::min() + || *anchor == Anchor::max() + || self.version.observed(anchor.timestamp) + } + pub fn clip_offset(&self, offset: usize, bias: Bias) -> usize { self.visible_text.clip_offset(offset, bias) }