use crossterm::event::{KeyCode, KeyEvent, KeyModifiers};
use crate::app::{App, Mode};
pub fn handle_key_event(app: &mut App, key: KeyEvent) {
if key.modifiers.contains(KeyModifiers::CONTROL) && key.code == KeyCode::Char('c') {
app.mode = Mode::Input;
return;
}
if key.modifiers.contains(KeyModifiers::CONTROL) && key.code == KeyCode::Char('l') {
if matches!(app.mode, Mode::Normal | Mode::Input) {
app.clear_buffer();
return;
}
}
if matches!(app.mode, Mode::Normal | Mode::Input) {
match key.code {
KeyCode::F(n) if n >= 1 && n <= 8 => {
app.send_quicksend((n - 1) as usize);
return;
}
_ => {}
}
}
match app.mode {
Mode::Normal => handle_normal_mode(app, key),
Mode::Input => handle_input_mode(app, key),
Mode::Search => handle_search_mode(app, key),
Mode::PortSelect => handle_port_select_mode(app, key),
Mode::Settings => handle_settings_mode(app, key),
Mode::Help => handle_help_mode(app, key),
Mode::MacroSelect => handle_macro_select_mode(app, key),
Mode::Filter => handle_filter_mode(app, key),
}
}
fn handle_normal_mode(app: &mut App, key: KeyEvent) {
match key.code {
KeyCode::Char('q') => app.should_quit = true,
KeyCode::Char('i') => app.mode = Mode::Input,
KeyCode::Char('j') | KeyCode::Down => app.scroll_down(1),
KeyCode::Char('k') | KeyCode::Up => app.scroll_up(1),
KeyCode::Char('x') => app.show_sent = !app.show_sent,
KeyCode::Char('G') => app.scroll_to_bottom(),
KeyCode::Char('g') => app.scroll_to_top(),
KeyCode::Char('d') if key.modifiers.contains(KeyModifiers::CONTROL) => {
app.scroll_down(10);
}
KeyCode::Char('u') if key.modifiers.contains(KeyModifiers::CONTROL) => {
app.scroll_up(10);
}
KeyCode::PageDown => app.scroll_down(20),
KeyCode::PageUp => app.scroll_up(20),
KeyCode::Char('/') => app.start_search(),
KeyCode::Char('n') => app.search_next(),
KeyCode::Char('N') => app.search_prev(),
KeyCode::Char('t') => app.show_timestamps = !app.show_timestamps,
KeyCode::Char('h') => app.toggle_hex_mode(),
KeyCode::Char('e') => app.toggle_line_endings(),
KeyCode::Char('l') => app.toggle_logging(),
KeyCode::Char('p') => app.open_port_selector(),
KeyCode::Char('s') => app.open_settings(),
KeyCode::Char('m') => app.open_macro_selector(),
KeyCode::Char('f') => app.open_filter_popup(),
KeyCode::Char('c') => app.toggle_connection(),
KeyCode::Char('?') => app.mode = Mode::Help,
KeyCode::Char(c) => {
app.mode = Mode::Input;
app.input_char(c);
}
_ => {}
}
}
fn handle_input_mode(app: &mut App, key: KeyEvent) {
match key.code {
KeyCode::Enter => {
app.send_command();
}
KeyCode::Esc => {
app.mode = Mode::Normal;
}
KeyCode::Backspace => {
app.input_backspace();
}
KeyCode::Delete => {
app.input_delete();
}
KeyCode::Left if key.modifiers.contains(KeyModifiers::CONTROL) => {
app.input_cursor_word_left();
}
KeyCode::Right if key.modifiers.contains(KeyModifiers::CONTROL) => {
app.input_cursor_word_right();
}
KeyCode::Left => {
app.input_cursor_left();
}
KeyCode::Right => {
if app.input_cursor == app.input_text.len() && app.ghost_suggestion.is_some() {
app.accept_suggestion();
} else {
app.input_cursor_right();
}
}
KeyCode::Tab => {
if app.ghost_suggestion.is_some() {
app.accept_suggestion();
}
}
KeyCode::Up => {
app.history_previous();
}
KeyCode::Down => {
app.history_next();
}
KeyCode::Home => {
app.input_cursor_home();
}
KeyCode::End => {
app.input_cursor_end();
}
KeyCode::PageUp => app.scroll_up(20),
KeyCode::PageDown => app.scroll_down(20),
KeyCode::Char('w') if key.modifiers.contains(KeyModifiers::CONTROL) => {
app.input_delete_word_back();
}
KeyCode::Char('u') if key.modifiers.contains(KeyModifiers::CONTROL) => {
app.input_kill_line();
}
KeyCode::Char('h') if key.modifiers.contains(KeyModifiers::CONTROL) => {
app.toggle_hex_input();
}
KeyCode::Char('p') if key.modifiers.contains(KeyModifiers::CONTROL) => {
app.open_port_selector();
}
KeyCode::Char('s') if key.modifiers.contains(KeyModifiers::CONTROL) => {
app.open_settings();
}
KeyCode::Char('l') if key.modifiers.contains(KeyModifiers::CONTROL) => {
app.toggle_logging();
}
KeyCode::Char('a') if key.modifiers.contains(KeyModifiers::CONTROL) => {
app.input_cursor_home();
}
KeyCode::Char('e') if key.modifiers.contains(KeyModifiers::CONTROL) => {
app.input_cursor_end();
}
KeyCode::Char(c) => {
app.input_char(c);
}
_ => {}
}
}
fn handle_search_mode(app: &mut App, key: KeyEvent) {
match key.code {
KeyCode::Esc => {
app.end_search();
}
KeyCode::Enter => {
app.mode = Mode::Input;
}
KeyCode::Backspace => {
app.search_backspace();
}
KeyCode::Char('n') if key.modifiers.contains(KeyModifiers::CONTROL) => {
app.search_next();
}
KeyCode::Char('p') if key.modifiers.contains(KeyModifiers::CONTROL) => {
app.search_prev();
}
KeyCode::Down => {
app.search_next();
}
KeyCode::Up => {
app.search_prev();
}
KeyCode::Char(c) => {
app.search_char(c);
}
_ => {}
}
}
fn handle_port_select_mode(app: &mut App, key: KeyEvent) {
match key.code {
KeyCode::Esc | KeyCode::Char('q') => {
app.mode = Mode::Input;
}
KeyCode::Enter => {
app.connect_selected_port();
}
KeyCode::Up | KeyCode::Char('k') => {
if app.port_select_index > 0 {
app.port_select_index -= 1;
}
}
KeyCode::Down | KeyCode::Char('j') => {
if app.port_select_index + 1 < app.available_ports.len() {
app.port_select_index += 1;
}
}
KeyCode::Char('r') => {
app.available_ports = crate::serial::detector::available_ports();
app.port_select_index = 0;
}
KeyCode::Char('a') => {
if let Some(port) = app.available_ports.get(app.port_select_index) {
let port_name = port.name.clone();
app.auto_detect_baud(&port_name);
}
}
_ => {}
}
}
fn handle_help_mode(app: &mut App, key: KeyEvent) {
match key.code {
KeyCode::Esc | KeyCode::Char('q') | KeyCode::Char('?') => {
app.mode = Mode::Input;
}
_ => {}
}
}
fn handle_settings_mode(app: &mut App, key: KeyEvent) {
match key.code {
KeyCode::Esc | KeyCode::Char('q') => {
app.mode = Mode::Input;
}
KeyCode::Enter => {
app.apply_settings();
}
KeyCode::Up | KeyCode::Char('k') => {
if app.settings_field > 0 {
app.settings_field -= 1;
}
}
KeyCode::Down | KeyCode::Char('j') => {
if app.settings_field < 5 {
app.settings_field += 1;
}
}
KeyCode::Right | KeyCode::Char('l') | KeyCode::Tab => {
app.settings_next_value();
}
KeyCode::Left | KeyCode::Char('h') => {
app.settings_prev_value();
}
_ => {}
}
}
fn handle_macro_select_mode(app: &mut App, key: KeyEvent) {
match key.code {
KeyCode::Esc | KeyCode::Char('q') => {
app.mode = Mode::Input;
}
KeyCode::Enter => {
app.execute_selected_macro();
app.mode = Mode::Input;
}
KeyCode::Up | KeyCode::Char('k') => {
if app.macro_select_index > 0 {
app.macro_select_index -= 1;
}
}
KeyCode::Down | KeyCode::Char('j') => {
let count = app.macros.list().len();
if app.macro_select_index + 1 < count {
app.macro_select_index += 1;
}
}
_ => {}
}
}
fn handle_filter_mode(app: &mut App, key: KeyEvent) {
match key.code {
KeyCode::Esc => {
app.mode = Mode::Input;
}
KeyCode::Enter => {
app.submit_filter();
}
KeyCode::Tab => {
app.filter_mode_is_exclude = !app.filter_mode_is_exclude;
}
KeyCode::Backspace => {
app.filter_input.pop();
}
KeyCode::Char('d') if app.filter_input.is_empty() => {
let count = app.filter.count();
if count > 0 && app.filter_select_index < count {
app.remove_filter(app.filter_select_index);
}
}
KeyCode::Up | KeyCode::Char('k') if app.filter_input.is_empty() => {
if app.filter_select_index > 0 {
app.filter_select_index -= 1;
}
}
KeyCode::Down | KeyCode::Char('j') if app.filter_input.is_empty() => {
let count = app.filter.count();
if app.filter_select_index + 1 < count {
app.filter_select_index += 1;
}
}
KeyCode::Char(c) => {
app.filter_input.push(c);
}
_ => {}
}
}