Detailed changes
@@ -67,6 +67,7 @@
"ctrl-o": "pane::GoBack",
"ctrl-i": "pane::GoForward",
"ctrl-]": "editor::GoToDefinition",
+ "ctrl-t": "pane::GoToOlderTag",
"escape": "vim::SwitchToNormalMode",
"ctrl-[": "vim::SwitchToNormalMode",
"v": "vim::ToggleVisual",
@@ -25,6 +25,7 @@ use std::{
any::{Any, TypeId},
collections::hash_map::Entry,
ops::Range,
+ rc::Rc,
sync::Arc,
};
use ui::{CommonAnimationExt, IconButtonShape, KeyBinding, Tooltip, prelude::*, vertical_divider};
@@ -516,12 +517,7 @@ impl Item for AgentDiffPane {
.update(cx, |editor, cx| editor.deactivated(window, cx));
}
- fn navigate(
- &mut self,
- data: Box<dyn Any>,
- window: &mut Window,
- cx: &mut Context<Self>,
- ) -> bool {
+ fn navigate(&mut self, data: Rc<dyn Any>, window: &mut Window, cx: &mut Context<Self>) -> bool {
self.editor
.update(cx, |editor, cx| editor.navigate(data, window, cx))
}
@@ -2530,7 +2530,7 @@ impl Item for TextThreadEditor {
fn navigate(
&mut self,
- data: Box<dyn std::any::Any>,
+ data: Rc<dyn std::any::Any>,
window: &mut Window,
cx: &mut Context<Self>,
) -> bool {
@@ -18,6 +18,7 @@ use project::Project;
use rpc::proto::ChannelVisibility;
use std::{
any::{Any, TypeId},
+ rc::Rc,
sync::Arc,
};
use ui::prelude::*;
@@ -515,12 +516,7 @@ impl Item for ChannelView {
})))
}
- fn navigate(
- &mut self,
- data: Box<dyn Any>,
- window: &mut Window,
- cx: &mut Context<Self>,
- ) -> bool {
+ fn navigate(&mut self, data: Rc<dyn Any>, window: &mut Window, cx: &mut Context<Self>) -> bool {
self.editor
.update(cx, |editor, cx| editor.navigate(data, window, cx))
}
@@ -1,4 +1,7 @@
-use std::any::{Any, TypeId};
+use std::{
+ any::{Any, TypeId},
+ rc::Rc,
+};
use collections::HashMap;
use dap::StackFrameId;
@@ -331,12 +334,7 @@ impl Item for StackTraceView {
.update(cx, |editor, cx| editor.deactivated(window, cx));
}
- fn navigate(
- &mut self,
- data: Box<dyn Any>,
- window: &mut Window,
- cx: &mut Context<Self>,
- ) -> bool {
+ fn navigate(&mut self, data: Rc<dyn Any>, window: &mut Window, cx: &mut Context<Self>) -> bool {
self.editor
.update(cx, |editor, cx| editor.navigate(data, window, cx))
}
@@ -24,6 +24,7 @@ use settings::Settings;
use std::{
any::{Any, TypeId},
cmp::Ordering,
+ rc::Rc,
sync::Arc,
};
use text::{Anchor, BufferSnapshot, OffsetRangeExt};
@@ -734,12 +735,7 @@ impl Item for BufferDiagnosticsEditor {
self.multibuffer.read(cx).is_dirty(cx)
}
- fn navigate(
- &mut self,
- data: Box<dyn Any>,
- window: &mut Window,
- cx: &mut Context<Self>,
- ) -> bool {
+ fn navigate(&mut self, data: Rc<dyn Any>, window: &mut Window, cx: &mut Context<Self>) -> bool {
self.editor
.update(cx, |editor, cx| editor.navigate(data, window, cx))
}
@@ -35,6 +35,7 @@ use std::{
any::{Any, TypeId},
cmp,
ops::{Range, RangeInclusive},
+ rc::Rc,
sync::Arc,
time::Duration,
};
@@ -728,12 +729,7 @@ impl Item for ProjectDiagnosticsEditor {
.update(cx, |editor, cx| editor.deactivated(window, cx));
}
- fn navigate(
- &mut self,
- data: Box<dyn Any>,
- window: &mut Window,
- cx: &mut Context<Self>,
- ) -> bool {
+ fn navigate(&mut self, data: Rc<dyn Any>, window: &mut Window, cx: &mut Context<Self>) -> bool {
self.editor
.update(cx, |editor, cx| editor.navigate(data, window, cx))
}
@@ -14038,6 +14038,27 @@ impl Editor {
);
}
+ fn finish_tag_jump(&mut self, point: Point, cx: &mut Context<Self>) {
+ let Some(nav_history) = self.nav_history.as_mut() else {
+ return;
+ };
+ let snapshot = self.buffer.read(cx).snapshot(cx);
+ let cursor_anchor = snapshot.anchor_after(point);
+ let cursor_position = cursor_anchor.to_point(&snapshot);
+ let scroll_state = self.scroll_manager.anchor();
+ let scroll_top_row = scroll_state.top_row(&snapshot);
+ dbg!("finish tag jump", cursor_position);
+ nav_history.finish_tag_jump(
+ Some(NavigationData {
+ cursor_anchor,
+ cursor_position,
+ scroll_anchor: scroll_state,
+ scroll_top_row,
+ }),
+ cx,
+ );
+ }
+
fn push_to_nav_history(
&mut self,
cursor_anchor: Anchor,
@@ -16437,18 +16458,37 @@ impl Editor {
let Some(provider) = self.semantics_provider.clone() else {
return Task::ready(Ok(Navigated::No));
};
- let head = self
+ let cursor = self
.selections
.newest::<usize>(&self.display_snapshot(cx))
.head();
- let buffer = self.buffer.read(cx);
- let Some((buffer, head)) = buffer.text_anchor_for_position(head, cx) else {
+ let multi_buffer = self.buffer.read(cx);
+ let Some((buffer, head)) = multi_buffer.text_anchor_for_position(cursor, cx) else {
return Task::ready(Ok(Navigated::No));
};
let Some(definitions) = provider.definitions(&buffer, head, kind, cx) else {
return Task::ready(Ok(Navigated::No));
};
+ if let Some(nav_history) = self.nav_history.as_mut() {
+ let snapshot = self.buffer.read(cx).snapshot(cx);
+ let cursor_anchor = snapshot.anchor_after(cursor);
+ let cursor_position = snapshot.offset_to_point(cursor);
+ let scroll_anchor = self.scroll_manager.anchor();
+ let scroll_top_row = scroll_anchor.top_row(&snapshot);
+
+ dbg!("start tag jump", cursor_position);
+ nav_history.start_tag_jump(
+ Some(NavigationData {
+ cursor_anchor,
+ cursor_position,
+ scroll_anchor,
+ scroll_top_row,
+ }),
+ cx,
+ );
+ }
+
cx.spawn_in(window, async move |editor, cx| {
let Some(definitions) = definitions.await? else {
return Ok(Navigated::No);
@@ -16693,6 +16733,7 @@ impl Editor {
if !split
&& Some(&target_buffer) == editor.buffer.read(cx).as_singleton().as_ref()
{
+ editor.finish_tag_jump(range.start, cx);
editor.go_to_singleton_buffer_range(range, window, cx);
} else {
let pane = workspace.read(cx).active_pane().clone();
@@ -16718,6 +16759,7 @@ impl Editor {
// When selecting a definition in a different buffer, disable the nav history
// to avoid creating a history entry at the previous cursor location.
pane.update(cx, |pane, _| pane.disable_history());
+ target_editor.finish_tag_jump(range.start, cx);
target_editor.go_to_singleton_buffer_range(range, window, cx);
pane.update(cx, |pane, _| pane.enable_history());
});
@@ -17039,6 +17081,7 @@ impl Editor {
multibuffer.with_title(title)
});
+ let first_range = ranges.first().cloned();
let existing = workspace.active_pane().update(cx, |pane, cx| {
pane.items()
.filter_map(|item| item.downcast::<Editor>())
@@ -17091,6 +17134,21 @@ impl Editor {
});
}
});
+ cx.defer({
+ let editor = editor.clone();
+ move |cx| {
+ let Some(range) = first_range else { return };
+ editor.update(cx, |editor, cx| {
+ let point = editor
+ .buffer()
+ .read(cx)
+ .snapshot(cx)
+ .summary_for_anchor(&range.start);
+
+ editor.finish_tag_jump(point, cx)
+ })
+ }
+ });
let item = Box::new(editor);
let item_id = item.item_id();
@@ -911,7 +911,7 @@ async fn test_navigation_history(cx: &mut TestAppContext) {
invalid_anchor.text_anchor.buffer_id = BufferId::new(999).ok();
let invalid_point = Point::new(9999, 0);
editor.navigate(
- Box::new(NavigationData {
+ Rc::new(NavigationData {
cursor_anchor: invalid_anchor,
cursor_position: invalid_point,
scroll_anchor: ScrollAnchor {
@@ -241,6 +241,19 @@ impl Editor {
}
})
.collect();
+
+ // todo!()
+ // if let Some(nav_history) = self.nav_history.as_mut() {
+ // nav_history.start_tag_jump(
+ // Some(NavigationData {
+ // cursor_anchor,
+ // cursor_position,
+ // scroll_anchor: scroll_state,
+ // scroll_top_row,
+ // }),
+ // cx,
+ // );
+ // }
let navigate_task =
self.navigate_to_hover_links(None, links, modifiers.alt, window, cx);
self.select(SelectPhase::End, window, cx);
@@ -34,6 +34,7 @@ use std::{
iter,
ops::Range,
path::{Path, PathBuf},
+ rc::Rc,
sync::Arc,
};
use text::{BufferId, BufferSnapshot, Selection};
@@ -589,7 +590,7 @@ impl Item for Editor {
fn navigate(
&mut self,
- data: Box<dyn std::any::Any>,
+ data: Rc<dyn std::any::Any>,
window: &mut Window,
cx: &mut Context<Self>,
) -> bool {
@@ -17,6 +17,7 @@ use std::{
any::{Any, TypeId},
fmt::Write as _,
path::PathBuf,
+ rc::Rc,
sync::Arc,
};
use ui::{
@@ -527,12 +528,7 @@ impl Item for CommitView {
});
}
- fn navigate(
- &mut self,
- data: Box<dyn Any>,
- window: &mut Window,
- cx: &mut Context<Self>,
- ) -> bool {
+ fn navigate(&mut self, data: Rc<dyn Any>, window: &mut Window, cx: &mut Context<Self>) -> bool {
self.editor
.update(cx, |editor, cx| editor.navigate(data, window, cx))
}
@@ -14,6 +14,7 @@ use std::{
any::{Any, TypeId},
path::PathBuf,
pin::pin,
+ rc::Rc,
sync::Arc,
time::Duration,
};
@@ -301,12 +302,7 @@ impl Item for FileDiffView {
});
}
- fn navigate(
- &mut self,
- data: Box<dyn Any>,
- window: &mut Window,
- cx: &mut Context<Self>,
- ) -> bool {
+ fn navigate(&mut self, data: Rc<dyn Any>, window: &mut Window, cx: &mut Context<Self>) -> bool {
self.editor
.update(cx, |editor, cx| editor.navigate(data, window, cx))
}
@@ -32,9 +32,12 @@ use project::{
},
};
use settings::{Settings, SettingsStore};
-use std::any::{Any, TypeId};
use std::ops::Range;
use std::sync::Arc;
+use std::{
+ any::{Any, TypeId},
+ rc::Rc,
+};
use theme::ActiveTheme;
use ui::{KeyBinding, Tooltip, prelude::*, vertical_divider};
use util::{ResultExt as _, rel_path::RelPath};
@@ -649,12 +652,7 @@ impl Item for ProjectDiff {
.update(cx, |editor, cx| editor.deactivated(window, cx));
}
- fn navigate(
- &mut self,
- data: Box<dyn Any>,
- window: &mut Window,
- cx: &mut Context<Self>,
- ) -> bool {
+ fn navigate(&mut self, data: Rc<dyn Any>, window: &mut Window, cx: &mut Context<Self>) -> bool {
self.editor
.update(cx, |editor, cx| editor.navigate(data, window, cx))
}
@@ -15,6 +15,7 @@ use std::{
cmp,
ops::Range,
pin::pin,
+ rc::Rc,
sync::Arc,
time::Duration,
};
@@ -362,12 +363,7 @@ impl Item for TextDiffView {
});
}
- fn navigate(
- &mut self,
- data: Box<dyn Any>,
- window: &mut Window,
- cx: &mut Context<Self>,
- ) -> bool {
+ fn navigate(&mut self, data: Rc<dyn Any>, window: &mut Window, cx: &mut Context<Self>) -> bool {
self.diff_editor
.update(cx, |editor, cx| editor.navigate(data, window, cx))
}
@@ -36,6 +36,7 @@ use std::{
mem,
ops::{Not, Range},
pin::pin,
+ rc::Rc,
sync::Arc,
};
use ui::{IconButtonShape, KeyBinding, Toggleable, Tooltip, prelude::*, utils::SearchInputWidth};
@@ -633,12 +634,7 @@ impl Item for ProjectSearchView {
});
}
- fn navigate(
- &mut self,
- data: Box<dyn Any>,
- window: &mut Window,
- cx: &mut Context<Self>,
- ) -> bool {
+ fn navigate(&mut self, data: Rc<dyn Any>, window: &mut Window, cx: &mut Context<Self>) -> bool {
self.results_editor
.update(cx, |editor, cx| editor.navigate(data, window, cx))
}
@@ -194,7 +194,7 @@ pub trait Item: Focusable + EventEmitter<Self::Event> + Render + Sized {
fn discarded(&self, _project: Entity<Project>, _window: &mut Window, _cx: &mut Context<Self>) {}
fn on_removed(&self, _cx: &App) {}
fn workspace_deactivated(&mut self, _window: &mut Window, _: &mut Context<Self>) {}
- fn navigate(&mut self, _: Box<dyn Any>, _window: &mut Window, _: &mut Context<Self>) -> bool {
+ fn navigate(&mut self, _: Rc<dyn Any>, _window: &mut Window, _: &mut Context<Self>) -> bool {
false
}
@@ -449,7 +449,7 @@ pub trait ItemHandle: 'static + Send {
fn deactivated(&self, window: &mut Window, cx: &mut App);
fn on_removed(&self, cx: &App);
fn workspace_deactivated(&self, window: &mut Window, cx: &mut App);
- fn navigate(&self, data: Box<dyn Any>, window: &mut Window, cx: &mut App) -> bool;
+ fn navigate(&self, data: Rc<dyn Any>, window: &mut Window, cx: &mut App) -> bool;
fn item_id(&self) -> EntityId;
fn to_any(&self) -> AnyView;
fn is_dirty(&self, cx: &App) -> bool;
@@ -900,7 +900,7 @@ impl<T: Item> ItemHandle for Entity<T> {
self.update(cx, |this, cx| this.workspace_deactivated(window, cx));
}
- fn navigate(&self, data: Box<dyn Any>, window: &mut Window, cx: &mut App) -> bool {
+ fn navigate(&self, data: Rc<dyn Any>, window: &mut Window, cx: &mut App) -> bool {
self.update(cx, |this, cx| this.navigate(data, window, cx))
}
@@ -1277,7 +1277,7 @@ pub mod test {
InteractiveElement, IntoElement, Render, SharedString, Task, WeakEntity, Window,
};
use project::{Project, ProjectEntryId, ProjectPath, WorktreeId};
- use std::{any::Any, cell::Cell};
+ use std::{any::Any, cell::Cell, rc::Rc};
use util::rel_path::rel_path;
pub struct TestProjectItem {
@@ -1510,11 +1510,14 @@ pub mod test {
fn navigate(
&mut self,
- state: Box<dyn Any>,
+ state: Rc<dyn Any>,
_window: &mut Window,
_: &mut Context<Self>,
) -> bool {
- let state = *state.downcast::<String>().unwrap_or_default();
+ let state = state
+ .downcast_ref::<String>()
+ .map(|s| s.to_string())
+ .unwrap_or_default();
if state != self.state {
self.state = state;
true
@@ -211,6 +211,10 @@ actions!(
GoBack,
/// Navigates forward in history.
GoForward,
+ /// Navigates back in the tag stack.
+ GoToOlderTag,
+ /// Navigates forward in the tag stack.
+ GoToNewerTag,
/// Joins this pane into the next pane.
JoinIntoNext,
/// Joins all panes into one.
@@ -417,6 +421,9 @@ struct NavHistoryState {
backward_stack: VecDeque<NavigationEntry>,
forward_stack: VecDeque<NavigationEntry>,
closed_stack: VecDeque<NavigationEntry>,
+ tag_stack: VecDeque<(NavigationEntry, NavigationEntry)>,
+ tag_stack_pos: usize,
+ pending_tag_source: Option<NavigationEntry>,
paths_by_item: HashMap<EntityId, (ProjectPath, Option<PathBuf>)>,
pane: WeakEntity<Pane>,
next_timestamp: Arc<AtomicUsize>,
@@ -438,9 +445,10 @@ impl Default for NavigationMode {
}
}
+#[derive(Clone)]
pub struct NavigationEntry {
pub item: Arc<dyn WeakItemHandle>,
- pub data: Option<Box<dyn Any + Send>>,
+ pub data: Option<Rc<dyn Any + Send>>,
pub timestamp: usize,
pub is_preview: bool,
}
@@ -513,6 +521,9 @@ impl Pane {
backward_stack: Default::default(),
forward_stack: Default::default(),
closed_stack: Default::default(),
+ tag_stack: Default::default(),
+ tag_stack_pos: 0,
+ pending_tag_source: None,
paths_by_item: Default::default(),
pane: handle,
next_timestamp,
@@ -850,6 +861,24 @@ impl Pane {
}
}
+ pub fn go_to_older_tag(
+ &mut self,
+ _: &GoToOlderTag,
+ window: &mut Window,
+ cx: &mut Context<Self>,
+ ) {
+ if let Some(workspace) = self.workspace.upgrade() {
+ let pane = cx.entity().downgrade();
+ window.defer(cx, move |window, cx| {
+ workspace.update(cx, |workspace, cx| {
+ workspace
+ .navigate_tag_history(pane, window, cx)
+ .detach_and_log_err(cx)
+ })
+ })
+ }
+ }
+
fn history_updated(&mut self, cx: &mut Context<Self>) {
self.toolbar.update(cx, |_, cx| cx.notify());
}
@@ -3756,6 +3785,7 @@ impl Render for Pane {
.on_action(cx.listener(Pane::toggle_zoom))
.on_action(cx.listener(Self::navigate_backward))
.on_action(cx.listener(Self::navigate_forward))
+ .on_action(cx.listener(Self::go_to_older_tag))
.on_action(
cx.listener(|pane: &mut Pane, action: &ActivateItem, window, cx| {
pane.activate_item(
@@ -3996,8 +4026,40 @@ impl ItemNavHistory {
self.history.pop(NavigationMode::GoingBack, cx)
}
- pub fn pop_forward(&mut self, cx: &mut App) -> Option<NavigationEntry> {
- self.history.pop(NavigationMode::GoingForward, cx)
+ pub fn start_tag_jump<D>(&mut self, data: Option<D>, cx: &mut App)
+ where
+ D: 'static + Any + Send,
+ {
+ if self
+ .item
+ .upgrade()
+ .is_some_and(|item| item.include_in_nav_history())
+ {
+ self.history.start_tag_jump(
+ data.map(|data| Rc::new(data) as Rc<dyn Any + Send>),
+ self.item.clone(),
+ self.is_preview,
+ cx,
+ );
+ }
+ }
+
+ pub fn finish_tag_jump<D>(&mut self, data: Option<D>, cx: &mut App)
+ where
+ D: 'static + Any + Send,
+ {
+ if self
+ .item
+ .upgrade()
+ .is_some_and(|item| item.include_in_nav_history())
+ {
+ self.history.finish_tag_jump(
+ data.map(|data| Rc::new(data) as Rc<dyn Any + Send>),
+ self.item.clone(),
+ self.is_preview,
+ cx,
+ );
+ }
}
}
@@ -4075,7 +4137,7 @@ impl NavHistory {
}
state.backward_stack.push_back(NavigationEntry {
item,
- data: data.map(|data| Box::new(data) as Box<dyn Any + Send>),
+ data: data.map(|data| Rc::new(data) as Rc<dyn Any + Send>),
timestamp: state.next_timestamp.fetch_add(1, Ordering::SeqCst),
is_preview,
});
@@ -4087,7 +4149,7 @@ impl NavHistory {
}
state.forward_stack.push_back(NavigationEntry {
item,
- data: data.map(|data| Box::new(data) as Box<dyn Any + Send>),
+ data: data.map(|data| Rc::new(data) as Rc<dyn Any + Send>),
timestamp: state.next_timestamp.fetch_add(1, Ordering::SeqCst),
is_preview,
});
@@ -4098,7 +4160,7 @@ impl NavHistory {
}
state.backward_stack.push_back(NavigationEntry {
item,
- data: data.map(|data| Box::new(data) as Box<dyn Any + Send>),
+ data: data.map(|data| Rc::new(data) as Rc<dyn Any + Send>),
timestamp: state.next_timestamp.fetch_add(1, Ordering::SeqCst),
is_preview,
});
@@ -4109,7 +4171,7 @@ impl NavHistory {
}
state.closed_stack.push_back(NavigationEntry {
item,
- data: data.map(|data| Box::new(data) as Box<dyn Any + Send>),
+ data: data.map(|data| Rc::new(data) as Rc<dyn Any + Send>),
timestamp: state.next_timestamp.fetch_add(1, Ordering::SeqCst),
is_preview,
});
@@ -4135,6 +4197,55 @@ impl NavHistory {
pub fn path_for_item(&self, item_id: EntityId) -> Option<(ProjectPath, Option<PathBuf>)> {
self.0.lock().paths_by_item.get(&item_id).cloned()
}
+
+ pub fn start_tag_jump(
+ &mut self,
+ data: Option<Rc<dyn Any + Send>>,
+ item: Arc<dyn WeakItemHandle>,
+ is_preview: bool,
+ _cx: &mut App,
+ ) {
+ self.0.lock().pending_tag_source.replace(NavigationEntry {
+ item,
+ data,
+ timestamp: 0,
+ is_preview,
+ });
+ }
+
+ pub fn finish_tag_jump(
+ &mut self,
+ data: Option<Rc<dyn Any + Send>>,
+ item: Arc<dyn WeakItemHandle>,
+ is_preview: bool,
+ _cx: &mut App,
+ ) {
+ let mut state = self.0.lock();
+ let Some(source) = state.pending_tag_source.take() else {
+ debug_panic!("Finished tag jump without starting one?");
+ return;
+ };
+ let dest = NavigationEntry {
+ item,
+ data,
+ timestamp: 0,
+ is_preview,
+ };
+ let truncate_to = state.tag_stack_pos;
+ state.tag_stack.truncate(truncate_to);
+ state.tag_stack.push_back((source, dest));
+ state.tag_stack_pos += 1;
+ }
+
+ pub fn tag_stack_back(&mut self) -> Option<NavigationEntry> {
+ let mut state = self.0.lock();
+ if state.tag_stack_pos > 0 {
+ state.tag_stack_pos -= 1;
+ Some(state.tag_stack[state.tag_stack_pos].0.clone())
+ } else {
+ None
+ }
+ }
}
impl NavHistoryState {
@@ -1927,6 +1927,127 @@ impl Workspace {
.collect()
}
+ fn navigate_tag_history(
+ &mut self,
+ pane: WeakEntity<Pane>,
+ window: &mut Window,
+ cx: &mut Context<Workspace>,
+ ) -> Task<Result<()>> {
+ let to_load = if let Some(pane) = pane.upgrade() {
+ pane.update(cx, |pane, cx| {
+ window.focus(&pane.focus_handle(cx));
+ loop {
+ // Retrieve the weak item handle from the history.
+ let entry = pane.nav_history_mut().tag_stack_back()?;
+
+ // If the item is still present in this pane, then activate it.
+ if let Some(index) = entry
+ .item
+ .upgrade()
+ .and_then(|v| pane.index_for_item(v.as_ref()))
+ {
+ let prev_active_item_index = pane.active_item_index();
+ pane.activate_item(index, true, true, window, cx);
+
+ let mut navigated = prev_active_item_index != pane.active_item_index();
+ if let Some(data) = entry.data {
+ navigated |= pane.active_item()?.navigate(data, window, cx);
+ }
+
+ if navigated {
+ break None;
+ }
+ } else {
+ // If the item is no longer present in this pane, then retrieve its
+ // path info in order to reopen it.
+ break pane
+ .nav_history()
+ .path_for_item(entry.item.id())
+ .map(|(project_path, abs_path)| (project_path, abs_path, entry));
+ }
+ }
+ })
+ } else {
+ None
+ };
+
+ if let Some((project_path, abs_path, entry)) = to_load {
+ // If the item was no longer present, then load it again from its previous path, first try the local path
+ let open_by_project_path = self.load_path(project_path.clone(), window, cx);
+
+ cx.spawn_in(window, async move |workspace, cx| {
+ let open_by_project_path = open_by_project_path.await;
+ let mut navigated = false;
+ match open_by_project_path
+ .with_context(|| format!("Navigating to {project_path:?}"))
+ {
+ Ok((project_entry_id, build_item)) => {
+ let prev_active_item_id = pane.update(cx, |pane, _| {
+ pane.active_item().map(|p| p.item_id())
+ })?;
+
+ pane.update_in(cx, |pane, window, cx| {
+ let item = pane.open_item(
+ project_entry_id,
+ project_path,
+ true,
+ entry.is_preview,
+ true,
+ None,
+ window, cx,
+ build_item,
+ );
+ navigated |= Some(item.item_id()) != prev_active_item_id;
+ if let Some(data) = entry.data {
+ navigated |= item.navigate(data, window, cx);
+ }
+ })?;
+ }
+ Err(open_by_project_path_e) => {
+ // Fall back to opening by abs path, in case an external file was opened and closed,
+ // and its worktree is now dropped
+ if let Some(abs_path) = abs_path {
+ let prev_active_item_id = pane.update(cx, |pane, _| {
+ pane.active_item().map(|p| p.item_id())
+ })?;
+ let open_by_abs_path = workspace.update_in(cx, |workspace, window, cx| {
+ workspace.open_abs_path(abs_path.clone(), OpenOptions { visible: Some(OpenVisible::None), ..Default::default() }, window, cx)
+ })?;
+ match open_by_abs_path
+ .await
+ .with_context(|| format!("Navigating to {abs_path:?}"))
+ {
+ Ok(item) => {
+ pane.update_in(cx, |pane, window, cx| {
+ navigated |= Some(item.item_id()) != prev_active_item_id;
+ if let Some(data) = entry.data {
+ navigated |= item.navigate(data, window, cx);
+ }
+ })?;
+ }
+ Err(open_by_abs_path_e) => {
+ log::error!("Failed to navigate history: {open_by_project_path_e:#} and {open_by_abs_path_e:#}");
+ }
+ }
+ }
+ }
+ }
+
+ if !navigated {
+ workspace
+ .update_in(cx, |workspace, window, cx| {
+ Self::navigate_tag_history(workspace, pane, window, cx)
+ })?
+ .await?;
+ }
+
+ Ok(())
+ })
+ } else {
+ Task::ready(Ok(()))
+ }
+ }
+
fn navigate_history(
&mut self,
pane: WeakEntity<Pane>,