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

feat(macros): 🎸 support path to declare widget type #606

Merged
merged 1 commit into from
Jun 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@
{
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
Loading