feat: Default env variables

This commit is contained in:
2025-04-06 14:21:17 -04:00
parent ac948f193b
commit a5d442f7ff
4 changed files with 103 additions and 3 deletions

View File

@@ -185,6 +185,27 @@ let command = cmd!(
assert_eq!(format!("{command:?}"), r#"NEW_VAR="new_var" TEST="test" "echo" "test""#); assert_eq!(format!("{command:?}"), r#"NEW_VAR="new_var" TEST="test" "echo" "test""#);
``` ```
#### Conditional
You can have a default value set for an environment variable.
```rust
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""#);
```
#### Current Directory and Env Variable Order Matters #### Current Directory and Env Variable Order Matters
Environment variable declarations **MUST** come after the current directory declaration. Environment variable declarations **MUST** come after the current directory declaration.

View File

@@ -437,24 +437,50 @@ impl ToTokens for EnvVars {
struct EnvVar { struct EnvVar {
key: Value, key: Value,
value: Value, value: Value,
conditional: bool,
} }
impl Parse for EnvVar { impl Parse for EnvVar {
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> { fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
let key = input.parse()?; let key = input.parse()?;
_ = input.parse::<Token![:]>()?; _ = input.parse::<Token![:]>()?;
let conditional = if input.lookahead1().peek(Token![?]) {
input.parse::<Token![?]>()?;
true
} else {
false
};
let value = input.parse()?; let value = input.parse()?;
Ok(Self { key, value }) Ok(Self {
key,
value,
conditional,
})
} }
} }
impl ToTokens for EnvVar { impl ToTokens for EnvVar {
fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
let Self { key, value } = self; let Self {
key,
value,
conditional,
} = self;
if *conditional {
tokens.extend(quote! {
if ::std::env::var(#key).ok().is_none() {
_c.env(#key, #value);
}
});
} else {
tokens.extend(quote! { _c.env(#key, #value); }); tokens.extend(quote! { _c.env(#key, #value); });
} }
}
} }
struct CurrentDir(Option<Value>); struct CurrentDir(Option<Value>);

View File

@@ -56,6 +56,26 @@ mod pipe;
/// assert_eq!(format!("{command:?}"), r#"NEW_VAR="new_var" TEST="test" "echo" "test""#); /// assert_eq!(format!("{command:?}"), r#"NEW_VAR="new_var" TEST="test" "echo" "test""#);
/// ``` /// ```
/// ///
/// #### Conditional
/// You can have a default value set for an environment variable.
///
/// ```rust
/// # use comlexr_macro::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""#);
/// ```
///
/// ### Current Directory and Environment Variable Order /// ### Current Directory and Environment Variable Order
/// ``` /// ```
/// # use comlexr_macro::cmd; /// # use comlexr_macro::cmd;

View File

@@ -1,6 +1,8 @@
extern crate comlexr; extern crate comlexr;
extern crate rstest; extern crate rstest;
use std::env;
use comlexr::cmd; use comlexr::cmd;
use rstest::rstest; use rstest::rstest;
@@ -35,6 +37,37 @@ fn env_vars() {
assert_eq!(format!("{command:?}"), r#"TEST="test" "echo" "test""#); assert_eq!(format!("{command:?}"), r#"TEST="test" "echo" "test""#);
} }
#[test]
fn conditional_env_vars() {
env::set_var("TEST", "realvalue");
env::set_var("TEST2", "won't see");
let command = cmd!(
env {
"TEST":? "test",
"TEST2": "test2"
};
"echo",
"test",
);
assert_eq!(format!("{command:?}"), r#"TEST2="test2" "echo" "test""#);
let command = cmd!(
env {
"TEST": "test",
"TEST2": "test2"
};
"echo",
"test",
);
assert_eq!(
format!("{command:?}"),
r#"TEST="test" TEST2="test2" "echo" "test""#
);
}
#[test] #[test]
fn cd_env_vars() { fn cd_env_vars() {
let command = cmd!( let command = cmd!(