use std::path::PathBuf;
pub fn quote(s: &str) -> String {
if cfg!(windows) {
return format!("\"{s}\"");
}
let mut out = String::with_capacity(s.len() + 2);
out.push('\'');
for ch in s.chars() {
if ch == '\'' {
out.push_str("'\\''");
} else {
out.push(ch);
}
}
out.push('\'');
out
}
pub fn invocation(bin: &str, config_paths: &[PathBuf], account: Option<&str>) -> String {
let mut invocation = String::from(bin);
for path in config_paths {
invocation.push_str(" -c ");
invocation.push_str("e(&path.to_string_lossy()));
}
if let Some(name) = account.filter(|name| !name.is_empty()) {
invocation.push_str(" -a ");
invocation.push_str("e(name));
}
invocation
}
#[cfg(test)]
mod tests {
use std::path::PathBuf;
use crate::shell;
#[test]
#[cfg(not(windows))]
fn quote_escapes_embedded_quotes() {
assert_eq!(shell::quote("plain"), "'plain'");
assert_eq!(shell::quote("a;b"), "'a;b'");
assert_eq!(shell::quote("it's"), "'it'\\''s'");
}
#[test]
#[cfg(not(windows))]
fn invocation_carries_the_account_and_config() {
assert_eq!(shell::invocation("app", &[], None), "app");
assert_eq!(shell::invocation("app", &[], Some("")), "app");
assert_eq!(shell::invocation("app", &[], Some("mail")), "app -a 'mail'");
let paths = [PathBuf::from("/a.toml"), PathBuf::from("/b c.toml")];
assert_eq!(
shell::invocation("app", &paths, Some("work's")),
"app -c '/a.toml' -c '/b c.toml' -a 'work'\\''s'"
);
}
}