1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
//! Crate to easily run system/shell commands across different platforms, similar to the C `system` command.

use std::{
    io,
    process::{Command, Output},
};

#[cfg(target_os = "windows")]
use std::os::windows::process::CommandExt;

/// Trait to allow for the creation of system commands.
pub trait System<T> {
    fn system(command: &str) -> T;
}

impl System<Command> for Command {
    #[cfg(target_os = "windows")]
    /// Construct a new [Command] that runs the given system command when executed.
    ///
    /// See [Command::new] for the default configuration.
    ///
    /// # Example
    ///
    /// ```rust
    /// use std::process::Command;
    ///
    /// use system::System;
    ///
    /// fn main() {
    ///     let out = Command::system("echo Hello, world!")
    ///         .output()
    ///         .expect("Failed to run command.");
    ///
    ///     #[cfg(target_os = "windows")]
    ///     assert_eq!(String::from_utf8_lossy(&out.stdout), "Hello, world!\r\n");
    ///
    ///     #[cfg(not(target_os = "windows"))]
    ///     assert_eq!(String::from_utf8_lossy(&out.stdout), "Hello, world!\n");
    /// }
    /// ```
    fn system(command: &str) -> Command {
        let mut rust_command = Command::new("cmd");
        rust_command.arg("/c");
        rust_command.raw_arg(&command);
        return rust_command;
    }

    #[cfg(not(target_os = "windows"))]
    /// Construct a new [Command] that runs the given system command when executed.
    ///
    /// See [Command::new] for the default configuration.
    ///
    /// # Example
    ///
    /// ```rust
    /// use std::process::Command;
    ///
    /// use system::System;
    ///
    /// fn main() {
    ///     let out = Command::system("echo Hello, world!")
    ///         .output()
    ///         .expect("Failed to run command.");
    ///
    ///     #[cfg(target_os = "windows")]
    ///     assert_eq!(String::from_utf8_lossy(&out.stdout), "Hello, world!\r\n");
    ///
    ///     #[cfg(not(target_os = "windows"))]
    ///     assert_eq!(String::from_utf8_lossy(&out.stdout), "Hello, world!\n");
    /// }
    /// ```
    fn system(command: &str) -> Command {
        let mut rust_command = Command::new("sh");
        rust_command.arg("-c");
        rust_command.arg(&command);
        return rust_command;
    }
}

/// Run a system/shell command and return the [Output].
///
/// # Example
/// use system::system;
///
/// ```rust
/// fn main() {
///     let out = system("echo Hello, world!").expect("Failed to run command.");
///
///     #[cfg(target_os = "windows")]
///     assert_eq!(String::from_utf8_lossy(&out.stdout), "Hello, world!\r\n");
///
///     #[cfg(not(target_os = "windows"))]
///     assert_eq!(String::from_utf8_lossy(&out.stdout), "Hello, world!\n");
/// ```
pub fn system(command: &str) -> io::Result<Output> {
    Command::system(command).output()
}