prototty_event_routine/
lib.rs

1pub use prototty_input;
2pub use prototty_input::Input;
3pub use prototty_render;
4pub use prototty_render::{ColModify, Frame, View, ViewContext};
5use std::marker::PhantomData;
6use std::time::Duration;
7
8mod app;
9pub mod common_event;
10pub use app::*;
11
12pub enum Handled<R, C> {
13    Return(R),
14    Continue(C),
15}
16
17impl<R, C> Handled<R, C> {
18    pub fn map_continue<D, F>(self, f: F) -> Handled<R, D>
19    where
20        F: FnOnce(C) -> D,
21    {
22        match self {
23            Handled::Return(r) => Handled::Return(r),
24            Handled::Continue(c) => Handled::Continue(f(c)),
25        }
26    }
27    pub fn map_return<S, F>(self, f: F) -> Handled<S, C>
28    where
29        F: FnOnce(R) -> S,
30    {
31        match self {
32            Handled::Return(r) => Handled::Return(f(r)),
33            Handled::Continue(c) => Handled::Continue(c),
34        }
35    }
36}
37
38pub trait EventOrPeek: Sized + private::Sealed {
39    type Event;
40    fn with<A, X, F, G>(self, arg: A, f: F, g: G) -> X
41    where
42        F: FnOnce(A, Self::Event) -> X,
43        G: FnOnce(A) -> X;
44}
45
46pub fn event_or_peek_with_handled<EP, A, X, F>(event_or_peek: EP, arg: A, f: F) -> Handled<X, A>
47where
48    EP: EventOrPeek,
49    F: FnOnce(A, EP::Event) -> Handled<X, A>,
50{
51    event_or_peek.with(arg, f, Handled::Continue)
52}
53
54pub struct Event<E>(E);
55pub struct Peek<E>(PhantomData<E>);
56
57impl<E> Event<E> {
58    pub fn new(e: E) -> Self {
59        Self(e)
60    }
61}
62
63impl<E> Peek<E> {
64    pub fn new() -> Self {
65        Self(PhantomData)
66    }
67}
68
69impl<E> Default for Peek<E> {
70    fn default() -> Self {
71        Self::new()
72    }
73}
74
75impl<E> EventOrPeek for Event<E> {
76    type Event = E;
77    fn with<A, X, F, G>(self, arg: A, f: F, _g: G) -> X
78    where
79        F: FnOnce(A, Self::Event) -> X,
80        G: FnOnce(A) -> X,
81    {
82        f(arg, self.0)
83    }
84}
85
86impl<E> EventOrPeek for Peek<E> {
87    type Event = E;
88    fn with<A, X, F, G>(self, arg: A, _f: F, g: G) -> X
89    where
90        F: FnOnce(A, Self::Event) -> X,
91        G: FnOnce(A) -> X,
92    {
93        g(arg)
94    }
95}
96
97mod private {
98    pub trait Sealed {}
99    impl<E> Sealed for super::Event<E> {}
100    impl<E> Sealed for super::Peek<E> {}
101}
102
103pub trait EventRoutine: Sized {
104    type Return;
105    type Data;
106    type View;
107    type Event;
108
109    fn handle<EP>(self, data: &mut Self::Data, view: &Self::View, event_or_peek: EP) -> Handled<Self::Return, Self>
110    where
111        EP: EventOrPeek<Event = Self::Event>;
112
113    fn view<F, C>(&self, data: &Self::Data, view: &mut Self::View, context: ViewContext<C>, frame: &mut F)
114    where
115        F: Frame,
116        C: ColModify;
117
118    fn repeat<U, F>(self, f: F) -> Repeat<Self, F>
119    where
120        F: FnMut(Self::Return) -> Handled<U, Self>,
121    {
122        Repeat { t: self, f }
123    }
124
125    fn select<S>(self, selector: S) -> Select<Self, S>
126    where
127        S: Selector<DataOutput = Self::Data, ViewOutput = Self::View>,
128    {
129        Select { t: self, selector }
130    }
131
132    fn and_then<U, F>(self, f: F) -> AndThen<Self, U, F>
133    where
134        U: EventRoutine<Data = Self::Data, View = Self::View>,
135        F: FnOnce(Self::Return) -> U,
136    {
137        AndThen(AndThenPrivate::First { t: self, f })
138    }
139
140    fn map<F, U>(self, f: F) -> Map<Self, F>
141    where
142        F: FnOnce(Self::Return) -> U,
143    {
144        Map { t: self, f }
145    }
146
147    fn convert_input_to_common_event(self) -> common_event::ConvertInputToCommonEvent<Self> {
148        common_event::ConvertInputToCommonEvent(self)
149    }
150
151    fn app_one_shot_ignore_return(
152        self,
153        data: Self::Data,
154        view: Self::View,
155    ) -> EventRoutineAppOneShotIgnoreReturn<Self> {
156        EventRoutineAppOneShotIgnoreReturn::new(self, data, view)
157    }
158
159    fn return_on_exit<F>(self, f: F) -> common_event::ReturnOnExit<Self, F>
160    where
161        F: FnOnce(&mut Self::Data) -> Self::Return,
162    {
163        common_event::ReturnOnExit { t: self, f }
164    }
165
166    fn decorated<D>(self, d: D) -> Decorated<Self, D>
167    where
168        D: Decorate<View = Self::View, Data = Self::Data>,
169    {
170        Decorated { t: self, d }
171    }
172
173    fn on_event<F>(self, f: F) -> OnEvent<Self, F>
174    where
175        F: FnMut(&mut &mut Self::Data, &Self::Event),
176    {
177        OnEvent { t: self, f }
178    }
179}
180
181struct OneShot<T, D, V, E> {
182    field: T,
183    data: PhantomData<D>,
184    view: PhantomData<V>,
185    event: PhantomData<E>,
186}
187
188impl<T, D, V, E> OneShot<T, D, V, E> {
189    pub fn new(field: T) -> Self {
190        Self {
191            field,
192            data: PhantomData,
193            view: PhantomData,
194            event: PhantomData,
195        }
196    }
197}
198
199pub struct Value<T, D, V, E>(OneShot<T, D, V, E>);
200
201impl<T, D, V, E> Value<T, D, V, E> {
202    pub fn new(value: T) -> Self {
203        Self(OneShot::new(value))
204    }
205}
206
207impl<T, D, V, E> EventRoutine for Value<T, D, V, E> {
208    type Return = T;
209    type Data = D;
210    type View = V;
211    type Event = E;
212
213    fn handle<EP>(self, _data: &mut Self::Data, _view: &Self::View, _event_or_peek: EP) -> Handled<Self::Return, Self>
214    where
215        EP: EventOrPeek<Event = Self::Event>,
216    {
217        Handled::Return(self.0.field)
218    }
219
220    fn view<F, C>(&self, _data: &Self::Data, _view: &mut Self::View, _context: ViewContext<C>, _frame: &mut F)
221    where
222        F: Frame,
223        C: ColModify,
224    {
225    }
226}
227
228pub struct SideEffect<F, D, V, E>(OneShot<F, D, V, E>);
229
230impl<F, D, V, E> SideEffect<F, D, V, E> {
231    pub fn new(f: F) -> Self {
232        Self(OneShot::new(f))
233    }
234}
235
236impl<F, D, V, E, T> EventRoutine for SideEffect<F, D, V, E>
237where
238    F: FnOnce(&mut D, &V) -> T,
239{
240    type Return = T;
241    type Data = D;
242    type View = V;
243    type Event = E;
244
245    fn handle<EP>(self, data: &mut Self::Data, view: &Self::View, _event_or_peek: EP) -> Handled<Self::Return, Self>
246    where
247        EP: EventOrPeek<Event = Self::Event>,
248    {
249        Handled::Return((self.0.field)(data, view))
250    }
251
252    fn view<G, C>(&self, _data: &Self::Data, _view: &mut Self::View, _context: ViewContext<C>, _frame: &mut G)
253    where
254        G: Frame,
255        C: ColModify,
256    {
257    }
258}
259
260enum SideEffectThenPrivate<F, D, V, E, U> {
261    First(OneShot<F, D, V, E>),
262    Second(U),
263}
264pub struct SideEffectThen<F, D, V, E, U>(SideEffectThenPrivate<F, D, V, E, U>);
265
266impl<F, D, V, E, U> SideEffectThen<F, D, V, E, U>
267where
268    U: EventRoutine<Data = D, View = V, Event = E>,
269    F: FnOnce(&mut D, &V) -> U,
270{
271    pub fn new(f: F) -> Self {
272        Self(SideEffectThenPrivate::First(OneShot::new(f)))
273    }
274}
275
276impl<F, D, V, E, U> EventRoutine for SideEffectThen<F, D, V, E, U>
277where
278    U: EventRoutine<Data = D, View = V, Event = E>,
279    F: FnOnce(&mut D, &V) -> U,
280{
281    type Return = U::Return;
282    type Data = D;
283    type View = V;
284    type Event = E;
285
286    fn handle<EP>(self, data: &mut Self::Data, view: &Self::View, event_or_peek: EP) -> Handled<Self::Return, Self>
287    where
288        EP: EventOrPeek<Event = Self::Event>,
289    {
290        match self.0 {
291            SideEffectThenPrivate::First(one_shot) => (one_shot.field)(data, view)
292                .handle(data, view, Peek::new())
293                .map_continue(|u| SideEffectThen(SideEffectThenPrivate::Second(u))),
294            SideEffectThenPrivate::Second(u) => u
295                .handle(data, view, event_or_peek)
296                .map_continue(|u| SideEffectThen(SideEffectThenPrivate::Second(u))),
297        }
298    }
299
300    fn view<G, C>(&self, data: &Self::Data, view: &mut Self::View, context: ViewContext<C>, frame: &mut G)
301    where
302        G: Frame,
303        C: ColModify,
304    {
305        match self.0 {
306            SideEffectThenPrivate::First(_) => (),
307            SideEffectThenPrivate::Second(ref u) => u.view(data, view, context, frame),
308        }
309    }
310}
311
312pub struct Map<T, F> {
313    t: T,
314    f: F,
315}
316
317impl<T, U, F> EventRoutine for Map<T, F>
318where
319    T: EventRoutine,
320    F: FnOnce(T::Return) -> U,
321{
322    type Return = U;
323    type Data = T::Data;
324    type View = T::View;
325    type Event = T::Event;
326
327    fn handle<EP>(self, data: &mut Self::Data, view: &Self::View, event_or_peek: EP) -> Handled<Self::Return, Self>
328    where
329        EP: EventOrPeek<Event = Self::Event>,
330    {
331        let Self { t, f } = self;
332        match t.handle(data, view, event_or_peek) {
333            Handled::Continue(t) => Handled::Continue(Self { t, f }),
334            Handled::Return(r) => Handled::Return(f(r)),
335        }
336    }
337
338    fn view<G, C>(&self, data: &Self::Data, view: &mut Self::View, context: ViewContext<C>, frame: &mut G)
339    where
340        G: Frame,
341        C: ColModify,
342    {
343        self.t.view(data, view, context, frame)
344    }
345}
346
347enum AndThenPrivate<T, U, F> {
348    First { t: T, f: F },
349    Second(U),
350}
351
352pub struct AndThen<T, U, F>(AndThenPrivate<T, U, F>);
353
354impl<T, U, F> EventRoutine for AndThen<T, U, F>
355where
356    T: EventRoutine,
357    U: EventRoutine<Data = T::Data, View = T::View, Event = T::Event>,
358    F: FnOnce(T::Return) -> U,
359{
360    type Return = U::Return;
361    type Data = T::Data;
362    type View = T::View;
363    type Event = T::Event;
364
365    fn handle<EP>(self, data: &mut Self::Data, view: &Self::View, event_or_peek: EP) -> Handled<Self::Return, Self>
366    where
367        EP: EventOrPeek<Event = Self::Event>,
368    {
369        match self.0 {
370            AndThenPrivate::First { t, f } => match t.handle(data, view, event_or_peek) {
371                Handled::Continue(t) => Handled::Continue(AndThen(AndThenPrivate::First { t, f })),
372                Handled::Return(r) => f(r)
373                    .handle(data, view, Peek::new())
374                    .map_continue(|u| AndThen(AndThenPrivate::Second(u))),
375            },
376            AndThenPrivate::Second(u) => u
377                .handle(data, view, event_or_peek)
378                .map_continue(|u| AndThen(AndThenPrivate::Second(u))),
379        }
380    }
381
382    fn view<G, C>(&self, data: &Self::Data, view: &mut Self::View, context: ViewContext<C>, frame: &mut G)
383    where
384        G: Frame,
385        C: ColModify,
386    {
387        match self.0 {
388            AndThenPrivate::First { ref t, .. } => t.view(data, view, context, frame),
389            AndThenPrivate::Second(ref u) => u.view(data, view, context, frame),
390        }
391    }
392}
393
394pub trait DataSelector {
395    type DataInput;
396    type DataOutput;
397    fn data<'a>(&self, input: &'a Self::DataInput) -> &'a Self::DataOutput;
398    fn data_mut<'a>(&self, input: &'a mut Self::DataInput) -> &'a mut Self::DataOutput;
399}
400
401pub trait ViewSelector {
402    type ViewInput;
403    type ViewOutput;
404    fn view<'a>(&self, input: &'a Self::ViewInput) -> &'a Self::ViewOutput;
405    fn view_mut<'a>(&self, input: &'a mut Self::ViewInput) -> &'a mut Self::ViewOutput;
406}
407
408pub trait Selector: DataSelector + ViewSelector {}
409
410#[derive(Clone, Copy)]
411pub struct Select<T, S> {
412    t: T,
413    selector: S,
414}
415
416impl<T, S> EventRoutine for Select<T, S>
417where
418    T: EventRoutine,
419    S: Selector<DataOutput = T::Data, ViewOutput = T::View>,
420{
421    type Return = T::Return;
422    type Data = S::DataInput;
423    type View = S::ViewInput;
424    type Event = T::Event;
425
426    fn handle<EP>(self, data: &mut Self::Data, view: &Self::View, event_or_peek: EP) -> Handled<Self::Return, Self>
427    where
428        EP: EventOrPeek<Event = Self::Event>,
429    {
430        let Self { t, selector } = self;
431        t.handle(selector.data_mut(data), selector.view(view), event_or_peek)
432            .map_continue(|t| Self { t, selector })
433    }
434
435    fn view<F, C>(&self, data: &Self::Data, view: &mut Self::View, context: ViewContext<C>, frame: &mut F)
436    where
437        F: Frame,
438        C: ColModify,
439    {
440        self.t
441            .view(self.selector.data(data), self.selector.view_mut(view), context, frame)
442    }
443}
444
445pub struct Repeat<T, F> {
446    t: T,
447    f: F,
448}
449impl<T, U, F> EventRoutine for Repeat<T, F>
450where
451    T: EventRoutine,
452    F: FnMut(T::Return) -> Handled<U, T>,
453{
454    type Return = U;
455    type Data = T::Data;
456    type View = T::View;
457    type Event = T::Event;
458
459    fn handle<EP>(self, data: &mut Self::Data, view: &Self::View, event_or_peek: EP) -> Handled<Self::Return, Self>
460    where
461        EP: EventOrPeek<Event = Self::Event>,
462    {
463        let Self { t, mut f } = self;
464        match t.handle(data, view, event_or_peek) {
465            Handled::Continue(t) => Handled::Continue(Self { t, f }),
466            Handled::Return(r) => match f(r) {
467                Handled::Continue(t) => Handled::Continue(Self { t, f }),
468                Handled::Return(r) => Handled::Return(r),
469            },
470        }
471    }
472
473    fn view<G, C>(&self, data: &Self::Data, view: &mut Self::View, context: ViewContext<C>, frame: &mut G)
474    where
475        G: Frame,
476        C: ColModify,
477    {
478        self.t.view(data, view, context, frame)
479    }
480}
481
482pub struct EventRoutineView<'e, 'v, E: EventRoutine> {
483    pub event_routine: &'e E,
484    pub view: &'v mut E::View,
485}
486
487impl<'e, 'v, 'd, E> View<&'d E::Data> for EventRoutineView<'e, 'v, E>
488where
489    E: EventRoutine,
490{
491    fn view<F: Frame, C: ColModify>(&mut self, data: &'d E::Data, context: ViewContext<C>, frame: &mut F) {
492        self.event_routine.view(data, self.view, context, frame)
493    }
494}
495
496pub trait Decorate {
497    type View;
498    type Data;
499
500    fn view<E, F, C>(
501        data: &Self::Data,
502        event_routine_view: EventRoutineView<E>,
503        context: ViewContext<C>,
504        frame: &mut F,
505    ) where
506        E: EventRoutine<Data = Self::Data, View = Self::View>,
507        F: Frame,
508        C: ColModify;
509}
510
511pub struct Decorated<T, D> {
512    t: T,
513    d: D,
514}
515
516impl<T, D> EventRoutine for Decorated<T, D>
517where
518    T: EventRoutine,
519    D: Decorate<View = T::View, Data = T::Data>,
520{
521    type Return = T::Return;
522    type Data = T::Data;
523    type View = T::View;
524    type Event = T::Event;
525
526    fn handle<EP>(self, data: &mut Self::Data, view: &Self::View, event_or_peek: EP) -> Handled<Self::Return, Self>
527    where
528        EP: EventOrPeek<Event = Self::Event>,
529    {
530        let Self { t, d } = self;
531        t.handle(data, view, event_or_peek).map_continue(|t| Self { t, d })
532    }
533
534    fn view<F, C>(&self, data: &Self::Data, view: &mut Self::View, context: ViewContext<C>, frame: &mut F)
535    where
536        F: Frame,
537        C: ColModify,
538    {
539        let event_routine_view = EventRoutineView {
540            event_routine: &self.t,
541            view,
542        };
543        D::view(data, event_routine_view, context, frame)
544    }
545}
546
547pub struct OnEvent<T, F> {
548    t: T,
549    f: F,
550}
551
552impl<T, F> EventRoutine for OnEvent<T, F>
553where
554    T: EventRoutine,
555    F: FnMut(&mut &mut T::Data, &T::Event),
556{
557    type Return = T::Return;
558    type Data = T::Data;
559    type View = T::View;
560    type Event = T::Event;
561
562    fn handle<EP>(self, data: &mut Self::Data, view: &Self::View, event_or_peek: EP) -> Handled<Self::Return, Self>
563    where
564        EP: EventOrPeek<Event = Self::Event>,
565    {
566        let on_peek = |(s, data)| {
567            let Self { t, f } = s;
568            t.handle(data, view, Peek::new()).map_continue(|t| Self { t, f })
569        };
570        let on_event = |(s, mut data), event| {
571            let Self { t, mut f } = s;
572            (f)(&mut data, &event);
573            t.handle(data, view, Event::new(event)).map_continue(|t| Self { t, f })
574        };
575        event_or_peek.with((self, data), on_event, on_peek)
576    }
577
578    fn view<G, C>(&self, data: &Self::Data, view: &mut Self::View, context: ViewContext<C>, frame: &mut G)
579    where
580        G: Frame,
581        C: ColModify,
582    {
583        self.t.view(data, view, context, frame);
584    }
585}
586
587make_either!(Either = Left | Right);
588
589#[macro_export]
590macro_rules! make_either {
591    ($type:ident = $first:ident | $($rest:ident)|*) => {
592        pub enum $type<$first, $($rest),*> {
593            $first($first),
594            $($rest($rest)),*
595        }
596        impl<$first, $($rest),*> EventRoutine for $type<$first, $($rest),*>
597            where
598                $first: EventRoutine,
599                $($rest: EventRoutine<Data = $first::Data, View = $first::View, Return = $first::Return, Event = $first::Event>),*
600        {
601            type Return = $first::Return;
602            type Data = $first::Data;
603            type View = $first::View;
604            type Event = $first::Event;
605
606            fn handle<EP>(self, data: &mut Self::Data, view: &Self::View, event_or_peek: EP) -> Handled<Self::Return, Self>
607            where
608                EP: EventOrPeek<Event = Self::Event>,
609            {
610                match self {
611                    $type::$first(x) => x.handle(data, view, event_or_peek).map_continue($type::$first),
612                    $($type::$rest(x) => x.handle(data, view, event_or_peek).map_continue($type::$rest)),*
613                }
614            }
615            fn view<FR, CM>(&self, data: &Self::Data, view: &mut Self::View, context: ViewContext<CM>, frame: &mut FR)
616            where
617                FR: Frame,
618                CM: ColModify,
619            {
620                match self {
621                    $type::$first(x) => x.view(data, view, context, frame),
622                    $($type::$rest(x) => x.view(data, view, context, frame)),*
623                }
624            }
625        }
626    };
627}