diff --git a/crates/languages/src/python.rs b/crates/languages/src/python.rs index e602aec841c0e734d12e9873f0cd3ad3e116b2e6..2ac4a5b9f543576944e1ce30b52593afaef8d34a 100644 --- a/crates/languages/src/python.rs +++ b/crates/languages/src/python.rs @@ -1189,6 +1189,7 @@ impl ToolchainLister for PythonToolchainProvider { ShellKind::Nushell => "activate.nu", ShellKind::PowerShell => "activate.ps1", ShellKind::Cmd => "activate.bat", + ShellKind::Xonsh => "activate.xsh", }; let path = prefix.join(BINARY_DIR).join(activate_script_name); @@ -1215,6 +1216,7 @@ impl ToolchainLister for PythonToolchainProvider { ShellKind::Tcsh => None, ShellKind::Cmd => None, ShellKind::Rc => None, + ShellKind::Xonsh => None, }) } _ => {} diff --git a/crates/task/src/shell_builder.rs b/crates/task/src/shell_builder.rs index a32e016df1f8b0650fd0c0b6dfddeb382dde48b8..520c04e367b2407fa98f84cabc6564d9003e309f 100644 --- a/crates/task/src/shell_builder.rs +++ b/crates/task/src/shell_builder.rs @@ -56,7 +56,8 @@ impl ShellBuilder { | ShellKind::Fish | ShellKind::Csh | ShellKind::Tcsh - | ShellKind::Rc => { + | ShellKind::Rc + | ShellKind::Xonsh => { let interactivity = self.interactive.then_some("-i ").unwrap_or_default(); format!( "{PROGRAM} {interactivity}-c '{command_to_use_in_label}'", @@ -91,7 +92,8 @@ impl ShellBuilder { | ShellKind::Fish | ShellKind::Csh | ShellKind::Tcsh - | ShellKind::Rc => { + | ShellKind::Rc + | ShellKind::Xonsh => { combined_command.insert(0, '('); combined_command.push_str(") String { @@ -165,6 +166,7 @@ impl fmt::Display for ShellKind { ShellKind::Nushell => write!(f, "nu"), ShellKind::Cmd => write!(f, "cmd"), ShellKind::Rc => write!(f, "rc"), + ShellKind::Xonsh => write!(f, "xonsh"), } } } @@ -197,6 +199,8 @@ impl ShellKind { ShellKind::Tcsh } else if program == "rc" { ShellKind::Rc + } else if program == "xonsh" { + ShellKind::Xonsh } else if program == "sh" || program == "bash" { ShellKind::Posix } else { @@ -220,6 +224,7 @@ impl ShellKind { Self::Tcsh => input.to_owned(), Self::Rc => input.to_owned(), Self::Nushell => Self::to_nushell_variable(input), + Self::Xonsh => input.to_owned(), } } @@ -345,7 +350,8 @@ impl ShellKind { | ShellKind::Fish | ShellKind::Csh | ShellKind::Tcsh - | ShellKind::Rc => interactive + | ShellKind::Rc + | ShellKind::Xonsh => interactive .then(|| "-i".to_owned()) .into_iter() .chain(["-c".to_owned(), combined_command]) @@ -387,6 +393,7 @@ impl ShellKind { ShellKind::Csh => "source", ShellKind::Tcsh => "source", ShellKind::Posix | ShellKind::Rc => "source", + ShellKind::Xonsh => "source", } } diff --git a/crates/util/src/shell_env.rs b/crates/util/src/shell_env.rs index 3559bf2c78d48545afa1c299d43d220957349dc4..9d097d91658d69e420599856ef67efe22f685d4d 100644 --- a/crates/util/src/shell_env.rs +++ b/crates/util/src/shell_env.rs @@ -46,10 +46,14 @@ async fn capture_unix( // See: https://github.com/zed-industries/zed/pull/32136#issuecomment-2999645482 const FD_STDIN: std::os::fd::RawFd = 0; const FD_STDOUT: std::os::fd::RawFd = 1; + const FD_STDERR: std::os::fd::RawFd = 2; let (fd_num, redir) = match shell_kind { ShellKind::Rc => (FD_STDIN, format!(">[1={}]", FD_STDIN)), // `[1=0]` ShellKind::Nushell | ShellKind::Tcsh => (FD_STDOUT, "".to_string()), + // xonsh doesn't support redirecting to stdin, and control sequences are printed to + // stdout on startup + ShellKind::Xonsh => (FD_STDERR, "o>e".to_string()), _ => (FD_STDIN, format!(">&{}", FD_STDIN)), // `>&0` }; command.stdin(Stdio::null()); @@ -133,7 +137,12 @@ async fn capture_windows( let shell_kind = ShellKind::new(shell_path); let env_output = match shell_kind { - ShellKind::Posix | ShellKind::Csh | ShellKind::Tcsh | ShellKind::Rc | ShellKind::Fish => { + ShellKind::Posix + | ShellKind::Csh + | ShellKind::Tcsh + | ShellKind::Rc + | ShellKind::Fish + | ShellKind::Xonsh => { return Err(anyhow::anyhow!("unsupported shell kind")); } ShellKind::PowerShell => {