View plugins
This commit is contained in:
@@ -8,6 +8,7 @@ pub fn main() {
|
||||
#[component]
|
||||
fn App(cx: &Arc<Context>) -> View {
|
||||
rsx! {
|
||||
impl my_center(11, 1)
|
||||
Card { content: "Hello World".to_string() }
|
||||
}
|
||||
.view(&cx)
|
||||
@@ -22,3 +23,9 @@ fn Card(cx: &Arc<Context>, content: String) -> View {
|
||||
}
|
||||
.view(&cx)
|
||||
}
|
||||
|
||||
fn my_center(ctx: &mut DrawContext, view: View, w: u16, h: u16) {
|
||||
let (x, y) = ((ctx.area.width - w) / 2, (ctx.area.height - h) / 2);
|
||||
let area = ctx.allocate(x, y, w, h);
|
||||
ctx.draw_view(area, view);
|
||||
}
|
||||
|
||||
@@ -51,6 +51,20 @@ fn emit_deps_vec(deps: &[Dep]) -> TokenStream {
|
||||
}
|
||||
}
|
||||
|
||||
/// Emits a Vec of plugins
|
||||
fn emit_plugins(deps: &[ViewPlugin]) -> TokenStream {
|
||||
deps.iter()
|
||||
.map(|d| {
|
||||
let path = &d.path;
|
||||
if let Some(args) = &d.args {
|
||||
quote!( #path(ctx, view #(,#args)*); )
|
||||
} else {
|
||||
quote!( #path(ctx, view); )
|
||||
}
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Emits code for a single node within a scope
|
||||
fn emit_node_scope(node: &RsxNode) -> TokenStream {
|
||||
match node {
|
||||
@@ -144,6 +158,7 @@ fn emit_node(node: &RsxNode) -> TokenStream {
|
||||
}
|
||||
|
||||
RsxNode::Component {
|
||||
plugins,
|
||||
path,
|
||||
props,
|
||||
children,
|
||||
@@ -171,9 +186,17 @@ fn emit_node(node: &RsxNode) -> TokenStream {
|
||||
}
|
||||
};
|
||||
|
||||
if plugins.len() == 0 {
|
||||
quote! {
|
||||
scope.child(#component_expr, None);
|
||||
}
|
||||
} else {
|
||||
let plugins_emit = emit_plugins(plugins);
|
||||
|
||||
quote! {
|
||||
scope.child(#component_expr, Some(std::sync::Arc::new(|ctx, view| {#plugins_emit})));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RsxNode::Mount(m) => quote! {
|
||||
|
||||
+41
-1
@@ -5,13 +5,14 @@
|
||||
use std::collections::HashSet;
|
||||
|
||||
use proc_macro2::Span;
|
||||
use syn::braced;
|
||||
use syn::parse::discouraged::Speculative;
|
||||
use syn::punctuated::Punctuated;
|
||||
use syn::{
|
||||
Expr, Ident, LitStr, Pat, Path, Result, Token,
|
||||
parse::{Parse, ParseStream},
|
||||
token::Brace,
|
||||
};
|
||||
use syn::{braced, parenthesized};
|
||||
|
||||
/// Root of an RSX expression
|
||||
pub struct RsxRoot {
|
||||
@@ -45,6 +46,8 @@ pub enum RsxNode {
|
||||
Expr(Expr),
|
||||
/// Component instantiation: `Component { prop: value, ... }`
|
||||
Component {
|
||||
/// View plugins
|
||||
plugins: Vec<ViewPlugin>,
|
||||
/// Component path (e.g., `my_module::MyComponent`)
|
||||
path: Path,
|
||||
/// Component properties
|
||||
@@ -82,6 +85,11 @@ pub struct Dep {
|
||||
pub is_dep: bool,
|
||||
}
|
||||
|
||||
pub struct ViewPlugin {
|
||||
pub path: Path,
|
||||
pub args: Option<Vec<Expr>>,
|
||||
}
|
||||
|
||||
fn parse_deps(input: ParseStream) -> Result<Vec<Dep>> {
|
||||
let mut deps = Vec::new();
|
||||
|
||||
@@ -122,6 +130,35 @@ fn parse_deps(input: ParseStream) -> Result<Vec<Dep>> {
|
||||
Ok(deps)
|
||||
}
|
||||
|
||||
fn parse_plugins(input: ParseStream) -> Result<Vec<ViewPlugin>> {
|
||||
let mut plugins = Vec::new();
|
||||
|
||||
if input.peek(Token![impl]) {
|
||||
input.parse::<Token![impl]>()?;
|
||||
loop {
|
||||
let path: Path = input.parse()?;
|
||||
|
||||
let args = if input.peek(syn::token::Paren) {
|
||||
let content;
|
||||
parenthesized!(content in input);
|
||||
let exprs = Punctuated::<Expr, Token![,]>::parse_terminated(&content)?;
|
||||
Some(exprs.into_iter().collect())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
plugins.push(ViewPlugin { path, args });
|
||||
|
||||
if !input.peek(Token![,]) {
|
||||
break;
|
||||
}
|
||||
input.parse::<Token![,]>()?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(plugins)
|
||||
}
|
||||
|
||||
impl Parse for RsxNode {
|
||||
fn parse(input: ParseStream) -> Result<Self> {
|
||||
// @{ $expr }
|
||||
@@ -201,10 +238,12 @@ impl Parse for RsxNode {
|
||||
|
||||
/// Parses Path or Path { ... } into RsxNode::Component.
|
||||
fn parse_component_invocation(input: ParseStream) -> Result<RsxNode> {
|
||||
let plugins = parse_plugins(input)?;
|
||||
let path: Path = input.parse()?;
|
||||
|
||||
if !input.peek(Brace) {
|
||||
return Ok(RsxNode::Component {
|
||||
plugins,
|
||||
path,
|
||||
props: Vec::new(),
|
||||
children: Vec::new(),
|
||||
@@ -217,6 +256,7 @@ fn parse_component_invocation(input: ParseStream) -> Result<RsxNode> {
|
||||
let (props, children) = parse_props_and_children(&content)?;
|
||||
|
||||
Ok(RsxNode::Component {
|
||||
plugins,
|
||||
path,
|
||||
props,
|
||||
children,
|
||||
|
||||
Reference in New Issue
Block a user