use super::pty_core::pty_types::PtyCommand;
use std::path::PathBuf;
#[derive(Debug)]
pub struct PtyCommandBuilder {
command: String,
args: Vec<String>,
cwd: Option<PathBuf>,
env_vars: Vec<(String, String)>,
}
impl PtyCommandBuilder {
pub fn new(command: impl Into<String>) -> Self {
Self {
command: command.into(),
args: Vec::new(),
cwd: None,
env_vars: Vec::new(),
}
}
#[must_use]
pub fn args(mut self, args: impl IntoIterator<Item = impl Into<String>>) -> Self {
self.args.extend(args.into_iter().map(Into::into));
self
}
#[must_use]
pub fn cwd(mut self, path: impl Into<PathBuf>) -> Self {
self.cwd = Some(path.into());
self
}
#[must_use]
pub fn env(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
self.env_vars.push((key.into(), value.into()));
self
}
#[must_use]
pub fn enable_osc_sequences(self) -> Self {
if std::env::var("WT_SESSION").is_ok() {
self
} else if std::env::var("ConEmuANSI").ok() == Some("ON".into()) {
self
} else {
self.env("TERM_PROGRAM", "WezTerm")
}
}
pub fn build(mut self) -> miette::Result<PtyCommand> {
if self.cwd.is_none() {
let current_dir = std::env::current_dir()
.map_err(|e| miette::miette!("Failed to get current directory: {}", e))?;
self = self.cwd(current_dir);
}
let mut cmd_to_return = PtyCommand::new(&self.command);
for arg in &self.args {
cmd_to_return.arg(arg);
}
let cwd = self.cwd.unwrap_or_else(|| {
unreachable!("Working directory must be set - we ensure this above")
});
cmd_to_return.cwd(cwd);
for (key, value) in &self.env_vars {
tracing::debug!("Applying user env var: {}={}", key, value);
cmd_to_return.env(key, value);
}
Ok(cmd_to_return)
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::env;
#[test]
fn test_pty_command_builder_new() {
let builder = PtyCommandBuilder::new("test");
assert_eq!(builder.command, "test");
assert!(builder.args.is_empty());
assert!(builder.cwd.is_none());
assert!(builder.env_vars.is_empty());
}
#[test]
fn test_pty_command_builder_args() {
let builder = PtyCommandBuilder::new("test").args(["arg1", "arg2"]);
assert_eq!(builder.args, vec!["arg1", "arg2"]);
}
#[test]
fn test_pty_command_builder_cwd() {
let path = env::temp_dir();
let builder = PtyCommandBuilder::new("test").cwd(&path);
assert_eq!(builder.cwd, Some(path));
}
#[test]
fn test_pty_command_builder_env() {
let builder = PtyCommandBuilder::new("test")
.env("KEY1", "value1")
.env("KEY2", "value2");
assert_eq!(
builder.env_vars,
vec![
("KEY1".to_string(), "value1".to_string()),
("KEY2".to_string(), "value2".to_string())
]
);
}
#[test]
fn test_pty_command_builder_build() {
let builder = PtyCommandBuilder::new("ls")
.args(["-la", "-h"])
.env("TEST_VAR", "test_value");
let result = builder.build();
assert!(result.is_ok());
let _pty_command = result.unwrap();
}
#[test]
fn test_pty_command_builder_build_with_cwd() {
let temp_dir = env::temp_dir();
let builder = PtyCommandBuilder::new("test").cwd(&temp_dir);
let result = builder.build();
assert!(result.is_ok());
}
#[test]
fn test_pty_command_builder_chaining() {
let builder = PtyCommandBuilder::new("cargo")
.args(["build", "--release"])
.cwd(env::current_dir().unwrap())
.env("CARGO_TERM_COLOR", "always")
.enable_osc_sequences();
let result = builder.build();
assert!(result.is_ok());
}
}