pub mod cmdline;
pub mod error;
pub mod highlight;
pub mod keymap;
pub mod query;
pub mod snapshot;
pub mod state;
pub mod ui;
pub use error::{Error, Result};
use ratatui::DefaultTerminal;
use ratatui::crossterm::event::{self, Event, KeyEventKind};
use keymap::Command;
use state::{AppState, Level, Mode};
pub fn run(terminal: &mut DefaultTerminal, mut state: AppState) -> Result<()> {
loop {
state.ensure_content();
terminal.draw(|f| ui::draw(f, &mut state))?;
match event::read()? {
Event::Key(key) if key.kind != KeyEventKind::Release => match state.mode {
Mode::Command => cmdline::handle_key(&mut state, &key),
Mode::Help => state.mode = Mode::Normal,
Mode::Normal => match keymap::lookup(&state, &key) {
Some(Command::Edit) => run_editor(terminal, &mut state)?,
Some(cmd) => state::apply(&mut state, cmd),
None => {}
},
},
_ => {}
}
if state.quit {
return Ok(());
}
}
}
fn run_editor(terminal: &mut DefaultTerminal, state: &mut AppState) -> Result<()> {
let Some((r, label)) = state::edit_target(state) else {
state.set_message(Level::Error, "no jot selected");
return Ok(());
};
ratatui::restore();
let result = state.app.edit(&cuj::Opts::default(), &r);
*terminal = ratatui::init();
terminal.clear()?;
match result {
Ok(true) => {
state::apply(state, Command::Reload);
state.set_message(Level::Info, format!("edited {label}"));
}
Ok(false) => state.set_message(Level::Info, format!("{label} unchanged")),
Err(e) => state.set_message(Level::Error, e.to_string()),
}
Ok(())
}