feat: Pipe

This commit is contained in:
2025-01-29 00:04:00 -05:00
parent 6fa4b21c4f
commit 9d944c3218
15 changed files with 888 additions and 235 deletions

View File

@@ -1,177 +1,8 @@
#![doc = include_str!("../README.md")]
extern crate quote;
extern crate syn;
extern crate comlexr_macro;
use quote::quote;
use syn::parse_macro_input;
pub use comlexr_macro::*;
pub use pipe::*;
mod cmd;
/// Generates a command expression by combining static strings, conditional logic, loops,
/// pattern matching, and closures to dynamically build and format command-line arguments.
///
/// The `cmd!` macro supports flexible syntax constructs such as:
/// - **Static arguments**: Basic string arguments.
/// - **Conditional inclusion**: Using `if` or `if let` to conditionally include arguments.
/// - **Iterative inclusion**: Using `for` loops to include multiple arguments from collections.
/// - **Pattern matching**: Using `match` expressions for dynamic argument selection.
/// - **Closures**: Dynamically generating arguments at runtime.
///
/// # Examples
///
/// ## Basic Usage
/// ```
/// use comlexr::cmd;
///
/// let command = cmd!("echo", "test");
/// assert_eq!(format!("{command:?}"), r#""echo" "test""#.to_string());
/// ```
///
/// ## Current Directory
/// ```
/// use comlexr::cmd;
///
/// let command = cmd!(
/// cd "~/";
/// "echo",
/// "test",
/// );
///
/// assert_eq!(format!("{command:?}"), r#"cd "~/" && "echo" "test""#);
/// ```
///
/// ## Environment Vars
/// ```
/// 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""#);
/// ```
///
/// ### Current Directory and Environment Variable Order
/// ```
/// use comlexr::cmd;
///
/// let command = cmd!(
/// cd "~/";
/// env {
/// "TEST": "test",
/// };
/// "echo",
/// "test",
/// );
///
/// assert_eq!(
/// format!("{command:?}"),
/// r#"cd "~/" && TEST="test" "echo" "test""#
/// );
///
/// ```
///
/// ## Conditional Arguments
/// ```
/// use comlexr::cmd;
///
/// let include_arg = true;
///
/// let command = cmd!("echo", "test", if include_arg => "optional_arg");
/// assert_eq!(format!("{command:?}"), r#""echo" "test" "optional_arg""#.to_string());
/// ```
///
/// ## Conditional 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());
/// ```
///
/// ## Iterative Argument Inclusion
/// ```
/// use comlexr::cmd;
///
/// let args = &["arg1", "arg2"];
///
/// let command = cmd!("echo", for args);
/// assert_eq!(format!("{command:?}"), r#""echo" "arg1" "arg2""#.to_string());
/// ```
///
/// ## Iteration with `for in`
/// ```
/// 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 Statements
/// ```
/// 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());
/// ```
///
/// ## Dynamic Closures
/// ```
/// use comlexr::cmd;
///
/// let numbers = vec![1, 2, 3];
/// let multiplier = 2;
///
/// let command = cmd!("echo", || numbers.into_iter().map(|n| format!("{}", n * multiplier)));
/// assert_eq!(format!("{command:?}"), r#""echo" "2" "4" "6""#.to_string());
/// ```
#[proc_macro]
pub fn cmd(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let command = parse_macro_input!(input as cmd::Command);
quote! { #command }.into()
}
mod pipe;