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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
/// Creates or modifies a `std::process::Command` adding args.
///
/// # Examples
/// ```
/// use blue_build_utils::cmd;
///
/// const NAME: &str = "Bob";
/// let mut command = cmd!("echo", "Hello world!");
/// cmd!(command, "This is Joe.", format!("And this is {NAME}"));
/// command.status().unwrap();
/// ```
#[macro_export]
macro_rules! cmd {
    ($command:expr) => {
        ::std::process::Command::new($command)
    };
    ($command:ident, $($tail:tt)*) => {
        $crate::cmd!(@ $command, $($tail)*)
    };
    ($command:expr, $($tail:tt)*) => {
        {
            let mut c = $crate::cmd!($command);
            $crate::cmd!(@ c, $($tail)*);
            c
        }
    };
    (@ $command:ident $(,)?) => { };
    (@ $command:ident, for $for_expr:expr $(, $($tail:tt)*)?) => {
        {
            for arg in $for_expr.iter() {
                $crate::cmd!($command, arg);
            }
            $($crate::cmd!(@ $command, $($tail)*);)*
        }
    };
    (@ $command:ident, for $iter:ident in $for_expr:expr => [ $($arg:expr),* $(,)? ] $(, $($tail:tt)*)?) => {
        {
            for $iter in $for_expr.iter() {
                $($crate::cmd!(@ $command, $arg);)*
            }
            $($crate::cmd!(@ $command, $($tail)*);)*
        }
    };
    (@ $command:ident, for $iter:ident in $for_expr:expr => $arg:expr $(, $($tail:tt)*)?) => {
        {
            for $iter in $for_expr.iter() {
                $crate::cmd!(@ $command, $arg);
            }
            $($crate::cmd!(@ $command, $($tail)*);)*
        }
    };
    (@ $command:ident, if let $let_pat:pat = $if_expr:expr => [ $($arg:expr),* $(,)? ] $(, $($tail:tt)*)?) => {
        {
            if let $let_pat = $if_expr {
                $($crate::cmd!(@ $command, $arg);)*
            }
            $($crate::cmd!(@ $command, $($tail)*);)*
        }
    };
    (@ $command:ident, if let $let_pat:pat = $if_expr:expr => $arg:expr $(, $($tail:tt)*)?) => {
        {
            if let $let_pat = $if_expr {
                $crate::cmd!(@ $command, $arg);
            }
            $($crate::cmd!(@ $command, $($tail)*);)*
        }
    };
    (@ $command:ident, if $if_expr:expr => [ $($arg:expr),* $(,)?] $(, $($tail:tt)*)?) => {
        {
            if $if_expr {
                $($crate::cmd!(@ $command, $arg);)*
            }
            $($crate::cmd!(@ $command, $($tail)*);)*
        }
    };
    (@ $command:ident, if $if_expr:expr => $arg:expr $(, $($tail:tt)*)?) => {
        {
            if $if_expr {
                $crate::cmd!(@ $command, $arg);
            }
            $($crate::cmd!(@ $command, $($tail)*);)*
        }
    };
    (@ $command:ident, |$cmd_ref:ident|? $op:block $(, $($tail:tt)*)?) => {
        {
            let op_fn = |$cmd_ref: &mut ::std::process::Command| -> Result<()>  {
                $op
                Ok(())
            };
            op_fn(&mut $command)?;
            $($crate::cmd!(@ $command, $($tail)*);)*
        }
    };
    (@ $command:ident, |$cmd_ref:ident| $op:block $(, $($tail:tt)*)?) => {
        {
            let op_fn = |$cmd_ref: &mut ::std::process::Command| $op;
            op_fn(&mut $command);
            $($crate::cmd!(@ $command, $($tail)*);)*
        }
    };
    (@ $command:ident, $key:expr => $value:expr $(, $($tail:tt)*)?) => {
        {
            $command.env($key, $value);
            $($crate::cmd!(@ $command, $($tail)*);)*
        }
    };
    (@ $command:ident, current_dir = $dir:expr $(, $($tail:tt)*)?) => {
        {
            $command.current_dir($dir);
            $($crate::cmd!(@ $command, $($tail)*);)*
        }
    };
    (@ $command:ident, stdin = $pipe:expr $(, $($tail:tt)*)?) => {
        {
            $command.stdin($pipe);
            $($crate::cmd!(@ $command, $($tail)*);)*
        }
    };
    (@ $command:ident, stdout = $pipe:expr $(, $($tail:tt)*)?) => {
        {
            $command.stdout($pipe);
            $($crate::cmd!(@ $command, $($tail)*);)*
        }
    };
    (@ $command:ident, stderr = $pipe:expr $(, $($tail:tt)*)?) => {
        {
            $command.stderr($pipe);
            $($crate::cmd!(@ $command, $($tail)*);)*
        }
    };
    (@ $command:ident, $arg:expr $(, $($tail:tt)*)?) => {
        {
            $command.arg($arg);
            $($crate::cmd!(@ $command, $($tail)*);)*
        }
    };
}

#[macro_export]
macro_rules! string {
    ($str:expr) => {
        String::from($str)
    };
}

#[macro_export]
macro_rules! string_vec {
    ($($string:expr),+ $(,)?) => {
        {
            use $crate::string;
            vec![
                $($crate::string!($string),)*
            ]
        }
    };
}