terminal: Escape strings with backticks rather than backslashes in PowerShell (#39657)

Closes #39007 

Strings should be escaped with backticks in PowerShell, so the following

```
\"pwsh.exe -C pytest -m \\\"some_test\\\"\"
```

becomes

```
\"pwsh.exe -C pytest -m `\"some_test`\"\"
```

Otherwise PowerShell will misinterpret the invocation resulting in
weirdness all-around such as the issue linked above.

Release Notes:

- N/A
This commit is contained in:
Jakub Konka
2025-10-07 19:30:09 +02:00
committed by GitHub
parent d04ac864b8
commit 3106472bf3
2 changed files with 15 additions and 3 deletions
+3 -2
View File
@@ -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
+12 -1
View File
@@ -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,
})
}
}