feat: Add more support for patterns and conditional match

This commit is contained in:
2025-01-11 15:52:13 -05:00
parent 0858e04c41
commit 820afa2171
3 changed files with 111 additions and 8 deletions

View File

@@ -64,7 +64,10 @@ enum LogicArg {
impl Parse for LogicArg {
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
if input.peek(Token![for]) {
if input.peek3(Token![in]) {
let pat_fork = input.fork();
_ = pat_fork.parse::<Token![for]>()?;
if pat_fork.call(syn::Pat::parse_single).is_ok() && pat_fork.peek(Token![in]) {
input.parse().map(Self::ForIn)
} else {
input.parse().map(Self::ForIter)
@@ -263,28 +266,54 @@ impl ToTokens for Match {
struct MatchArm {
pattern: syn::Pat,
if_expr: Option<Value>,
args: Arguments,
}
impl Parse for MatchArm {
fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
let pattern = input.call(syn::Pat::parse_multi)?;
let if_expr = if input.peek(Token![if]) {
_ = input.parse::<Token![if]>()?;
Some(input.parse()?)
} else {
None
};
_ = input.parse::<Token![=>]>()?;
let args = input.parse()?;
Ok(Self { pattern, args })
Ok(Self {
pattern,
if_expr,
args,
})
}
}
impl ToTokens for MatchArm {
fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
let Self { pattern, args } = self;
let Self {
pattern,
if_expr,
args,
} = self;
tokens.extend(quote! {
#pattern => {
#args
}
});
tokens.extend(if_expr.as_ref().map_or_else(
|| {
quote! {
#pattern => {
#args
}
}
},
|if_expr| {
quote! {
#pattern if #if_expr => {
#args
}
}
},
));
}
}

View File

@@ -86,6 +86,29 @@ mod cmd;
/// 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;