prototty_event_routine 0.29.0

Pseudo-synchronous composable event-based state machines for prototty apps
Documentation
use crate::*;
use prototty_input::keys;

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum CommonEvent {
    Input(Input),
    Frame(Duration),
}

impl From<Input> for CommonEvent {
    fn from(input: Input) -> Self {
        CommonEvent::Input(input)
    }
}

impl From<Duration> for CommonEvent {
    fn from(duration: Duration) -> Self {
        CommonEvent::Frame(duration)
    }
}

pub struct ConvertInputToCommonEvent<T>(pub(crate) T);

impl<T> EventRoutine for ConvertInputToCommonEvent<T>
where
    T: EventRoutine<Event = Input>,
{
    type Return = T::Return;
    type Data = T::Data;
    type View = T::View;
    type Event = CommonEvent;

    fn handle<EP>(self, data: &mut Self::Data, view: &Self::View, event_or_peek: EP) -> Handled<Self::Return, Self>
    where
        EP: EventOrPeek<Event = Self::Event>,
    {
        event_or_peek.with(
            self,
            |s, event| match event {
                CommonEvent::Input(input) => s.0.handle(data, view, Event::new(input)).map_continue(Self),
                CommonEvent::Frame(_) => Handled::Continue(s),
            },
            Handled::Continue,
        )
    }

    fn view<G, C>(&self, data: &Self::Data, view: &mut Self::View, context: ViewContext<C>, frame: &mut G)
    where
        G: Frame,
        C: ColModify,
    {
        self.0.view(data, view, context, frame)
    }
}

pub struct ReturnOnExit<T, F> {
    pub(crate) t: T,
    pub(crate) f: F,
}

impl<T, F> EventRoutine for ReturnOnExit<T, F>
where
    T: EventRoutine<Event = CommonEvent>,
    F: FnOnce(&mut T::Data) -> T::Return,
{
    type Return = T::Return;
    type Data = T::Data;
    type View = T::View;
    type Event = CommonEvent;

    fn handle<EP>(self, data: &mut Self::Data, view: &Self::View, event_or_peek: EP) -> Handled<Self::Return, Self>
    where
        EP: EventOrPeek<Event = Self::Event>,
    {
        event_or_peek.with(
            (self, data),
            |(s, data), event| {
                let Self { t, f } = s;
                if event == CommonEvent::Input(Input::Keyboard(keys::ETX)) {
                    Handled::Return(f(data))
                } else {
                    t.handle(data, view, Event::new(event)).map_continue(|t| Self { t, f })
                }
            },
            |(s, data)| {
                let Self { t, f } = s;
                t.handle(data, view, Peek::new()).map_continue(|t| Self { t, f })
            },
        )
    }

    fn view<G, C>(&self, data: &Self::Data, view: &mut Self::View, context: ViewContext<C>, frame: &mut G)
    where
        G: Frame,
        C: ColModify,
    {
        self.t.view(data, view, context, frame)
    }
}