use anyhow::{Context, Result};
use crossterm::event::{Event, KeyCode, KeyEvent, KeyModifiers};
use tui_input::backend::crossterm::EventHandler;
use crate::app::{App, InputMode, View};
pub fn handle_log_keys(app: &mut App, key: KeyEvent) -> Result<()> {
let mut check_load_more = false;
match key.code {
KeyCode::Char('q') | KeyCode::Esc => {
app.quit();
}
KeyCode::Char('j') | KeyCode::Down => {
app.select_next();
check_load_more = true;
}
KeyCode::Char('k') | KeyCode::Up => {
app.select_previous();
}
KeyCode::Char('g') | KeyCode::Home => {
app.select_first();
}
KeyCode::Char('G') | KeyCode::End => {
app.select_last();
check_load_more = true;
}
KeyCode::Enter => {
app.open_detail().context("failed to open detail view")?;
}
KeyCode::Char('d') if key.modifiers.contains(KeyModifiers::CONTROL) => {
app.page_down(10);
check_load_more = true;
}
KeyCode::Char('u') if key.modifiers.contains(KeyModifiers::CONTROL) => {
app.page_up(10);
}
KeyCode::PageDown => {
app.page_down(10);
check_load_more = true;
}
KeyCode::PageUp => {
app.page_up(10);
}
KeyCode::Char('a') => {
app.show_abandon_confirm();
}
KeyCode::Char('s') => {
app.show_squash_confirm();
}
KeyCode::Char('f') => {
app.execute_git_fetch()
.context("failed to execute jj git fetch")?;
}
KeyCode::Char('p') => {
app.show_push_confirm();
}
KeyCode::Char('u') => {
app.show_undo_confirm();
}
KeyCode::Char('n') => {
app.execute_new().context("failed to execute jj new")?;
}
KeyCode::Char('N') => {
app.start_input_mode(InputMode::NewWithMessage);
}
KeyCode::Char('e') => {
app.execute_edit().context("failed to execute jj edit")?;
}
KeyCode::Char('d') => {
app.start_input_mode(InputMode::Describe);
}
KeyCode::Char('b') => {
app.start_input_mode(InputMode::BookmarkSet);
}
KeyCode::Char('r') => {
app.start_input_mode(InputMode::RebaseDestination);
}
_ => {}
}
if check_load_more {
app.request_load_more_check();
}
Ok(())
}
pub fn handle_input_keys(app: &mut App, key: KeyEvent, event: &Event) -> Result<()> {
match key.code {
KeyCode::Enter => {
app.submit_input().context("failed to submit input")?;
}
KeyCode::Esc => {
app.cancel_input_mode();
}
_ => {
app.input.handle_event(event);
}
}
Ok(())
}
pub fn handle_modal_keys(app: &mut App, key: KeyEvent) -> Result<()> {
match key.code {
KeyCode::Char('y') | KeyCode::Char('Y') => {
app.confirm_action().context("failed to execute action")?;
}
KeyCode::Char('n') | KeyCode::Char('N') | KeyCode::Esc => {
app.close_modal();
}
_ => {}
}
Ok(())
}
pub fn handle_detail_keys(app: &mut App, key: KeyEvent) -> Result<()> {
match key.code {
KeyCode::Char('q') | KeyCode::Esc => {
app.close_detail();
}
KeyCode::Char('j') | KeyCode::Down => {
app.detail_scroll_down(1);
}
KeyCode::Char('k') | KeyCode::Up => {
app.detail_scroll_up(1);
}
KeyCode::Char('d') if key.modifiers.contains(KeyModifiers::CONTROL) => {
app.detail_scroll_down(10);
}
KeyCode::Char('u') if key.modifiers.contains(KeyModifiers::CONTROL) => {
app.detail_scroll_up(10);
}
KeyCode::PageDown => {
app.detail_scroll_down(10);
}
KeyCode::PageUp => {
app.detail_scroll_up(10);
}
KeyCode::Char('d') => {
app.open_diff_view().context("failed to open diff view")?;
}
_ => {}
}
Ok(())
}
pub fn handle_diff_keys(app: &mut App, key: KeyEvent) -> Result<()> {
match key.code {
KeyCode::Char('q') | KeyCode::Esc => {
app.close_diff();
}
KeyCode::Char('j') | KeyCode::Down => {
app.diff_select_next();
app.refresh_diff_text().context("failed to refresh diff")?;
}
KeyCode::Char('k') | KeyCode::Up => {
app.diff_select_previous();
app.refresh_diff_text().context("failed to refresh diff")?;
}
KeyCode::Char('d') if key.modifiers.contains(KeyModifiers::CONTROL) => {
app.diff_scroll_down(10);
}
KeyCode::Char('u') if key.modifiers.contains(KeyModifiers::CONTROL) => {
app.diff_scroll_up(10);
}
KeyCode::PageDown => {
app.diff_scroll_down(10);
}
KeyCode::PageUp => {
app.diff_scroll_up(10);
}
KeyCode::Right => {
app.diff_scroll_right(8);
}
KeyCode::Left => {
app.diff_scroll_left(8);
}
_ => {}
}
Ok(())
}
pub fn dispatch_key_event(app: &mut App, key: KeyEvent, event: &Event) -> Result<bool> {
if app.is_input_mode() {
handle_input_keys(app, key, event)?;
return Ok(false);
}
if app.is_modal_open() {
handle_modal_keys(app, key)?;
return Ok(false);
}
if app.show_help {
match key.code {
KeyCode::Esc | KeyCode::Char('?') => app.close_help(),
_ => {}
}
return Ok(true);
}
if key.code == KeyCode::Char('?') {
app.toggle_help();
return Ok(true);
}
match app.view {
View::Log => handle_log_keys(app, key)?,
View::Detail => handle_detail_keys(app, key)?,
View::Diff => handle_diff_keys(app, key)?,
}
Ok(false)
}