terminal: Fix terminal cloning on WSL (#39552)
Marco Mihai Condrache
created 1 month ago
Should close #39428
The working directory of the `wsl.exe` program is set to a Linux path,
which is invalid on the Windows side, causing the terminal to crash. The
first spawn works because there is no active terminal view, allowing a
new shell (which checks for the remote) to be created. I cannot explain
why it works on SSH remote clients, but I may be missing something in
the remote connection implementation.
I don't have a Windows machine to test this, so I would appreciate
someone testing it. 🙏🏼
Release Notes:
- Fixed an issue where WSL terminals could not be splitted
---------
Signed-off-by: Marco Mihai Condrache <52580954+marcocondrache@users.noreply.github.com>
Change summary
crates/project/src/terminals.rs | 55 +++++++++++++----------
crates/terminal/src/terminal.rs | 8 --
crates/terminal_view/src/terminal_panel.rs | 2
crates/terminal_view/src/terminal_view.rs | 2
4 files changed, 36 insertions(+), 31 deletions(-)
Detailed changes
@@ -404,31 +404,40 @@ impl Project {
&mut self,
terminal: &Entity<Terminal>,
cx: &mut Context<'_, Project>,
- cwd: impl FnOnce() -> Option<PathBuf>,
+ cwd: Option<PathBuf>,
) -> Result<Entity<Terminal>> {
- terminal.read(cx).clone_builder(cx, cwd).map(|builder| {
- let terminal_handle = cx.new(|cx| builder.subscribe(cx));
-
- self.terminals
- .local_handles
- .push(terminal_handle.downgrade());
-
- let id = terminal_handle.entity_id();
- cx.observe_release(&terminal_handle, move |project, _terminal, cx| {
- let handles = &mut project.terminals.local_handles;
-
- if let Some(index) = handles
- .iter()
- .position(|terminal| terminal.entity_id() == id)
- {
- handles.remove(index);
- cx.notify();
- }
- })
- .detach();
+ let local_path = if self.is_via_remote_server() {
+ None
+ } else {
+ cwd
+ };
- terminal_handle
- })
+ terminal
+ .read(cx)
+ .clone_builder(cx, local_path)
+ .map(|builder| {
+ let terminal_handle = cx.new(|cx| builder.subscribe(cx));
+
+ self.terminals
+ .local_handles
+ .push(terminal_handle.downgrade());
+
+ let id = terminal_handle.entity_id();
+ cx.observe_release(&terminal_handle, move |project, _terminal, cx| {
+ let handles = &mut project.terminals.local_handles;
+
+ if let Some(index) = handles
+ .iter()
+ .position(|terminal| terminal.entity_id() == id)
+ {
+ handles.remove(index);
+ cx.notify();
+ }
+ })
+ .detach();
+
+ terminal_handle
+ })
}
pub fn terminal_settings<'a>(
@@ -2135,12 +2135,8 @@ impl Terminal {
self.vi_mode_enabled
}
- pub fn clone_builder(
- &self,
- cx: &App,
- cwd: impl FnOnce() -> Option<PathBuf>,
- ) -> Result<TerminalBuilder> {
- let working_directory = self.working_directory().or_else(cwd);
+ pub fn clone_builder(&self, cx: &App, cwd: Option<PathBuf>) -> Result<TerminalBuilder> {
+ let working_directory = self.working_directory().or_else(|| cwd);
TerminalBuilder::new(
working_directory,
None,
@@ -466,7 +466,7 @@ impl TerminalPanel {
Some(view) => Task::ready(project.clone_terminal(
&view.read(cx).terminal.clone(),
cx,
- || working_directory,
+ working_directory,
)),
None => project.create_terminal_shell(working_directory, cx),
})
@@ -1225,7 +1225,7 @@ impl Item for TerminalView {
let cwd = project
.active_project_directory(cx)
.map(|it| it.to_path_buf());
- project.clone_terminal(self.terminal(), cx, || cwd)
+ project.clone_terminal(self.terminal(), cx, cwd)
})
.ok()?
.log_err()?;