printable_shell_command/
command.rs

1use std::{process::Command, str::Utf8Error};
2
3use crate::{
4    ShellPrintable,
5    escape::{SimpleEscapeOptions, simple_escape},
6};
7
8impl ShellPrintable for Command {
9    fn printable_invocation_string_lossy(&self) -> String {
10        let mut lines: Vec<String> = vec![simple_escape(
11            &self.get_program().to_string_lossy(),
12            SimpleEscapeOptions { is_command: true },
13        )];
14        for arg in self.get_args() {
15            lines.push(simple_escape(
16                &arg.to_string_lossy(),
17                SimpleEscapeOptions { is_command: false },
18            ))
19        }
20        lines.join(
21            " \\
22  ",
23        )
24    }
25    fn printable_invocation_string(&self) -> Result<String, Utf8Error> {
26        let mut lines: Vec<String> = vec![simple_escape(
27            TryInto::<&str>::try_into(self.get_program())?,
28            SimpleEscapeOptions { is_command: true },
29        )];
30        for arg in self.get_args() {
31            lines.push(simple_escape(
32                TryInto::<&str>::try_into(arg)?,
33                SimpleEscapeOptions { is_command: false },
34            ))
35        }
36        Ok(lines.join(
37            " \\
38  ",
39        ))
40    }
41}
42
43#[cfg(test)]
44mod tests {
45    use std::process::Command;
46
47    use crate::ShellPrintable;
48
49    #[test]
50    fn echo() -> Result<(), String> {
51        let mut command = Command::new("echo");
52        command.args(["#hi"]);
53        // Not printed by tests, but we can at least check this doesn't panic.
54        let _ = command.print_invocation();
55
56        assert_eq!(
57            command.printable_invocation_string().unwrap(),
58            "echo \\
59  '#hi'"
60        );
61        Ok(())
62    }
63}