use crate::core::render::Rendered;
use crate::error::Result;
use crate::input::Outcome;
use crate::input::event::{EventSource, InputEvent};
use crate::output::live::InPlace;
pub(crate) enum Flow<T> {
Continue,
Submit(T),
Cancel,
Shortcut(i32),
Refresh,
}
pub(crate) fn run_prompt<S, E, R, H, T>(
source: &mut E,
state: &mut S,
mut render: R,
mut handle: H,
) -> Result<Outcome<T>>
where
E: EventSource,
R: FnMut(&S, bool) -> Rendered,
H: FnMut(&mut S, InputEvent) -> Flow<T>,
{
let mut inplace = if source.is_interactive() {
InPlace::new(false)
} else {
InPlace::silent()
};
loop {
let frame = render(state, false);
inplace.draw(&frame)?;
let event = source.next_event()?;
match handle(state, event) {
Flow::Continue => {}
Flow::Refresh => inplace.reset(),
Flow::Submit(value) => {
let frame = render(state, true);
inplace.draw(&frame)?;
inplace.finish()?;
return Ok(Outcome::Submitted(value));
}
Flow::Cancel => {
inplace.finish()?;
return Ok(Outcome::Cancelled);
}
Flow::Shortcut(id) => {
inplace.finish()?;
return Ok(Outcome::Shortcut(id));
}
}
}
}