| Crates.io | comlexr |
| lib.rs | comlexr |
| version | 1.4.2 |
| created_at | 2025-01-11 05:28:27.373037+00 |
| updated_at | 2025-05-18 16:54:06.380156+00 |
| description | Dynamically build Command objects with conditional expressions |
| homepage | |
| repository | https://gitlab.com/wunker-bunker/comlexr |
| max_upload_size | |
| id | 1512168 |
| size | 43,206 |
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.4.2"
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 inLeverage 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());
matchDynamically 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""#);
You can have a default value set for an environment variable.
use comlexr::cmd;
const NEW_VAR: &str = "NEW_VAR";
std::env::set_var("TEST", "realvalue");
let command = cmd!(
env {
"TEST":? "test",
NEW_VAR: "new_var"
};
"echo",
"test",
);
assert_eq!(format!("{command:?}"), r#"NEW_VAR="new_var" "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.