Skip to content

Commit

Permalink
feat(macros): 🎸 support path to declare widget type
Browse files Browse the repository at this point in the history
  • Loading branch information
M-Adoo committed Jun 22, 2024
1 parent 5e44169 commit ddfb488
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 38 deletions.
17 changes: 17 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,23 @@ Please only add new entries below the [Unreleased](#unreleased---releasedate) he

- **core**: Added support to query a `WriteRef` from a state, enabling users to modify the state after attaching it to a widget. (#601 @M-Adoo)
- **core**: Introduced the `DeclareInto` trait for any type that implements `DeclareFrom`. (#604 @M-Adoo)
- **macros**: Improved widget declaration to allow specifying widget types via path. (#606 @M-Adoo)
```rust
// Previously, a widget type could only be specified using an identifier, requiring prior import of `Row`.
use ribir::prelude::*;
fn_widget! {
@Row {
...
}
}

// Now, the widget type can be specified using a path, removing the need for a prior import.
fn_widget! {
@ribir::prelude::Row {
...
}
}
```

### Changed

Expand Down
12 changes: 12 additions & 0 deletions docs/en/get_started/quick_start.md
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,18 @@ fn main() {
});
}
```
For expression widgets that are simple function calls, the `{}` can be omitted for brevity:

```rust ignore
fn_widget! {
// Instead of using braces:
let label = @ { Label::new("Increment") };
// You can directly write:
let label = @Label::new("Increment");
...
};
```

## State -- make data watchable and shareable

Although we have created a counter, it always shows `0` and does not respond to the button. In this section, you will learn how to make your counter work through state.
Expand Down
12 changes: 12 additions & 0 deletions docs/zh/get_started/quick_start.md
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,18 @@ fn main() {
}
```

对于简单的函数调用形式的表达式 widget ,可以省略 `{}` 以简化书写:

```rust ignore
fn_widget! {
// 使用大括号的写法:
let label = @ { Label::new("Increment") };
// 可以直接写为:
let label = @Label::new("Increment");
...
};
```

## 状态——让数据变得可被侦和共享

我们虽然创建了一个计数器,但它总是显示 `0`,也不响应按钮做任何事情。在这一节中,你将会了解到如何通过状态让你的计数器工作。
Expand Down
12 changes: 5 additions & 7 deletions examples/todos/src/ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,13 @@ impl Compose for Todos {
align_items: Align::Center,
item_gap: 12.,
@H1 { text: "Todo" }
@ {
input(None, move |text| {
$this.write().new_task(text.to_string());
})
}
@input(None, move |text| {
$this.write().new_task(text.to_string());
})
@Tabs {
@Tab {
@TabItem { @{ Label::new("ALL") } }
@TabPane { @{ task_lists(&this, |_| true) } }
@TabItem { @Label::new("ALL") }
@TabPane { @task_lists(&this, |_| true) }
}
@Tab {
@TabItem { @{ Label::new("ACTIVE") } }
Expand Down
55 changes: 24 additions & 31 deletions macros/src/symbol_process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,47 +113,40 @@ mod tokens_pre_process {
{
tokens.push(TokenTree::Ident(Ident::new(KW_RDL, at.span())));
tokens.push(not_token(at.span()));

let body = match iter.next() {
// declare a new widget: `@ SizedBox { ... }`
Some(TokenTree::Ident(name)) => {
let next = iter.next();
let Some(TokenTree::Group(body)) = next else {
return rdl_syntax_err(
at.span(),
next.map(|n| n.span()).or_else(|| Some(name.span()))
)
};
let tokens = TokenStream::from_iter([TokenTree::Ident(name), TokenTree::Group(body)]);
Group::new(Delimiter::Brace, tokens)
}
let mut rdl_group = smallvec::SmallVec::<[TokenTree; 3]>::default();
match iter.next() {
// declare a variable widget as parent, `@ $var { ... }`
Some(TokenTree::Punct(dollar)) if dollar.as_char() == '$' => {
if let Some(TokenTree::Ident(var)) = iter.next() {
let next = iter.next();
let Some(TokenTree::Group(body)) = next else {
return rdl_syntax_err(
at.span(),
next.map(|n| n.span()).or_else(|| Some(var.span()))
)
rdl_group.push(TokenTree::Punct(dollar));
rdl_group.push(TokenTree::Ident(var));
if let Some(g) = iter.next() {
rdl_group.push(g);
};
let tokens = TokenStream::from_iter([
TokenTree::Punct(dollar),
TokenTree::Ident(var),
TokenTree::Group(body),
]);
Group::new(Delimiter::Brace, tokens)
} else {
return dollar_err(dollar.span());
}
}
// declare a expression widget `@ { ... }`
Some(TokenTree::Group(g)) => g,
n => {
return rdl_syntax_err(at.span(), n.map(|n| n.span()));
}
Some(TokenTree::Group(g)) => rdl_group.push(TokenTree::Group(g)) ,
// declare a new widget: `@ SizedBox { ... }`
mut n => {
while let Some(t) = n.take() {
let is_group = matches!(t, TokenTree::Group(_));
rdl_group.push(t);
if is_group {
break
}
n = iter.next();
};
},
};
tokens.push(TokenTree::Group(body));
if let Some(TokenTree::Group(_)) = rdl_group.last() {
let rdl_group = TokenStream::from_iter(rdl_group);
tokens.push(TokenTree::Group(Group::new(Delimiter::Brace, rdl_group)));
} else {
return rdl_syntax_err(at.span(), rdl_group.last().map(|n| n.span()));

Check warning on line 148 in macros/src/symbol_process.rs

View check run for this annotation

Codecov / codecov/patch

macros/src/symbol_process.rs#L148

Added line #L148 was not covered by tests
}
}
Some(TokenTree::Punct(p)) if p.as_char() == '$' => {
match iter.next() {
Expand Down

0 comments on commit ddfb488

Please sign in to comment.