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