Codex Handbook
core/src/shell.rs 104 lines
use codex_exec_server::ShellInfo;use codex_shell_command::shell_detect::DetectedShell;use serde::Deserialize;use serde::Serialize;use std::path::PathBuf;pub use codex_shell_command::shell_detect::ShellType;#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]pub struct Shell {    pub(crate) shell_type: ShellType,    pub(crate) shell_path: PathBuf,}impl Shell {    pub fn name(&self) -> &'static str {        self.shell_type.name()    }    /// Takes a string of shell and returns the full list of command args to    /// use with `exec()` to run the shell command.    pub fn derive_exec_args(&self, command: &str, use_login_shell: bool) -> Vec<String> {        match self.shell_type {            ShellType::Zsh | ShellType::Bash | ShellType::Sh => {                let arg = if use_login_shell { "-lc" } else { "-c" };                vec![                    self.shell_path.to_string_lossy().to_string(),                    arg.to_string(),                    command.to_string(),                ]            }            ShellType::PowerShell => {                let mut args = vec![self.shell_path.to_string_lossy().to_string()];                if !use_login_shell {                    args.push("-NoProfile".to_string());                }                args.push("-Command".to_string());                args.push(command.to_string());                args            }            ShellType::Cmd => {                let mut args = vec![self.shell_path.to_string_lossy().to_string()];                args.push("/c".to_string());                args.push(command.to_string());                args            }        }    }}impl From<DetectedShell> for Shell {    fn from(detected: DetectedShell) -> Self {        Self {            shell_type: detected.shell_type,            shell_path: detected.shell_path,        }    }}impl Shell {    pub(crate) fn from_environment_shell_info(shell_info: ShellInfo) -> anyhow::Result<Self> {        let shell_type = match shell_info.name.as_str() {            "zsh" => ShellType::Zsh,            "bash" => ShellType::Bash,            "powershell" => ShellType::PowerShell,            "sh" => ShellType::Sh,            "cmd" => ShellType::Cmd,            name => anyhow::bail!("unknown environment shell `{name}`"),        };        Ok(Self {            shell_type,            shell_path: PathBuf::from(shell_info.path),        })    }}#[cfg(all(test, unix))]fn ultimate_fallback_shell() -> Shell {    codex_shell_command::shell_detect::ultimate_fallback_shell().into()}pub fn get_shell_by_model_provided_path(shell_path: &PathBuf) -> Shell {    codex_shell_command::shell_detect::get_shell_by_model_provided_path(shell_path).into()}pub fn get_shell(shell_type: ShellType, path: Option<&PathBuf>) -> Option<Shell> {    codex_shell_command::shell_detect::get_shell(shell_type, path).map(Into::into)}pub fn default_user_shell() -> Shell {    codex_shell_command::shell_detect::default_user_shell().into()}#[cfg(all(test, target_os = "macos"))]fn default_user_shell_from_path(user_shell_path: Option<PathBuf>) -> Shell {    codex_shell_command::shell_detect::default_user_shell_from_path(user_shell_path).into()}#[cfg(test)]#[cfg(unix)]#[path = "shell_tests.rs"]mod tests;