@@ -145,7 +145,7 @@ impl Project {
project.update(cx, move |this, cx| {
let format_to_run = || {
if let Some(command) = &spawn_task.command {
- let mut command: Option<Cow<str>> = shlex::try_quote(command).ok();
+ let mut command: Option<Cow<str>> = shell_kind.try_quote(command);
if let Some(command) = &mut command
&& command.starts_with('"')
&& let Some(prefix) = shell_kind.command_prefix()
@@ -156,7 +156,8 @@ impl Project {
let args = spawn_task
.args
.iter()
- .filter_map(|arg| shlex::try_quote(arg).ok());
+ .filter_map(|arg| shell_kind.try_quote(&arg));
+
command.into_iter().chain(args).join(" ")
} else {
// todo: this breaks for remotes to windows
@@ -1,4 +1,4 @@
-use std::{fmt, path::Path, sync::LazyLock};
+use std::{borrow::Cow, fmt, path::Path, sync::LazyLock};
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
pub enum ShellKind {
@@ -241,6 +241,7 @@ impl ShellKind {
input.into()
}
}
+
fn to_powershell_variable(input: &str) -> String {
if let Some(var_str) = input.strip_prefix("${") {
if var_str.find(':').is_none() {
@@ -359,4 +360,14 @@ impl ShellKind {
_ => None,
}
}
+
+ pub fn try_quote<'a>(&self, arg: &'a str) -> Option<Cow<'a, str>> {
+ shlex::try_quote(arg).ok().map(|arg| match self {
+ // If we are running in PowerShell, we want to take extra care when escaping strings.
+ // In particular, we want to escape strings with a backtick (`) rather than a backslash (\).
+ // TODO double escaping backslashes is not necessary in PowerShell and probably CMD
+ ShellKind::PowerShell => Cow::Owned(arg.replace("\\\"", "`\"")),
+ _ => arg,
+ })
+ }
}