Skip to content

Commit b16368c

Browse files
committed
use_context
1 parent 27ad5ef commit b16368c

File tree

15 files changed

+94
-263
lines changed

15 files changed

+94
-263
lines changed

examples/context.rs

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,14 @@ use iocraft::prelude::*;
22

33
struct NumberOfTheDay(i32);
44

5-
#[context]
6-
struct MyContextConsumerContext<'a> {
7-
number: &'a NumberOfTheDay,
8-
}
9-
105
#[component]
11-
fn MyContextConsumer(context: MyContextConsumerContext) -> impl Into<AnyElement<'static>> {
6+
fn MyContextConsumer(hooks: Hooks) -> impl Into<AnyElement<'static>> {
7+
let number = hooks.use_context::<NumberOfTheDay>();
8+
129
element! {
1310
Box(border_style: BorderStyle::Round, border_color: Color::Cyan) {
1411
Text(content: "The number of the day is... ")
15-
Text(color: Color::Green, weight: Weight::Bold, content: context.number.0.to_string())
12+
Text(color: Color::Green, weight: Weight::Bold, content: number.0.to_string())
1613
Text(content: "!")
1714
}
1815
}

examples/form.rs

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -37,23 +37,16 @@ fn FormField(props: &FormFieldProps) -> impl Into<AnyElement<'static>> {
3737
}
3838
}
3939

40-
#[context]
41-
struct FormContext<'a> {
42-
system: &'a mut SystemContext,
43-
}
44-
4540
#[props]
4641
struct FormProps<'a> {
4742
first_name_out: Option<&'a mut String>,
4843
last_name_out: Option<&'a mut String>,
4944
}
5045

5146
#[component]
52-
fn Form<'a>(
53-
props: &mut FormProps<'a>,
54-
mut hooks: Hooks,
55-
context: FormContext,
56-
) -> impl Into<AnyElement<'static>> {
47+
fn Form<'a>(props: &mut FormProps<'a>, mut hooks: Hooks) -> impl Into<AnyElement<'static>> {
48+
let mut system = hooks.use_context_mut::<SystemContext>();
49+
5750
let first_name = hooks.use_state(|| "".to_string());
5851
let last_name = hooks.use_state(|| "".to_string());
5952
let focus = hooks.use_state(|| 0);
@@ -77,7 +70,7 @@ fn Form<'a>(
7770
if let Some(last_name_out) = props.last_name_out.as_mut() {
7871
**last_name_out = last_name.to_string();
7972
}
80-
context.system.exit();
73+
system.exit();
8174
element!(Box)
8275
} else {
8376
element! {

examples/progress_bar.rs

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,9 @@
11
use iocraft::prelude::*;
22
use std::time::Duration;
33

4-
#[context]
5-
struct ProgressBarContext<'a> {
6-
system: &'a mut SystemContext,
7-
}
8-
94
#[component]
10-
fn ProgressBar(mut hooks: Hooks, context: ProgressBarContext) -> impl Into<AnyElement<'static>> {
5+
fn ProgressBar(mut hooks: Hooks) -> impl Into<AnyElement<'static>> {
6+
let mut system = hooks.use_context_mut::<SystemContext>();
117
let progress = hooks.use_state::<f32, _>(|| 0.0);
128

139
hooks.use_future(async move {
@@ -18,7 +14,7 @@ fn ProgressBar(mut hooks: Hooks, context: ProgressBarContext) -> impl Into<AnyEl
1814
});
1915

2016
if progress >= 100.0 {
21-
context.system.exit();
17+
system.exit();
2218
}
2319

2420
element! {

examples/use_input.rs

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,13 @@
11
use iocraft::prelude::*;
22
use unicode_width::UnicodeWidthStr;
33

4-
#[context]
5-
struct ExampleContext<'a> {
6-
system: &'a mut SystemContext,
7-
}
8-
94
const AREA_WIDTH: u32 = 80;
105
const AREA_HEIGHT: u32 = 11;
116
const FACE: &str = "👾";
127

138
#[component]
14-
fn Example(context: ExampleContext, mut hooks: Hooks) -> impl Into<AnyElement<'static>> {
9+
fn Example(mut hooks: Hooks) -> impl Into<AnyElement<'static>> {
10+
let mut system = hooks.use_context_mut::<SystemContext>();
1511
let x = hooks.use_state(|| 0);
1612
let y = hooks.use_state(|| 0);
1713
let should_exit = hooks.use_state(|| false);
@@ -33,7 +29,7 @@ fn Example(context: ExampleContext, mut hooks: Hooks) -> impl Into<AnyElement<'s
3329
});
3430

3531
if should_exit.get() {
36-
context.system.exit();
32+
system.exit();
3733
}
3834

3935
element! {

examples/use_output.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use iocraft::prelude::*;
22
use std::time::Duration;
33

44
#[component]
5-
fn Example(mut hooks: Hooks) -> impl Into<AnyElement> {
5+
fn Example(mut hooks: Hooks) -> impl Into<AnyElement<'static>> {
66
let (stdout, stderr) = hooks.use_output();
77

88
hooks.use_future(async move {

packages/iocraft-macros/src/lib.rs

Lines changed: 2 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -272,93 +272,9 @@ pub fn props(_attr: TokenStream, item: TokenStream) -> TokenStream {
272272
quote!(#props).into()
273273
}
274274

275-
struct ParsedContext {
276-
context: ItemStruct,
277-
}
278-
279-
impl Parse for ParsedContext {
280-
fn parse(input: ParseStream) -> Result<Self> {
281-
let context: ItemStruct = input.parse()?;
282-
Ok(Self { context })
283-
}
284-
}
285-
286-
impl ToTokens for ParsedContext {
287-
fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
288-
let context = &self.context;
289-
let name = &context.ident;
290-
let generics = &context.generics;
291-
let lifetime = generics.params.first();
292-
293-
let ref_fields = context.fields.iter().map(|field| {
294-
let field_name = &field.ident;
295-
let field_type = &field.ty;
296-
quote! { #field_name: <#field_type as ::iocraft::ContextRef<#lifetime>>::RefOwner<#lifetime> }
297-
});
298-
299-
let ref_field_assignments = context.fields.iter().map(|field| {
300-
let field_name = &field.ident;
301-
let field_type = &field.ty;
302-
quote! { #field_name: <#field_type as ::iocraft::ContextRef>::get_from_component_updater(updater) }
303-
});
304-
305-
let ref_field_borrows = context.fields.iter().map(|field| {
306-
let field_name = &field.ident;
307-
let field_type = &field.ty;
308-
quote! { #field_name: <#field_type as ::iocraft::ContextRef>::borrow(&mut refs.#field_name) }
309-
});
310-
311-
tokens.extend(quote! {
312-
#context
313-
314-
const _: () = {
315-
pub struct ContextRefs #generics {
316-
#(#ref_fields,)*
317-
}
318-
319-
impl<'iocraft_lta> ContextRefs<'iocraft_lta> {
320-
fn refs_from_component_updater<#lifetime: 'iocraft_lta>(updater: &#lifetime ::iocraft::ComponentUpdater) -> ContextRefs<#lifetime> {
321-
ContextRefs {
322-
#(#ref_field_assignments,)*
323-
}
324-
}
325-
}
326-
327-
impl<#lifetime> ContextRefs #generics {
328-
fn borrow_refs<'iocraft_ltb: #lifetime, 'iocraft_ltc: 'iocraft_ltb>(refs: &'iocraft_ltb mut ContextRefs<'iocraft_ltc>) -> #name<#lifetime> {
329-
#name {
330-
#(#ref_field_borrows,)*
331-
}
332-
}
333-
}
334-
335-
impl<'a> ::iocraft::ContextImplExt<'a> for #name<'a> {
336-
type Refs<'b: 'a> = ContextRefs<'b>;
337-
338-
fn refs_from_component_updater<'b: 'a>(updater: &'b ::iocraft::ComponentUpdater) -> Self::Refs<'b> {
339-
ContextRefs::refs_from_component_updater(updater)
340-
}
341-
342-
fn borrow_refs<'b: 'a, 'c: 'b>(refs: &'b mut Self::Refs<'c>) -> Self {
343-
ContextRefs::borrow_refs(refs)
344-
}
345-
}
346-
};
347-
});
348-
}
349-
}
350-
351-
/// Defines a struct containing context references to be made available to components.
352-
#[proc_macro_attribute]
353-
pub fn context(_attr: TokenStream, item: TokenStream) -> TokenStream {
354-
let context = parse_macro_input!(item as ParsedContext);
355-
quote!(#context).into()
356-
}
357-
358275
struct ParsedComponent {
359276
f: ItemFn,
360277
props_type: Option<Box<Type>>,
361-
context_type: Option<Box<Type>>,
362278
impl_args: Vec<proc_macro2::TokenStream>,
363279
}
364280

@@ -367,7 +283,6 @@ impl Parse for ParsedComponent {
367283
let f: ItemFn = input.parse()?;
368284

369285
let mut props_type = None;
370-
let mut context_type = None;
371286
let mut impl_args = Vec::new();
372287

373288
for arg in &f.sig.inputs {
@@ -400,23 +315,6 @@ impl Parse for ParsedComponent {
400315
}
401316
_ => return Err(Error::new(arg.ty.span(), "invalid `hooks` type")),
402317
},
403-
"context" | "_context" => {
404-
if context_type.is_some() {
405-
return Err(Error::new(arg.span(), "duplicate `context` argument"));
406-
}
407-
match &*arg.ty {
408-
Type::Path(_) => {
409-
context_type = Some(arg.ty.clone());
410-
impl_args.push({
411-
let type_name = &arg.ty;
412-
quote!(#type_name::borrow_refs(&mut context_refs))
413-
});
414-
}
415-
_ => {
416-
return Err(Error::new(arg.ty.span(), "invalid `context` type"))
417-
}
418-
}
419-
}
420318
_ => return Err(Error::new(arg.span(), "invalid argument")),
421319
}
422320
}
@@ -427,7 +325,6 @@ impl Parse for ParsedComponent {
427325
Ok(Self {
428326
f,
429327
props_type,
430-
context_type,
431328
impl_args,
432329
})
433330
}
@@ -449,12 +346,6 @@ impl ToTokens for ParsedComponent {
449346
.map(|ty| quote!(#ty))
450347
.unwrap_or_else(|| quote!(::iocraft::NoProps));
451348

452-
let context_refs = self.context_type.as_ref().map(|ty| {
453-
quote! {
454-
let mut context_refs = #ty::refs_from_component_updater(updater);
455-
}
456-
});
457-
458349
tokens.extend(quote! {
459350
#vis struct #name;
460351

@@ -469,9 +360,9 @@ impl ToTokens for ParsedComponent {
469360
Self
470361
}
471362

472-
fn update(&mut self, props: &mut Self::Props<'_>, hooks: ::iocraft::Hooks, updater: &mut ::iocraft::ComponentUpdater) {
363+
fn update(&mut self, props: &mut Self::Props<'_>, mut hooks: ::iocraft::Hooks, updater: &mut ::iocraft::ComponentUpdater) {
473364
let mut e = {
474-
#context_refs
365+
let hooks = hooks.with_context_stack(updater.component_context_stack());
475366
Self::implementation(#(#impl_args),*).into()
476367
};
477368
updater.update_children([&mut e], None);

packages/iocraft-macros/tests/context.rs

Lines changed: 0 additions & 12 deletions
This file was deleted.

packages/iocraft/src/components/context_provider.rs

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -39,19 +39,12 @@ mod tests {
3939
use crate::prelude::*;
4040

4141
struct StringContext(String);
42-
struct OtherContext;
43-
44-
#[context]
45-
struct MyComponentContext<'a> {
46-
string: &'a StringContext,
47-
_other: Option<&'a OtherContext>,
48-
_system: &'a mut SystemContext,
49-
}
5042

5143
#[component]
52-
fn MyComponent(context: MyComponentContext) -> impl Into<AnyElement<'static>> {
44+
fn MyComponent(hooks: Hooks) -> impl Into<AnyElement<'static>> {
45+
let s = hooks.use_context::<StringContext>();
5346
element! {
54-
Text(content: &context.string.0)
47+
Text(content: &s.0)
5548
}
5649
}
5750

0 commit comments

Comments
 (0)