use std::io::{self, Write};

pub fn shell_quote(value: &str) -> String {
    if value.is_empty() {
        return "''".to_owned();
    }

    let mut quoted = String::with_capacity(value.len() + 2);
    quoted.push('\'');
    for ch in value.chars() {
        if ch == '\'' {
            quoted.push_str("'\"'\"'");
        } else {
            quoted.push(ch);
        }
    }
    quoted.push('\'');
    quoted
}

pub fn write_assign_line<W: Write>(writer: &mut W, name: &str, value: &str) -> io::Result<()> {
    writeln!(writer, "{}={}", name, shell_quote(value))
}

pub fn write_export_line<W: Write>(writer: &mut W, name: &str, value: &str) -> io::Result<()> {
    write_assign_line(writer, name, value)?;
    writeln!(writer, "export {}", name)
}

pub fn write_set_argv_line<W: Write>(
    writer: &mut W,
    program: &str,
    args: &[String],
) -> io::Result<()> {
    write!(writer, "set -- {}", shell_quote(program))?;
    for arg in args {
        write!(writer, " {}", shell_quote(arg))?;
    }
    writer.write_all(b" \"$@\"\n")
}

#[cfg(test)]
mod tests {
    use super::shell_quote;

    #[test]
    fn quotes_single_quotes() {
        assert_eq!(shell_quote("a'b"), "'a'\"'\"'b'");
    }
}
