From 54a7da364cbcc738b52a0917631684c10afac59a Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Sun, 26 Oct 2025 12:01:40 +0200 Subject: [PATCH] Fix task terminal split (#41218) Re-lands https://github.com/zed-industries/zed/pull/40824 Release Notes: - N/A --- crates/project/src/terminals.rs | 12 ++++-- crates/terminal/src/terminal.rs | 2 +- crates/terminal_view/src/terminal_panel.rs | 4 +- crates/terminal_view/src/terminal_view.rs | 47 +++++++++++----------- 4 files changed, 36 insertions(+), 29 deletions(-) diff --git a/crates/project/src/terminals.rs b/crates/project/src/terminals.rs index f51331a3b073522d09e36c7a2ea96585c66a452f..08de0eb138b6695eb65bc30acbfa9688bb38fe00 100644 --- a/crates/project/src/terminals.rs +++ b/crates/project/src/terminals.rs @@ -410,14 +410,19 @@ impl Project { terminal: &Entity, cx: &mut Context<'_, Project>, cwd: Option, - ) -> Result> { + ) -> Task>> { + // We cannot clone the task's terminal, as it will effectively re-spawn the task, which might not be desirable. + // For now, create a new shell instead. + if terminal.read(cx).task().is_some() { + return self.create_terminal_shell(cwd, cx); + } let local_path = if self.is_via_remote_server() { None } else { cwd }; - terminal + let new_terminal = terminal .read(cx) .clone_builder(cx, local_path) .map(|builder| { @@ -442,7 +447,8 @@ impl Project { .detach(); terminal_handle - }) + }); + Task::ready(new_terminal) } pub fn terminal_settings<'a>( diff --git a/crates/terminal/src/terminal.rs b/crates/terminal/src/terminal.rs index 7da7ba78d90848ed3349c840eff13b13e5b23c34..41c51c38f7b1163229bb6570679ac873bd36474b 100644 --- a/crates/terminal/src/terminal.rs +++ b/crates/terminal/src/terminal.rs @@ -455,7 +455,7 @@ impl TerminalBuilder { args: Option>, title_override: Option, ) -> Self { - log::info!("Using {program} as shell"); + log::debug!("Using {program} as shell"); Self { program, args, diff --git a/crates/terminal_view/src/terminal_panel.rs b/crates/terminal_view/src/terminal_panel.rs index 5ba6c6c503d1b47b3a40149e3a6becf44565e8cc..6568eac324552a293d64060c07f6299d2edf9f8d 100644 --- a/crates/terminal_view/src/terminal_panel.rs +++ b/crates/terminal_view/src/terminal_panel.rs @@ -461,11 +461,11 @@ impl TerminalPanel { cx.spawn_in(window, async move |panel, cx| { let terminal = project .update(cx, |project, cx| match terminal_view { - Some(view) => Task::ready(project.clone_terminal( + Some(view) => project.clone_terminal( &view.read(cx).terminal.clone(), cx, working_directory, - )), + ), None => project.create_terminal_shell(working_directory, cx), }) .ok()? diff --git a/crates/terminal_view/src/terminal_view.rs b/crates/terminal_view/src/terminal_view.rs index 7430a2b8acbbf4d6d2d78109e40c4781f1fab7a7..5111f3a99b49d35a7f3a7ba141e20d4dc7cc4828 100644 --- a/crates/terminal_view/src/terminal_view.rs +++ b/crates/terminal_view/src/terminal_view.rs @@ -38,7 +38,7 @@ use ui::{ prelude::*, scrollbars::{self, GlobalSetting, ScrollbarVisibility}, }; -use util::{ResultExt, maybe}; +use util::ResultExt; use workspace::{ CloseActiveItem, NewCenterTerminal, NewTerminal, ToolbarItemLocation, Workspace, WorkspaceId, delete_unloaded_items, @@ -1219,29 +1219,30 @@ impl Item for TerminalView { window: &mut Window, cx: &mut Context, ) -> Task>> { - Task::ready(maybe!({ - let terminal = self - .project - .update(cx, |project, cx| { - let cwd = project - .active_project_directory(cx) - .map(|it| it.to_path_buf()); - project.clone_terminal(self.terminal(), cx, cwd) + let Some(terminal_task) = self + .project + .update(cx, |project, cx| { + let cwd = project + .active_project_directory(cx) + .map(|it| it.to_path_buf()); + project.clone_terminal(self.terminal(), cx, cwd) + }) + .ok() + else { + return Task::ready(None); + }; + + let workspace = self.workspace.clone(); + let project = self.project.clone(); + cx.spawn_in(window, async move |_, cx| { + let terminal = terminal_task.await.log_err()?; + cx.update(|window, cx| { + cx.new(|cx| { + TerminalView::new(terminal, workspace, workspace_id, project, window, cx) }) - .ok()? - .log_err()?; - - Some(cx.new(|cx| { - TerminalView::new( - terminal, - self.workspace.clone(), - workspace_id, - self.project.clone(), - window, - cx, - ) - })) - })) + }) + .ok() + }) } fn is_dirty(&self, cx: &gpui::App) -> bool {