Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions crates/acp_thread/src/acp_thread.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2112,6 +2112,7 @@ impl AcpThread {

let project = self.project.clone();
let language_registry = project.read(cx).languages().clone();
let is_windows = project.read(cx).path_style(cx).is_windows();

let terminal_id = acp::TerminalId(Uuid::new_v4().to_string().into());
let terminal_task = cx.spawn({
Expand All @@ -2125,9 +2126,10 @@ impl AcpThread {
.and_then(|r| r.read(cx).default_system_shell())
})?
.unwrap_or_else(|| get_default_system_shell_preferring_bash());
let (task_command, task_args) = ShellBuilder::new(&Shell::Program(shell))
.redirect_stdin_to_dev_null()
.build(Some(command.clone()), &args);
let (task_command, task_args) =
ShellBuilder::new(&Shell::Program(shell), is_windows)
.redirect_stdin_to_dev_null()
.build(Some(command.clone()), &args);
let terminal = project
.update(cx, |project, cx| {
project.create_terminal_task(
Expand Down
5 changes: 4 additions & 1 deletion crates/agent_servers/src/acp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -835,7 +835,10 @@ impl acp::Client for ClientDelegate {
.map(Shell::Program)
})?
.unwrap_or(task::Shell::System);
let (task_command, task_args) = task::ShellBuilder::new(&shell)
let is_windows = project
.read_with(&self.cx, |project, cx| project.path_style(cx).is_windows())
.unwrap_or(cfg!(windows));
let (task_command, task_args) = task::ShellBuilder::new(&shell, is_windows)
.redirect_stdin_to_dev_null()
.build(Some(args.command.clone()), &args.args);

Expand Down
3 changes: 2 additions & 1 deletion crates/assistant_tools/src/terminal_tool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ impl Tool for TerminalTool {
}),
None => Task::ready(None).shared(),
};
let is_windows = project.read(cx).path_style(cx).is_windows();
let shell = project
.update(cx, |project, cx| {
project
Expand All @@ -155,7 +156,7 @@ impl Tool for TerminalTool {
let build_cmd = {
let input_command = input.command.clone();
move || {
ShellBuilder::new(&Shell::Program(shell))
ShellBuilder::new(&Shell::Program(shell), is_windows)
.redirect_stdin_to_dev_null()
.build(Some(input_command), &[])
}
Expand Down
3 changes: 2 additions & 1 deletion crates/debugger_ui/src/session/running.rs
Original file line number Diff line number Diff line change
Expand Up @@ -937,6 +937,7 @@ impl RunningState {
let task_store = project.read(cx).task_store().downgrade();
let weak_project = project.downgrade();
let weak_workspace = workspace.downgrade();
let is_windows = project.read(cx).path_style(cx).is_windows();
let remote_shell = project
.read(cx)
.remote_client()
Expand Down Expand Up @@ -1029,7 +1030,7 @@ impl RunningState {
task.resolved.shell = Shell::Program(remote_shell);
}

let builder = ShellBuilder::new(&task.resolved.shell);
let builder = ShellBuilder::new(&task.resolved.shell, is_windows);
let command_label = builder.command_label(task.resolved.command.as_deref().unwrap_or(""));
let (command, args) =
builder.build(task.resolved.command.clone(), &task.resolved.args);
Expand Down
2 changes: 1 addition & 1 deletion crates/project/src/debugger/locators/cargo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ impl DapLocator for CargoLocator {
.cwd
.clone()
.context("Couldn't get cwd from debug config which is needed for locators")?;
let builder = ShellBuilder::new(&build_config.shell).non_interactive();
let builder = ShellBuilder::new(&build_config.shell, cfg!(windows)).non_interactive();
let (program, args) = builder.build(
Some("cargo".into()),
&build_config
Expand Down
13 changes: 9 additions & 4 deletions crates/project/src/terminals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,8 @@ impl Project {
None => settings.shell.program(),
};

let is_windows = self.path_style(cx).is_windows();

let project_path_contexts = self
.active_entry()
.and_then(|entry_id| self.path_for_entry(entry_id, cx))
Expand All @@ -120,7 +122,7 @@ impl Project {
let lang_registry = self.languages.clone();
let fs = self.fs.clone();
cx.spawn(async move |project, cx| {
let shell_kind = ShellKind::new(&shell);
let shell_kind = ShellKind::new(&shell, is_windows);
let activation_script = maybe!(async {
for toolchain in toolchains {
let Some(toolchain) = toolchain.await else {
Expand Down Expand Up @@ -319,13 +321,15 @@ impl Project {
.map(|p| self.active_toolchain(p, LanguageName::new("Python"), cx))
.collect::<Vec<_>>();
let remote_client = self.remote_client.clone();
let shell_kind = ShellKind::new(&match &remote_client {
let shell = match &remote_client {
Some(remote_client) => remote_client
.read(cx)
.shell()
.unwrap_or_else(get_default_system_shell),
None => settings.shell.program(),
});
};

let shell_kind = ShellKind::new(&shell, self.path_style(cx).is_windows());

let lang_registry = self.languages.clone();
let fs = self.fs.clone();
Expand Down Expand Up @@ -466,7 +470,8 @@ impl Project {
.and_then(|remote_client| remote_client.read(cx).shell())
.map(Shell::Program)
.unwrap_or_else(|| settings.shell.clone());
let builder = ShellBuilder::new(&shell).non_interactive();
let is_windows = self.path_style(cx).is_windows();
let builder = ShellBuilder::new(&shell, is_windows).non_interactive();
let (command, args) = builder.build(Some(command), &Vec::new());

let mut env = self
Expand Down
3 changes: 2 additions & 1 deletion crates/prompt_store/src/prompts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ impl ProjectContext {
user_rules: default_user_rules,
os: std::env::consts::OS.to_string(),
arch: std::env::consts::ARCH.to_string(),
shell: ShellKind::new(&get_default_system_shell_preferring_bash()).to_string(),
shell: ShellKind::new(&get_default_system_shell_preferring_bash(), cfg!(windows))
.to_string(),
}
}
}
Expand Down
8 changes: 4 additions & 4 deletions crates/task/src/shell_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,14 @@ pub struct ShellBuilder {

impl ShellBuilder {
/// Create a new ShellBuilder as configured.
pub fn new(shell: &Shell) -> Self {
pub fn new(shell: &Shell, is_windows: bool) -> Self {
let (program, args) = match shell {
Shell::System => (get_system_shell(), Vec::new()),
Shell::Program(shell) => (shell.clone(), Vec::new()),
Shell::WithArguments { program, args, .. } => (program.clone(), args.clone()),
};

let kind = ShellKind::new(&program);
let kind = ShellKind::new(&program, is_windows);
Self {
program,
args,
Expand Down Expand Up @@ -120,7 +120,7 @@ mod test {
#[test]
fn test_nu_shell_variable_substitution() {
let shell = Shell::Program("nu".to_owned());
let shell_builder = ShellBuilder::new(&shell);
let shell_builder = ShellBuilder::new(&shell, false);

let (program, args) = shell_builder.build(
Some("echo".into()),
Expand Down Expand Up @@ -148,7 +148,7 @@ mod test {
#[test]
fn redirect_stdin_to_dev_null_precedence() {
let shell = Shell::Program("nu".to_owned());
let shell_builder = ShellBuilder::new(&shell);
let shell_builder = ShellBuilder::new(&shell, false);

let (program, args) = shell_builder
.redirect_stdin_to_dev_null()
Expand Down
6 changes: 3 additions & 3 deletions crates/terminal/src/terminal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2377,8 +2377,8 @@ mod tests {
cx.executor().allow_parking();

let (completion_tx, completion_rx) = smol::channel::unbounded();
let (program, args) =
ShellBuilder::new(&Shell::System).build(Some("echo".to_owned()), &["hello".to_owned()]);
let (program, args) = ShellBuilder::new(&Shell::System, false)
.build(Some("echo".to_owned()), &["hello".to_owned()]);
let terminal = cx.new(|cx| {
TerminalBuilder::new(
None,
Expand Down Expand Up @@ -2496,7 +2496,7 @@ mod tests {
cx.executor().allow_parking();

let (completion_tx, completion_rx) = smol::channel::unbounded();
let (program, args) = ShellBuilder::new(&Shell::System)
let (program, args) = ShellBuilder::new(&Shell::System, false)
.build(Some("asdasdasdasd".to_owned()), &["@@@@@".to_owned()]);
let terminal = cx.new(|cx| {
TerminalBuilder::new(
Expand Down
27 changes: 11 additions & 16 deletions crates/terminal_view/src/terminal_panel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -526,23 +526,18 @@ impl TerminalPanel {
window: &mut Window,
cx: &mut Context<Self>,
) -> Task<Result<WeakEntity<Terminal>>> {
let remote_client = self
.workspace
.update(cx, |workspace, cx| {
let project = workspace.project().read(cx);
if project.is_via_collab() {
Err(anyhow!("cannot spawn tasks as a guest"))
} else {
Ok(project.remote_client())
}
})
.flatten();

let remote_client = match remote_client {
Ok(remote_client) => remote_client,
Err(e) => return Task::ready(Err(e)),
let Some(workspace) = self.workspace.upgrade() else {
return Task::ready(Err(anyhow!("failed to read workspace")));
};

let project = workspace.read(cx).project().read(cx);

if project.is_via_collab() {
return Task::ready(Err(anyhow!("cannot spawn tasks as a guest")));
}

let remote_client = project.remote_client();
let is_windows = project.path_style(cx).is_windows();
let remote_shell = remote_client
.as_ref()
.and_then(|remote_client| remote_client.read(cx).shell());
Expand All @@ -555,7 +550,7 @@ impl TerminalPanel {
task.shell.clone()
};

let builder = ShellBuilder::new(&shell);
let builder = ShellBuilder::new(&shell, is_windows);
let command_label = builder.command_label(task.command.as_deref().unwrap_or(""));
let (command, args) = builder.build(task.command.clone(), &task.args);

Expand Down
18 changes: 8 additions & 10 deletions crates/util/src/shell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,18 +171,16 @@ impl fmt::Display for ShellKind {

impl ShellKind {
pub fn system() -> Self {
Self::new(&get_system_shell())
Self::new(&get_system_shell(), cfg!(windows))
}

pub fn new(program: impl AsRef<Path>) -> Self {
pub fn new(program: impl AsRef<Path>, is_windows: bool) -> Self {
let program = program.as_ref();
let Some(program) = program.file_stem().and_then(|s| s.to_str()) else {
return if cfg!(windows) {
ShellKind::PowerShell
} else {
ShellKind::Posix
};
};
let program = program
.file_stem()
.unwrap_or_else(|| program.as_os_str())
.to_string_lossy();

if program == "powershell" || program == "pwsh" {
ShellKind::PowerShell
} else if program == "cmd" {
Expand All @@ -200,7 +198,7 @@ impl ShellKind {
} else if program == "sh" || program == "bash" {
ShellKind::Posix
} else {
if cfg!(windows) {
if is_windows {
ShellKind::PowerShell
} else {
// Some other shell detected, the user might install and use a
Expand Down
4 changes: 2 additions & 2 deletions crates/util/src/shell_env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ async fn capture_unix(
use std::process::Stdio;

let zed_path = super::get_shell_safe_zed_path()?;
let shell_kind = ShellKind::new(shell_path);
let shell_kind = ShellKind::new(shell_path, false);

let mut command_string = String::new();
let mut command = std::process::Command::new(shell_path);
Expand Down Expand Up @@ -131,7 +131,7 @@ async fn capture_windows(
let zed_path =
std::env::current_exe().context("Failed to determine current zed executable path.")?;

let shell_kind = ShellKind::new(shell_path);
let shell_kind = ShellKind::new(shell_path, true);
let env_output = match shell_kind {
ShellKind::Posix | ShellKind::Csh | ShellKind::Tcsh | ShellKind::Rc | ShellKind::Fish => {
return Err(anyhow::anyhow!("unsupported shell kind"));
Expand Down
Loading