diff --git a/Cargo.lock b/Cargo.lock index 119515de8b429763e8dd9063297ee8c0b8dd5c58..03faaaf561596d1bab85b51b5f7e494de38b4712 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5677,6 +5677,7 @@ dependencies = [ "project", "serde_json", "theme", + "util", ] [[package]] diff --git a/crates/workspace/Cargo.toml b/crates/workspace/Cargo.toml index 74a9aea733ebfe5d04b6b2d593fbe8ff3bd41f93..f3ea330ca319620aa14f115a501b648798dde7a2 100644 --- a/crates/workspace/Cargo.toml +++ b/crates/workspace/Cargo.toml @@ -17,6 +17,7 @@ gpui = { path = "../gpui" } language = { path = "../language" } project = { path = "../project" } theme = { path = "../theme" } +util = { path = "../util" } anyhow = "1.0.38" log = "0.4" parking_lot = "0.11.1" diff --git a/crates/workspace/src/pane.rs b/crates/workspace/src/pane.rs index c7ea0049565217393547e1879dc2e9e4122a030d..6fb35ba78618e110691c35f0a6769faf8c3f2393 100644 --- a/crates/workspace/src/pane.rs +++ b/crates/workspace/src/pane.rs @@ -12,6 +12,7 @@ use gpui::{ use postage::watch; use project::ProjectPath; use std::{any::Any, cell::RefCell, cmp, mem, rc::Rc}; +use util::TryFutureExt; action!(Split, SplitDirection); action!(ActivateItem, usize); @@ -114,29 +115,51 @@ impl Pane { cx.emit(Event::Activate); } - pub fn go_back(&mut self, _: &GoBack, cx: &mut ViewContext) { - if self.navigation.0.borrow().backward_stack.is_empty() { - return; - } - - if let Some(item_view) = self.active_item() { - self.navigation.0.borrow_mut().mode = NavigationHistoryMode::GoingBack; - item_view.deactivated(cx); - self.navigation.0.borrow_mut().mode = NavigationHistoryMode::Normal; - } + pub fn go_back(workspace: &mut Workspace, _: &GoBack, cx: &mut ViewContext) { + let project_path = workspace.active_pane().update(cx, |pane, cx| { + let mut navigation = pane.navigation.0.borrow_mut(); + if let Some(entry) = navigation.backward_stack.pop() { + if let Some(index) = entry + .item_view + .upgrade(cx) + .and_then(|v| pane.index_for_item_view(v.as_ref())) + { + if let Some(item_view) = pane.active_item() { + pane.navigation.0.borrow_mut().mode = NavigationHistoryMode::GoingBack; + item_view.deactivated(cx); + pane.navigation.0.borrow_mut().mode = NavigationHistoryMode::Normal; + } - let mut navigation = self.navigation.0.borrow_mut(); - if let Some(entry) = navigation.backward_stack.pop() { - if let Some(index) = entry - .item_view - .upgrade(cx) - .and_then(|v| self.index_for_item_view(v.as_ref())) - { - self.active_item_index = index; - drop(navigation); - self.focus_active_item(cx); - cx.notify(); + pane.active_item_index = index; + drop(navigation); + pane.focus_active_item(cx); + cx.notify(); + } else { + return navigation.paths_by_item.get(&entry.item_view.id()).cloned(); + } } + + None + }); + + if let Some(project_path) = project_path { + let task = workspace.load_path(project_path, cx); + cx.spawn(|workspace, mut cx| { + async move { + let item = task.await?; + workspace.update(&mut cx, |workspace, cx| { + let pane = workspace.active_pane().clone(); + pane.update(cx, |pane, cx| { + pane.navigation.0.borrow_mut().mode = NavigationHistoryMode::GoingBack; + pane.open_item(item, workspace, cx); + pane.navigation.0.borrow_mut().mode = NavigationHistoryMode::Normal; + }); + }); + Ok(()) + } + .log_err() + }) + .detach(); } } @@ -268,17 +291,17 @@ impl Pane { pub fn close_item(&mut self, item_view_id: usize, cx: &mut ViewContext) { let mut item_ix = 0; - self.item_views.retain(|(item_id, item)| { - if item.id() == item_view_id { + self.item_views.retain(|(_, item_view)| { + if item_view.id() == item_view_id { let mut navigation = self.navigation.0.borrow_mut(); - if let Some(path) = item.project_path(cx) { - navigation.paths_by_item.insert(*item_id, path); + if let Some(path) = item_view.project_path(cx) { + navigation.paths_by_item.insert(item_view.id(), path); } else { - navigation.paths_by_item.remove(item_id); + navigation.paths_by_item.remove(&item_view.id()); } if item_ix == self.active_item_index { - item.deactivated(cx); + item_view.deactivated(cx); } item_ix += 1; false diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index 9f65062bf9b08d42c7356793a7e6ae70809516eb..99ef8764e8b6f95096ec42748700465711c8e97c 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -227,6 +227,7 @@ pub trait ItemViewHandle { } pub trait WeakItemViewHandle { + fn id(&self) -> usize; fn upgrade(&self, cx: &AppContext) -> Option>; } @@ -418,6 +419,10 @@ impl Clone for Box { } impl WeakItemViewHandle for WeakViewHandle { + fn id(&self) -> usize { + self.id() + } + fn upgrade(&self, cx: &AppContext) -> Option> { self.upgrade(cx) .map(|v| Box::new(v) as Box) @@ -747,46 +752,49 @@ impl Workspace { } } - #[must_use] pub fn open_path( &mut self, path: ProjectPath, cx: &mut ViewContext, ) -> Task, Arc>> { + let load_task = self.load_path(path, cx); + let pane = self.active_pane().clone().downgrade(); + cx.spawn(|this, mut cx| async move { + let item = load_task.await?; + this.update(&mut cx, |this, cx| { + let pane = pane + .upgrade(&cx) + .ok_or_else(|| anyhow!("could not upgrade pane reference"))?; + Ok(this.open_item_in_pane(item, &pane, cx)) + }) + }) + } + + pub fn load_path( + &mut self, + path: ProjectPath, + cx: &mut ViewContext, + ) -> Task>> { if let Some(existing_item) = self.item_for_path(&path, cx) { - return Task::ready(Ok(self.open_item(existing_item, cx))); + return Task::ready(Ok(existing_item)); } let worktree = match self.project.read(cx).worktree_for_id(path.worktree_id, cx) { Some(worktree) => worktree, None => { - return Task::ready(Err(Arc::new(anyhow!( - "worktree {} does not exist", - path.worktree_id - )))); + return Task::ready(Err(anyhow!("worktree {} does not exist", path.worktree_id))); } }; let project_path = path.clone(); let path_openers = self.path_openers.clone(); - let open_task = worktree.update(cx, |worktree, cx| { + worktree.update(cx, |worktree, cx| { for opener in path_openers.iter() { if let Some(task) = opener.open(worktree, project_path.clone(), cx) { return task; } } Task::ready(Err(anyhow!("no opener found for path {:?}", project_path))) - }); - - let pane = self.active_pane().clone().downgrade(); - cx.spawn(|this, mut cx| async move { - let item = open_task.await?; - this.update(&mut cx, |this, cx| { - let pane = pane - .upgrade(&cx) - .ok_or_else(|| anyhow!("could not upgrade pane reference"))?; - Ok(this.open_item_in_pane(item, &pane, cx)) - }) }) }