Skip to content

Commit 5b54d7f

Browse files
Ralithcmyr
authored andcommitted
Expose derived lenses as associated constants
1 parent b0a6e2d commit 5b54d7f

File tree

7 files changed

+33
-22
lines changed

7 files changed

+33
-22
lines changed

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,8 @@ struct AppState {
188188
### lens
189189

190190
The [Lens datatype] gives access to a part of a larger data structure. Like
191-
`Data`, This can be derived.
191+
`Data`, this can be derived. Derived lenses are accessed as associated constants
192+
with the same name as the field.
192193

193194
```rust
194195
#[derive(Clone, Data, Lens)]
@@ -202,7 +203,7 @@ To use the lens, wrap your widget with `LensWrap` (note the conversion of
202203
CamelCase to snake_case):
203204

204205
```rust
205-
LensWrap::new(WidgetThatExpectsf64::new(), app_state::value);
206+
LensWrap::new(WidgetThatExpectsf64::new(), AppState::value);
206207
```
207208

208209
## Using druid

druid-derive/src/lens.rs

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ fn derive_struct(input: &syn::DeriveInput) -> Result<proc_macro2::TokenStream, s
4848
};
4949

5050
let twizzled_name = if is_camel_case(&ty.to_string()) {
51-
let temp_name = to_snake_case(&ty.to_string());
51+
let temp_name = format!("{}_derived_lenses", to_snake_case(&ty.to_string()));
5252
proc_macro2::Ident::new(&temp_name, proc_macro2::Span::call_site())
5353
} else {
5454
return Err(syn::Error::new(
@@ -57,22 +57,15 @@ fn derive_struct(input: &syn::DeriveInput) -> Result<proc_macro2::TokenStream, s
5757
));
5858
};
5959

60-
// Declare a struct for each field
61-
let structs = fields.iter().map(|f| {
62-
let field_name = &f.ident;
63-
64-
quote! {
65-
#[allow(non_camel_case_types)]
66-
pub struct #field_name;
67-
}
68-
});
69-
7060
// Impl Lens for each field
7161
let impls = fields.iter().map(|f| {
7262
let field_name = &f.ident;
7363
let field_ty = &f.ty;
7464

7565
quote! {
66+
/// Lens for the field on #ty
67+
#[allow(non_camel_case_types)]
68+
pub struct #field_name;
7669

7770
impl Lens<#ty, #field_ty> for #field_name {
7871
fn with<V, F: FnOnce(&#field_ty) -> V>(&self, data: &#ty, f: F) -> V {
@@ -86,13 +79,26 @@ fn derive_struct(input: &syn::DeriveInput) -> Result<proc_macro2::TokenStream, s
8679
}
8780
});
8881

82+
let associated_items = fields.iter().map(|f| {
83+
let field_name = &f.ident;
84+
quote! {
85+
/// Lens for the corresponding field
86+
pub const #field_name: #field_name = #field_name;
87+
}
88+
});
89+
8990
let expanded = quote! {
9091
pub mod #twizzled_name {
92+
//! Lens definitions for #ty
9193
use super::*;
92-
9394
use druid::Lens;
94-
#(#structs)*
95+
9596
#(#impls)*
97+
98+
#[allow(non_upper_case_globals)]
99+
impl #ty {
100+
#(#associated_items)*
101+
}
96102
}
97103
};
98104

druid-derive/src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ pub fn derive_data(input: TokenStream) -> TokenStream {
3131
.into()
3232
}
3333

34+
/// Generates lenses to access the fields of a struct
35+
///
36+
/// An associated constant is defined on the struct for each field,
37+
/// having the same name as the field.
3438
#[proc_macro_derive(Lens)]
3539
pub fn derive_lens(input: TokenStream) -> TokenStream {
3640
let input = parse_macro_input!(input as syn::DeriveInput);

druid/examples/calc.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ fn build_calc() -> impl Widget<CalcState> {
152152
let mut column = Flex::column();
153153
let display = LensWrap::new(
154154
DynLabel::new(|data: &String, _env| data.clone()),
155-
calc_state::value,
155+
CalcState::value,
156156
);
157157
column.add_child(pad(display), 0.0);
158158
column.add_child(

druid/examples/either.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,12 @@ fn ui_builder() -> impl Widget<AppState> {
3535

3636
let mut col = Flex::column();
3737
col.add_child(
38-
Padding::new(5.0, LensWrap::new(Checkbox::new(), app_state::which)),
38+
Padding::new(5.0, LensWrap::new(Checkbox::new(), AppState::which)),
3939
0.0,
4040
);
4141
let either = Either::new(
4242
|data, _env| data.which,
43-
Padding::new(5.0, LensWrap::new(Slider::new(), app_state::value)),
43+
Padding::new(5.0, LensWrap::new(Slider::new(), AppState::value)),
4444
Padding::new(5.0, label),
4545
);
4646
col.add_child(either, 0.0);

druid/examples/slider.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,13 @@ fn build_widget() -> impl Widget<DemoState> {
3131
}
3232
});
3333
let mut row = Flex::row();
34-
let checkbox = LensWrap::new(Checkbox::new(), demo_state::double);
34+
let checkbox = LensWrap::new(Checkbox::new(), DemoState::double);
3535
let checkbox_label = Label::new("double the value");
3636
row.add_child(checkbox, 0.0);
3737
row.add_child(Padding::new(5.0, checkbox_label), 1.0);
3838

39-
let bar = LensWrap::new(ProgressBar::new(), demo_state::value);
40-
let slider = LensWrap::new(Slider::new(), demo_state::value);
39+
let bar = LensWrap::new(ProgressBar::new(), DemoState::value);
40+
let slider = LensWrap::new(Slider::new(), DemoState::value);
4141

4242
let button_1 = Button::sized(
4343
"increment ",

druid/examples/switch.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ struct DemoState {
2323
fn build_widget() -> impl Widget<DemoState> {
2424
let mut col = Flex::column();
2525
let mut row = Flex::row();
26-
let switch = LensWrap::new(Switch::new(), demo_state::value);
26+
let switch = LensWrap::new(Switch::new(), DemoState::value);
2727
let switch_label = Label::new("Setting label");
2828

2929
row.add_child(Padding::new(5.0, switch_label), 0.0);

0 commit comments

Comments
 (0)