Crates.io | comlexr |
lib.rs | comlexr |
version | 1.3.1 |
source | src |
created_at | 2025-01-11 05:28:27.373037 |
updated_at | 2025-01-31 03:02:34.32056 |
description | Dynamically build Command objects with conditional expressions |
homepage | |
repository | https://gitlab.com/wunker-bunker/comlexr |
max_upload_size | |
id | 1512168 |
size | 26,102 |
comlexr
is a Rust procedural macro crate designed to simplify command expression generation by using flexible syntax constructs. It allows you to dynamically build command-line instructions based on conditional statements, loops, pattern matching, closures, and more.
Add comlexr
to your project's Cargo.toml
:
[dependencies]
comlexr = "1.3.1"
The minimum supported Rust version is 1.60.0
for broader support.
Create simple command expressions using the cmd!
macro.
use comlexr::cmd;
let command = cmd!("echo", "test");
assert_eq!(format!("{command:?}"), r#""echo" "test""#.to_string());
Use if
statements to conditionally include arguments.
use comlexr::cmd;
let single = true;
let multi = false;
let command = cmd!(
"echo",
"test",
if single => "single",
if multi => [
"multi",
"arg",
],
);
assert_eq!(format!("{command:?}"), r#""echo" "test" "single""#.to_string());
Use if let
syntax to conditionally include arguments based on pattern matching.
use comlexr::cmd;
let single_option = Some("single");
let multi_option: Option<&str> = None;
let command = cmd!(
"echo",
"test",
if let Some(arg) = single_option => arg,
if let Some(arg) = multi_option => [
"multi",
arg,
],
);
assert_eq!(format!("{command:?}"), r#""echo" "test" "single""#.to_string());
Use the for
syntax to iterate over collections and include multiple arguments.
use comlexr::cmd;
let iter = &["1", "2"];
let command = cmd!(
"echo",
"test",
for iter,
);
assert_eq!(format!("{command:?}"), r#""echo" "test" "1" "2""#.to_string());
for in
Leverage the for in
syntax to map collection elements to arguments dynamically.
use comlexr::cmd;
let single_iter = &["arg1", "arg2"];
let multi_iter = &["multi1", "multi2"];
let command = cmd!(
"echo",
"test",
for arg in single_iter => arg,
for arg in multi_iter => [
"multi",
arg,
],
);
assert_eq!(format!("{command:?}"), r#""echo" "test" "arg1" "arg2" "multi" "multi1" "multi" "multi2""#.to_string());
match
Dynamically choose arguments based on pattern matching.
use comlexr::cmd;
enum TestArgs {
Arg1,
Arg2,
Arg3,
}
let match_arg = TestArgs::Arg2;
let command = cmd!(
"echo",
"test",
match match_arg {
TestArgs::Arg1 => "arg1",
TestArgs::Arg2 => ["arg1", "arg2"],
TestArgs::Arg3 => ["arg1", "arg2", "arg3"],
}
);
assert_eq!(format!("{command:?}"), r#""echo" "test" "arg1" "arg2""#.to_string());
Generate arguments on the fly using closures. The closure must return a type that implements IntoIterator
.
use comlexr::cmd;
let arr = vec![1, 2, 3];
let input = 2;
let command = cmd!(
"echo",
"test",
|| arr.into_iter().map(|i| format!("{}", i * input))
);
assert_eq!(format!("{command:?}"), r#""echo" "test" "2" "4" "6""#.to_string());
Specify the directory to run the command.
use comlexr::cmd;
let command = cmd!(
cd "~/";
"echo",
"test",
);
assert_eq!(format!("{command:?}"), r#"cd "~/" && "echo" "test""#);
Set environment variables for the command.
use comlexr::cmd;
const NEW_VAR: &str = "NEW_VAR";
let command = cmd!(
env {
"TEST": "test",
NEW_VAR: "new_var"
};
"echo",
"test",
);
assert_eq!(format!("{command:?}"), r#"NEW_VAR="new_var" TEST="test" "echo" "test""#);
Environment variable declarations MUST come after the current directory declaration.
use comlexr::cmd;
let command = cmd!(
cd "~/";
env {
"TEST": "test",
};
"echo",
"test",
);
assert_eq!(
format!("{command:?}"),
r#"cd "~/" && TEST="test" "echo" "test""#
);
When using the pipe
feature, you can make use of pipe!
to chain the stdout of commands to stdin. Execution is lazy so commands aren't run until status()
or output()
is called.
use comlexr::{pipe, cmd};
let dir = tempfile::tempdir().unwrap();
let file = dir.path().join("out");
let mut pipe = pipe!(cmd!("echo", "test") | cmd!("tee", &file));
let status = pipe.status().unwrap();
assert!(status.success());
You can also send data to the stdin of the first command in the chain.
use comlexr::{pipe, cmd};
let mut pipe = pipe!(stdin = "test"; cmd!("sed", "s|e|oa|"));
let output = pipe.output().unwrap();
assert!(output.status.success());
assert_eq!(String::from_utf8_lossy(&output.stdout), "toast");
if
, if let
)for
, for in
)match
)See the tests directory for more examples on how to use comlexr
effectively in your project.
This project is licensed under the MIT License.