#[cfg(feature = "ok")]
pub mod ok;
#[cfg(feature = "opt_arg")]
pub mod opt_arg;
#[cfg(feature = "output")]
pub mod output;
pub mod args;
#[doc(hidden)]
pub mod internal {
#[macro_export]
macro_rules! cmd_partial {
((var($e:ident))) => {
std::env::var(stringify!($e)).unwrap_or_default()
};
($e:ident) => {
stringify!($e)
};
($e:expr) => {
#[allow(unused_parens)]
$e
};
($e:tt) => {
stringify!($e)
};
}
#[macro_export]
macro_rules! arg {
($x:ident; (var($e:ident))) => {
$x.arg(std::env::var(stringify!($e)).unwrap_or_default())
};
($x:ident; ($f:tt $e:tt?)) => {{
$x.opt_arg(($crate::internal::cmd_partial!($f), $e))
}};
($x:ident; ($e:tt?)) => {{
$x.opt_arg($e)
}};
($x:ident; ($e:tt..)) => {
$x.args($e)
};
($x:ident; $e:tt) => {
$x.arg($crate::internal::cmd_partial!($e))
};
}
pub use arg;
pub use cmd_partial;
}
#[macro_export]
macro_rules! run {
($app:tt $($q:tt)*) => {
$crate::cmd!($app $($q)*).output()
}
}
#[macro_export]
macro_rules! exec {
($app:tt $($q:tt)*) => {
$crate::cmd!($app $($q)*).status()
}
}
#[macro_export]
macro_rules! spawn {
($app:tt $($q:tt)*) => {
$crate::cmd!($app $($q)*).spawn()
}
}
#[macro_export]
macro_rules! cmd {
($app:tt $($q:tt)*) => {
{
let mut x = std::process::Command::new($crate::internal::cmd_partial!($app));
$($crate::internal::arg!(x; $q);)*
x
}
};
}
#[cfg(test)]
mod test {
use std::env;
use crate::output::OutputExt;
use crate::run;
#[test]
fn hello_world() {
run!(echo "Hello World!").unwrap();
}
#[test]
fn path() {
env::set_var("MY_VAR", "my_value");
assert_eq!("my_value", run!(echo(var(MY_VAR))).unwrap().stdout_lossy());
}
#[test]
fn hello_world_array() {
let worlds = ["overworld", "nether", "end"];
let result = run!(echo Hello (worlds..)).unwrap();
assert_eq!("Hello overworld nether end", result.stdout().unwrap())
}
#[test]
fn interpolate() {
let name = "Steve";
let result = run!(echo Hello (name)).unwrap();
assert_eq!(format!("Hello {name}"), result.stdout().unwrap());
}
#[test]
fn interpolate_option() {
use crate::opt_arg::OptionalArgExtension;
let name = Some("Steve");
let result = run!(echo Hello (name?)).unwrap();
assert_eq!(format!("Hello Steve"), result.stdout().unwrap());
}
#[test]
fn interpolate_option_flag_some() {
use crate::opt_arg::OptionalArgExtension;
let name = Some("Steve");
let result = run!(echo Hello ("Lord" name ?)).unwrap();
assert_eq!(format!("Hello Lord Steve"), result.stdout().unwrap());
}
#[test]
fn interpolate_option_flag_none() {
use crate::opt_arg::OptionalArgExtension;
let name: Option<String> = None;
let result = run!(echo Hello ("Lord" name ?)).unwrap();
assert_eq!("Hello", result.stdout().unwrap());
}
#[test]
fn interpolate_option_flag_list() {
use crate::opt_arg::OptionalArgExtension;
let packages = vec!["cowsay", "emacs"];
let result = run!(echo Installing ("-p" packages ?)).unwrap();
assert_eq!("Installing -p cowsay emacs", result.stdout().unwrap());
}
#[test]
fn interpolate_option_flag_list_empty() {
use crate::opt_arg::OptionalArgExtension;
let packages: Vec<&str> = vec![];
let result = run!(echo Installing ("-p" packages ?)).unwrap();
assert_eq!("Installing", result.stdout().unwrap());
}
}