1pub mod cmdline;
12pub mod error;
13pub mod highlight;
14pub mod keymap;
15pub mod query;
16pub mod snapshot;
17pub mod state;
18pub mod ui;
19
20pub use error::{Error, Result};
21
22use ratatui::DefaultTerminal;
23use ratatui::crossterm::event::{self, Event, KeyEventKind};
24
25use keymap::Command;
26use state::{AppState, Level, Mode};
27
28pub fn run(terminal: &mut DefaultTerminal, mut state: AppState) -> Result<()> {
31 loop {
32 state.ensure_content();
33 terminal.draw(|f| ui::draw(f, &mut state))?;
34 match event::read()? {
35 Event::Key(key) if key.kind != KeyEventKind::Release => match state.mode {
36 Mode::Command => cmdline::handle_key(&mut state, &key),
37 Mode::Help => state.mode = Mode::Normal,
38 Mode::Normal => match keymap::lookup(&state, &key) {
39 Some(Command::Edit) => run_editor(terminal, &mut state)?,
40 Some(cmd) => state::apply(&mut state, cmd),
41 None => {}
42 },
43 },
44 _ => {}
45 }
46 if state.quit {
47 return Ok(());
48 }
49 }
50}
51
52fn run_editor(terminal: &mut DefaultTerminal, state: &mut AppState) -> Result<()> {
56 let Some((r, label)) = state::edit_target(state) else {
57 state.set_message(Level::Error, "no jot selected");
58 return Ok(());
59 };
60 ratatui::restore();
61 let result = state.app.edit(&cuj::Opts::default(), &r);
62 *terminal = ratatui::init();
63 terminal.clear()?;
64 match result {
65 Ok(true) => {
66 state::apply(state, Command::Reload);
67 state.set_message(Level::Info, format!("edited {label}"));
68 }
69 Ok(false) => state.set_message(Level::Info, format!("{label} unchanged")),
70 Err(e) => state.set_message(Level::Error, e.to_string()),
71 }
72 Ok(())
73}