Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support "format nodes"? #9

Closed
anp opened this issue Jan 2, 2021 · 6 comments
Closed

Support "format nodes"? #9

anp opened this issue Jan 2, 2021 · 6 comments
Labels
enhancement New feature or request

Comments

@anp
Copy link

anp commented Jan 2, 2021

I'm currently reviewing a PR that moves https://docs.rs/mox from snax to syn-rsx and I quite like most of what we get out of the change. One thing we're having to give up, though, is the ability to add sigils to the delimiters of expressions we parse in order to have a shorthand for string formatters, like this:

let button = mox! {
    <button onclick={move |_| set_value.update(|n| Some(n + 1))}>
        {% "{} ({})", text, value }
    </button>
};

I chose {% ... } for the delimiters because it was (a) easy enough to implement with snax, (b) didn't collide with other common rust sigils and (c) reminded me of python's formatter sigil. Definitely open to alternative ways of spelling it out.

With the switch to syn-rsx, the above becomes:

let button = mox! {
    <button onclick = move |_| set_value.update(|n| Some(n + 1))>
        {format_args!("{} ({})", text, value)}
    </button>
};

I'm of the opinion that formatting strings for XML-ish things is a common-enough operation that it deserves a shorthand, although I'll note that JSX itself gets by just fine without it. I'll also note that JS has tilde-format-strings, which we don't :*(. What do you think?

@gbj
Copy link
Contributor

gbj commented Jan 2, 2021

Just popping in to say I'd also benefit from something like this. Maybe it would be possible to specify an additional arbitrary delimiter, in addition to { ... }? So you could for example specify that {% ... } should be treated differently from { ... }, or (if someone wanted to mimic parts of Angular syntax for example) that [ ... ] has some special meaning as in <input [value]="whatever"/>

@stoically
Copy link
Owner

stoically commented Jan 3, 2021

The use cases for special, non-valid-Rust syntax inside blocks can probably be vastly different, e.g. when thinking about all the things template engines are doing. So I'm hesitant to start implementing that here, since I feel like it's too high level for syn-rsx which tries to be generic plumbing for people implementing their own proc macros.

However, I've implemented a transform_block configuration, which exposes the ability to parse and transform block content. An example usage which would cover {% "{} ({})", text, value } could look like this:

use quote::quote;
use syn::{Expr, ExprLit, Token};
use syn_rsx::{parse2_with_config, ParserConfig};

let tokens = quote! {
    <div>{% "{} ({})", text, value}</div>
};

let config = ParserConfig::new().transform_block(|input| {
    if input.peek(Token![%]) {
        input.parse::<Token![%]>()?;
        let format_string = input.parse::<ExprLit>()?;

        let mut values = vec![];
        loop {
            if input.is_empty() {
                break;
            }

            input.parse::<Token![,]>()?;
            values.push(input.parse::<Expr>()?);
        }

        Ok(Some(quote! { format_args!(#format_string, #(#values),*) }))
    } else {
        Ok(None)
    }
});

parse2_with_config(tokens, config).unwrap();

Hope that covers it. If that doesn't help or there's something missing, please let me know.

@stoically
Copy link
Owner

stoically commented Jan 3, 2021

Published transform_block in v0.8.0-beta.1, feedback welcome

@stoically stoically added the enhancement New feature or request label Jan 3, 2021
@anp
Copy link
Author

anp commented Jan 4, 2021

Wow, thanks! Will let you know how it goes.

@zetanumbers
Copy link

This works great! Thank you!

@stoically
Copy link
Owner

Closing as this seems to be solved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

4 participants