1use std::io;
4
5use crossterm::event::{self, Event, KeyEventKind};
6use ratatui::widgets::Widget;
7
8use super::app::{App, AppResult, UpdateResult};
9use super::backend::InlineTerminal;
10
11pub fn run(mut app: App) -> io::Result<Option<AppResult>> {
16 let height = app.terminal_height();
17 let mut term = InlineTerminal::new(height)?;
18
19 loop {
20 let new_height = app.terminal_height();
22 if new_height != term.height() {
23 tracing::trace!(old_height = term.height(), new_height, "resize viewport");
24 term.resize(new_height)?;
25 }
26
27 term.terminal().draw(|frame| {
28 let area = frame.area();
29 (&app).render(area, frame.buffer_mut());
30 if let Some((x, y)) = app.cursor_position(area) {
31 frame.set_cursor_position((x, y));
32 }
33 })?;
34
35 if let Event::Key(key) = event::read()? {
36 if key.kind != KeyEventKind::Press {
37 tracing::trace!(?key, "ignored non-press key event");
38 continue;
39 }
40 let result = app.update(key);
41 tracing::trace!(?key, ?result, "handled key event");
42 match result {
43 UpdateResult::Continue => {}
44 UpdateResult::Done => return Ok(app.extract_result()),
45 UpdateResult::Cancelled => return Ok(None),
46 }
47 }
48 }
49}