mirror of
https://github.com/zed-industries/zed.git
synced 2025-01-11 05:00:16 +00:00
Return a future from WorkspaceView::open_paths
Co-Authored-By: Nathan Sobo <nathan@zed.dev>
This commit is contained in:
parent
b126938af7
commit
5826a976ef
3 changed files with 130 additions and 70 deletions
|
@ -1717,6 +1717,10 @@ impl<'a, T: View> ViewContext<'a, T> {
|
||||||
self.window_id
|
self.window_id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn foreground(&self) -> &Rc<executor::Foreground> {
|
||||||
|
self.app.foreground_executor()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn background_executor(&self) -> &Arc<executor::Background> {
|
pub fn background_executor(&self) -> &Arc<executor::Background> {
|
||||||
&self.app.ctx.background
|
&self.app.ctx.background
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,7 +52,8 @@ fn open_paths(params: &OpenParams, app: &mut MutableAppContext) {
|
||||||
if let Some(handle) = app.root_view::<WorkspaceView>(window_id) {
|
if let Some(handle) = app.root_view::<WorkspaceView>(window_id) {
|
||||||
if handle.update(app, |view, ctx| {
|
if handle.update(app, |view, ctx| {
|
||||||
if view.contains_paths(¶ms.paths, ctx.as_ref()) {
|
if view.contains_paths(¶ms.paths, ctx.as_ref()) {
|
||||||
view.open_paths(¶ms.paths, ctx);
|
let open_paths = view.open_paths(¶ms.paths, ctx);
|
||||||
|
ctx.foreground().spawn(open_paths).detach();
|
||||||
log::info!("open paths on existing workspace");
|
log::info!("open paths on existing workspace");
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
|
@ -70,7 +71,8 @@ fn open_paths(params: &OpenParams, app: &mut MutableAppContext) {
|
||||||
let workspace = app.add_model(|ctx| Workspace::new(vec![], ctx));
|
let workspace = app.add_model(|ctx| Workspace::new(vec![], ctx));
|
||||||
app.add_window(|ctx| {
|
app.add_window(|ctx| {
|
||||||
let view = WorkspaceView::new(workspace, params.settings.clone(), ctx);
|
let view = WorkspaceView::new(workspace, params.settings.clone(), ctx);
|
||||||
view.open_paths(¶ms.paths, ctx);
|
let open_paths = view.open_paths(¶ms.paths, ctx);
|
||||||
|
ctx.foreground().spawn(open_paths).detach();
|
||||||
view
|
view
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use super::{pane, Pane, PaneGroup, SplitDirection, Workspace};
|
use super::{pane, Pane, PaneGroup, SplitDirection, Workspace};
|
||||||
use crate::{settings::Settings, watch};
|
use crate::{settings::Settings, watch};
|
||||||
use futures_core::future::LocalBoxFuture;
|
use futures_core::{future::LocalBoxFuture, Future};
|
||||||
use gpui::{
|
use gpui::{
|
||||||
color::rgbu, elements::*, json::to_string_pretty, keymap::Binding, AnyViewHandle, AppContext,
|
color::rgbu, elements::*, json::to_string_pretty, keymap::Binding, AnyViewHandle, AppContext,
|
||||||
ClipboardItem, Entity, ModelHandle, MutableAppContext, View, ViewContext, ViewHandle,
|
ClipboardItem, Entity, ModelHandle, MutableAppContext, View, ViewContext, ViewHandle,
|
||||||
|
@ -161,22 +161,38 @@ impl WorkspaceView {
|
||||||
self.workspace.read(app).contains_paths(paths, app)
|
self.workspace.read(app).contains_paths(paths, app)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn open_paths(&self, paths: &[PathBuf], ctx: &mut ViewContext<Self>) {
|
pub fn open_paths(
|
||||||
|
&self,
|
||||||
|
paths: &[PathBuf],
|
||||||
|
ctx: &mut ViewContext<Self>,
|
||||||
|
) -> impl Future<Output = ()> {
|
||||||
let entries = self
|
let entries = self
|
||||||
.workspace
|
.workspace
|
||||||
.update(ctx, |workspace, ctx| workspace.open_paths(paths, ctx));
|
.update(ctx, |workspace, ctx| workspace.open_paths(paths, ctx));
|
||||||
for (i, entry) in entries.into_iter().enumerate() {
|
let bg = ctx.background_executor().clone();
|
||||||
let path = paths[i].clone();
|
let tasks = paths
|
||||||
ctx.spawn(
|
.iter()
|
||||||
ctx.background_executor()
|
.cloned()
|
||||||
.spawn(async move { path.is_file() }),
|
.zip(entries.into_iter())
|
||||||
|me, is_file, ctx| {
|
.map(|(path, entry)| {
|
||||||
if is_file {
|
ctx.spawn(
|
||||||
me.open_entry(entry, ctx)
|
bg.spawn(async move { path.is_file() }),
|
||||||
}
|
|me, is_file, ctx| {
|
||||||
},
|
if is_file {
|
||||||
)
|
me.open_entry(entry, ctx)
|
||||||
.detach();
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
async move {
|
||||||
|
for task in tasks {
|
||||||
|
if let Some(task) = task.await {
|
||||||
|
task.await;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -207,16 +223,20 @@ impl WorkspaceView {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn open_entry(&mut self, entry: (usize, Arc<Path>), ctx: &mut ViewContext<Self>) {
|
pub fn open_entry(
|
||||||
|
&mut self,
|
||||||
|
entry: (usize, Arc<Path>),
|
||||||
|
ctx: &mut ViewContext<Self>,
|
||||||
|
) -> Option<impl Future<Output = ()>> {
|
||||||
if self.loading_entries.contains(&entry) {
|
if self.loading_entries.contains(&entry) {
|
||||||
return;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
if self
|
if self
|
||||||
.active_pane()
|
.active_pane()
|
||||||
.update(ctx, |pane, ctx| pane.activate_entry(entry.clone(), ctx))
|
.update(ctx, |pane, ctx| pane.activate_entry(entry.clone(), ctx))
|
||||||
{
|
{
|
||||||
return;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.loading_entries.insert(entry.clone());
|
self.loading_entries.insert(entry.clone());
|
||||||
|
@ -224,10 +244,13 @@ impl WorkspaceView {
|
||||||
match self.workspace.update(ctx, |workspace, ctx| {
|
match self.workspace.update(ctx, |workspace, ctx| {
|
||||||
workspace.open_entry(entry.clone(), ctx)
|
workspace.open_entry(entry.clone(), ctx)
|
||||||
}) {
|
}) {
|
||||||
Err(error) => error!("{}", error),
|
Err(error) => {
|
||||||
|
error!("{}", error);
|
||||||
|
None
|
||||||
|
}
|
||||||
Ok(item) => {
|
Ok(item) => {
|
||||||
let settings = self.settings.clone();
|
let settings = self.settings.clone();
|
||||||
ctx.spawn(item, move |me, item, ctx| {
|
Some(ctx.spawn(item, move |me, item, ctx| {
|
||||||
me.loading_entries.remove(&entry);
|
me.loading_entries.remove(&entry);
|
||||||
match item {
|
match item {
|
||||||
Ok(item) => {
|
Ok(item) => {
|
||||||
|
@ -238,8 +261,7 @@ impl WorkspaceView {
|
||||||
error!("{}", error);
|
error!("{}", error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
}))
|
||||||
.detach();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -423,13 +445,23 @@ mod tests {
|
||||||
let pane = app.read(|ctx| workspace_view.read(ctx).active_pane().clone());
|
let pane = app.read(|ctx| workspace_view.read(ctx).active_pane().clone());
|
||||||
|
|
||||||
// Open the first entry
|
// Open the first entry
|
||||||
workspace_view.update(&mut app, |w, ctx| w.open_entry(file1.clone(), ctx));
|
workspace_view
|
||||||
pane.condition(&app, |pane, _| pane.items().len() == 1)
|
.update(&mut app, |w, ctx| w.open_entry(file1.clone(), ctx))
|
||||||
|
.unwrap()
|
||||||
.await;
|
.await;
|
||||||
|
app.read(|ctx| {
|
||||||
|
let pane = pane.read(ctx);
|
||||||
|
assert_eq!(
|
||||||
|
pane.active_item().unwrap().entry_id(ctx),
|
||||||
|
Some(file1.clone())
|
||||||
|
);
|
||||||
|
assert_eq!(pane.items().len(), 1);
|
||||||
|
});
|
||||||
|
|
||||||
// Open the second entry
|
// Open the second entry
|
||||||
workspace_view.update(&mut app, |w, ctx| w.open_entry(file2.clone(), ctx));
|
workspace_view
|
||||||
pane.condition(&app, |pane, _| pane.items().len() == 2)
|
.update(&mut app, |w, ctx| w.open_entry(file2.clone(), ctx))
|
||||||
|
.unwrap()
|
||||||
.await;
|
.await;
|
||||||
app.read(|ctx| {
|
app.read(|ctx| {
|
||||||
let pane = pane.read(ctx);
|
let pane = pane.read(ctx);
|
||||||
|
@ -437,25 +469,38 @@ mod tests {
|
||||||
pane.active_item().unwrap().entry_id(ctx),
|
pane.active_item().unwrap().entry_id(ctx),
|
||||||
Some(file2.clone())
|
Some(file2.clone())
|
||||||
);
|
);
|
||||||
|
assert_eq!(pane.items().len(), 2);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Open the first entry again
|
// Open the first entry again. The existing pane item is activated.
|
||||||
workspace_view.update(&mut app, |w, ctx| w.open_entry(file1.clone(), ctx));
|
|
||||||
pane.condition(&app, move |pane, ctx| {
|
|
||||||
pane.active_item().unwrap().entry_id(ctx) == Some(file1.clone())
|
|
||||||
})
|
|
||||||
.await;
|
|
||||||
app.read(|ctx| {
|
|
||||||
assert_eq!(pane.read(ctx).items().len(), 2);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Open the third entry twice concurrently
|
|
||||||
workspace_view.update(&mut app, |w, ctx| {
|
workspace_view.update(&mut app, |w, ctx| {
|
||||||
w.open_entry(file3.clone(), ctx);
|
assert!(w.open_entry(file1.clone(), ctx).is_none())
|
||||||
w.open_entry(file3.clone(), ctx);
|
|
||||||
});
|
});
|
||||||
pane.condition(&app, |pane, _| pane.items().len() == 3)
|
app.read(|ctx| {
|
||||||
|
let pane = pane.read(ctx);
|
||||||
|
assert_eq!(
|
||||||
|
pane.active_item().unwrap().entry_id(ctx),
|
||||||
|
Some(file1.clone())
|
||||||
|
);
|
||||||
|
assert_eq!(pane.items().len(), 2);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Open the third entry twice concurrently. Only one pane item is added.
|
||||||
|
workspace_view
|
||||||
|
.update(&mut app, |w, ctx| {
|
||||||
|
let task = w.open_entry(file3.clone(), ctx).unwrap();
|
||||||
|
assert!(w.open_entry(file3.clone(), ctx).is_none());
|
||||||
|
task
|
||||||
|
})
|
||||||
.await;
|
.await;
|
||||||
|
app.read(|ctx| {
|
||||||
|
let pane = pane.read(ctx);
|
||||||
|
assert_eq!(
|
||||||
|
pane.active_item().unwrap().entry_id(ctx),
|
||||||
|
Some(file3.clone())
|
||||||
|
);
|
||||||
|
assert_eq!(pane.items().len(), 3);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -479,23 +524,29 @@ mod tests {
|
||||||
// Open a file within an existing worktree.
|
// Open a file within an existing worktree.
|
||||||
app.update(|ctx| {
|
app.update(|ctx| {
|
||||||
workspace_view.update(ctx, |view, ctx| {
|
workspace_view.update(ctx, |view, ctx| {
|
||||||
view.open_paths(&[dir1.path().join("a.txt")], ctx);
|
view.open_paths(&[dir1.path().join("a.txt")], ctx)
|
||||||
});
|
|
||||||
});
|
|
||||||
workspace_view
|
|
||||||
.condition(&app, |view, ctx| {
|
|
||||||
view.active_pane()
|
|
||||||
.read(ctx)
|
|
||||||
.active_item()
|
|
||||||
.map_or(false, |item| item.title(&ctx) == "a.txt")
|
|
||||||
})
|
})
|
||||||
.await;
|
})
|
||||||
|
.await;
|
||||||
|
app.read(|ctx| {
|
||||||
|
workspace_view
|
||||||
|
.read(ctx)
|
||||||
|
.active_pane()
|
||||||
|
.read(ctx)
|
||||||
|
.active_item()
|
||||||
|
.unwrap()
|
||||||
|
.title(ctx)
|
||||||
|
== "a.txt"
|
||||||
|
});
|
||||||
|
|
||||||
// Open a file outside of any existing worktree.
|
// Open a file outside of any existing worktree.
|
||||||
app.update(|ctx| {
|
app.update(|ctx| {
|
||||||
workspace_view.update(ctx, |view, ctx| {
|
workspace_view.update(ctx, |view, ctx| {
|
||||||
view.open_paths(&[dir2.path().join("b.txt")], ctx);
|
view.open_paths(&[dir2.path().join("b.txt")], ctx)
|
||||||
});
|
})
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
app.update(|ctx| {
|
||||||
let worktree_roots = workspace
|
let worktree_roots = workspace
|
||||||
.read(ctx)
|
.read(ctx)
|
||||||
.worktrees()
|
.worktrees()
|
||||||
|
@ -509,14 +560,16 @@ mod tests {
|
||||||
.collect(),
|
.collect(),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
workspace_view
|
app.read(|ctx| {
|
||||||
.condition(&app, |view, ctx| {
|
workspace_view
|
||||||
view.active_pane()
|
.read(ctx)
|
||||||
.read(ctx)
|
.active_pane()
|
||||||
.active_item()
|
.read(ctx)
|
||||||
.map_or(false, |item| item.title(&ctx) == "b.txt")
|
.active_item()
|
||||||
})
|
.unwrap()
|
||||||
.await;
|
.title(ctx)
|
||||||
|
== "b.txt"
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -544,15 +597,16 @@ mod tests {
|
||||||
app.add_window(|ctx| WorkspaceView::new(workspace.clone(), settings, ctx));
|
app.add_window(|ctx| WorkspaceView::new(workspace.clone(), settings, ctx));
|
||||||
let pane_1 = app.read(|ctx| workspace_view.read(ctx).active_pane().clone());
|
let pane_1 = app.read(|ctx| workspace_view.read(ctx).active_pane().clone());
|
||||||
|
|
||||||
workspace_view.update(&mut app, |w, ctx| w.open_entry(file1.clone(), ctx));
|
workspace_view
|
||||||
{
|
.update(&mut app, |w, ctx| w.open_entry(file1.clone(), ctx))
|
||||||
let file1 = file1.clone();
|
.unwrap()
|
||||||
pane_1
|
.await;
|
||||||
.condition(&app, move |pane, ctx| {
|
app.read(|ctx| {
|
||||||
pane.active_item().and_then(|i| i.entry_id(ctx)) == Some(file1.clone())
|
assert_eq!(
|
||||||
})
|
pane_1.read(ctx).active_item().unwrap().entry_id(ctx),
|
||||||
.await;
|
Some(file1.clone())
|
||||||
}
|
);
|
||||||
|
});
|
||||||
|
|
||||||
app.dispatch_action(window_id, vec![pane_1.id()], "pane:split_right", ());
|
app.dispatch_action(window_id, vec![pane_1.id()], "pane:split_right", ());
|
||||||
app.update(|ctx| {
|
app.update(|ctx| {
|
||||||
|
|
Loading…
Reference in a new issue