@@ -1012,4 +1012,40 @@ mod tests {
"uname".to_string()
);
}
+
+ #[test]
+ fn test_try_quote_single_quote_paths() {
+ let path_with_quote = r"C:\Temp\O'Brien\repo";
+ let shlex_shells = [
+ ShellKind::Posix,
+ ShellKind::Fish,
+ ShellKind::Csh,
+ ShellKind::Tcsh,
+ ShellKind::Rc,
+ ShellKind::Xonsh,
+ ShellKind::Elvish,
+ ShellKind::Nushell,
+ ];
+
+ for shell_kind in shlex_shells {
+ let quoted = shell_kind.try_quote(path_with_quote).unwrap().into_owned();
+ assert_ne!(quoted, path_with_quote);
+ assert_eq!(
+ shlex::split("ed),
+ Some(vec![path_with_quote.to_string()])
+ );
+
+ if shell_kind == ShellKind::Nushell {
+ let prefixed = shell_kind.prepend_command_prefix("ed);
+ assert!(prefixed.starts_with('^'));
+ }
+ }
+
+ for shell_kind in [ShellKind::PowerShell, ShellKind::Pwsh] {
+ let quoted = shell_kind.try_quote(path_with_quote).unwrap().into_owned();
+ assert!(quoted.starts_with('\''));
+ assert!(quoted.ends_with('\''));
+ assert!(quoted.contains("O''Brien"));
+ }
+ }
}
@@ -141,6 +141,14 @@ async fn capture_windows(
std::env::current_exe().context("Failed to determine current zed executable path.")?;
let shell_kind = ShellKind::new(shell_path, true);
+ let directory_string = directory.display().to_string();
+ let zed_path_string = zed_path.display().to_string();
+ let quote_for_shell = |value: &str| {
+ shell_kind
+ .try_quote(value)
+ .map(|quoted| quoted.into_owned())
+ .unwrap_or_else(|| value.to_owned())
+ };
let mut cmd = crate::command::new_command(shell_path);
cmd.args(args);
let cmd = match shell_kind {
@@ -149,52 +157,54 @@ async fn capture_windows(
| ShellKind::Rc
| ShellKind::Fish
| ShellKind::Xonsh
- | ShellKind::Posix => cmd.args([
- "-l",
- "-i",
- "-c",
- &format!(
- "cd '{}'; '{}' --printenv",
- directory.display(),
- zed_path.display()
- ),
- ]),
- ShellKind::PowerShell | ShellKind::Pwsh => cmd.args([
- "-NonInteractive",
- "-NoProfile",
- "-Command",
- &format!(
- "Set-Location '{}'; & '{}' --printenv",
- directory.display(),
- zed_path.display()
- ),
- ]),
- ShellKind::Elvish => cmd.args([
- "-c",
- &format!(
- "cd '{}'; '{}' --printenv",
- directory.display(),
- zed_path.display()
- ),
- ]),
- ShellKind::Nushell => cmd.args([
- "-c",
- &format!(
- "cd '{}'; {}'{}' --printenv",
- directory.display(),
- shell_kind
- .command_prefix()
- .map(|prefix| prefix.to_string())
- .unwrap_or_default(),
- zed_path.display()
- ),
- ]),
+ | ShellKind::Posix => {
+ let quoted_directory = quote_for_shell(&directory_string);
+ let quoted_zed_path = quote_for_shell(&zed_path_string);
+ cmd.args([
+ "-l",
+ "-i",
+ "-c",
+ &format!("cd {}; {} --printenv", quoted_directory, quoted_zed_path),
+ ])
+ }
+ ShellKind::PowerShell | ShellKind::Pwsh => {
+ let quoted_directory = ShellKind::quote_pwsh(&directory_string);
+ let quoted_zed_path = ShellKind::quote_pwsh(&zed_path_string);
+ cmd.args([
+ "-NonInteractive",
+ "-NoProfile",
+ "-Command",
+ &format!(
+ "Set-Location {}; & {} --printenv",
+ quoted_directory, quoted_zed_path
+ ),
+ ])
+ }
+ ShellKind::Elvish => {
+ let quoted_directory = quote_for_shell(&directory_string);
+ let quoted_zed_path = quote_for_shell(&zed_path_string);
+ cmd.args([
+ "-c",
+ &format!("cd {}; {} --printenv", quoted_directory, quoted_zed_path),
+ ])
+ }
+ ShellKind::Nushell => {
+ let quoted_directory = quote_for_shell(&directory_string);
+ let quoted_zed_path = quote_for_shell(&zed_path_string);
+ let zed_command = shell_kind
+ .prepend_command_prefix("ed_zed_path)
+ .into_owned();
+ cmd.args([
+ "-c",
+ &format!("cd {}; {} --printenv", quoted_directory, zed_command),
+ ])
+ }
ShellKind::Cmd => cmd.args([
"/c",
"cd",
- &directory.display().to_string(),
+ &directory_string,
"&&",
- &zed_path.display().to_string(),
+ &zed_path_string,
"--printenv",
]),
}