use crate::widgets::info::InfoTab;
use crate::{App, AppEvent, InputMode};
use crossterm::event::{KeyCode, KeyEvent};
impl App {
pub(crate) fn info_key(&mut self, event: &KeyEvent) -> Option<AppEvent> {
let schema_tab = self.info_modal.active_tab == InfoTab::Schema;
let notes_tab = self.info_modal.active_tab == InfoTab::Notes;
let documentation_tab = self.info_modal.active_tab == InfoTab::Documentation
&& self.info_documentation.is_open();
let detail_tab = matches!(
self.info_modal.active_tab,
InfoTab::Metadata | InfoTab::Format
);
let tables: Option<Vec<String>> = detail_tab
.then(|| self.data_table_state.as_ref()?.format_detail())
.flatten()
.filter(|d| self.info_modal.active_tab == InfoTab::Format && !d.tables.is_empty())
.map(|d| d.list.iter().map(|(key, _)| key.clone()).collect());
let notes = self
.data_table_state
.as_ref()
.map(|s| s.notes().len())
.unwrap_or(0);
let total_rows = self
.data_table_state
.as_ref()
.map(|s| s.schema().len())
.unwrap_or(0);
let visible = self.info_modal.schema_visible_height;
match event.code {
KeyCode::Esc | KeyCode::Char('i') if event.is_press() => {
self.info_modal.close();
self.input_mode = InputMode::Normal;
}
KeyCode::Char('c') if event.is_press() && self.row_estimate().is_some() => {
self.count_exactly();
}
KeyCode::Char('x') if event.is_press() => {
if let Some(path) = self.hex_target() {
self.info_modal.close();
self.input_mode = InputMode::Normal;
self.open_hex(path, crate::hex_view::Origin::Info, false, None);
}
}
KeyCode::Char('H') if event.is_press() && schema_tab => {
if self.header_toggle_offered() {
self.info_modal.close();
self.input_mode = InputMode::Normal;
return self.toggle_header();
}
}
KeyCode::Left | KeyCode::Char('h') | KeyCode::BackTab if event.is_press() => {
let offered = self.info_tabs_on_offer();
self.info_modal.switch_tab_prev(offered);
}
KeyCode::Right | KeyCode::Char('l') | KeyCode::Tab if event.is_press() => {
let offered = self.info_tabs_on_offer();
self.info_modal.switch_tab(offered);
}
KeyCode::Down | KeyCode::Char('j') if event.is_press() && schema_tab => {
self.info_modal.schema_table_down(total_rows, visible);
}
KeyCode::Up | KeyCode::Char('k') if event.is_press() && schema_tab => {
self.info_modal.schema_table_up(total_rows, visible);
}
KeyCode::Down | KeyCode::Char('j') if event.is_press() && documentation_tab => {
self.info_documentation.move_cursor(1);
}
KeyCode::Up | KeyCode::Char('k') if event.is_press() && documentation_tab => {
self.info_documentation.move_cursor(-1);
}
KeyCode::PageDown if event.is_press() && documentation_tab => {
let page = self.info_documentation.view_height.max(1) as isize;
self.info_documentation.move_cursor(page);
}
KeyCode::PageUp if event.is_press() && documentation_tab => {
let page = self.info_documentation.view_height.max(1) as isize;
self.info_documentation.move_cursor(-page);
}
KeyCode::Enter | KeyCode::Char(' ') if event.is_press() && documentation_tab => {
self.info_documentation.toggle_legend();
}
KeyCode::Char('o') if event.is_press() && documentation_tab => {
let link = self.info_documentation.link();
self.ask_to_open_link(link);
}
KeyCode::Char('y') if event.is_press() && documentation_tab => {
match self.info_documentation.copy_text() {
Some(text) => self.copy_documentation_text(text),
None => self.flash_note("Nothing to copy on this line".to_string()),
}
}
KeyCode::Down | KeyCode::Char('j') if event.is_press() && notes_tab => {
self.info_modal.notes_move(1, notes);
}
KeyCode::Up | KeyCode::Char('k') if event.is_press() && notes_tab => {
self.info_modal.notes_move(-1, notes);
}
KeyCode::Enter if event.is_press() && notes_tab => {
self.read_the_selected_note_s_column_as_text();
}
KeyCode::Enter if event.is_press() && schema_tab => {
let column = self.data_table_state.as_ref().and_then(|s| {
s.schema()
.get_at_index(self.info_modal.schema_selected_index)
.map(|(name, _)| name.to_string())
});
if let Some(column) = column {
self.open_retype(&column);
}
}
KeyCode::Down | KeyCode::Char('j') if event.is_press() && tables.is_some() => {
let last = tables.as_ref().map_or(0, |t| t.len().saturating_sub(1));
self.info_modal.detail_selected = (self.info_modal.detail_selected + 1).min(last);
}
KeyCode::Up | KeyCode::Char('k') if event.is_press() && tables.is_some() => {
self.info_modal.detail_selected = self.info_modal.detail_selected.saturating_sub(1);
}
KeyCode::PageDown if event.is_press() && tables.is_some() => {
let last = tables.as_ref().map_or(0, |t| t.len().saturating_sub(1));
let page = self.info_modal.detail_visible.max(1);
self.info_modal.detail_selected =
(self.info_modal.detail_selected + page).min(last);
}
KeyCode::PageUp if event.is_press() && tables.is_some() => {
let page = self.info_modal.detail_visible.max(1);
self.info_modal.detail_selected =
self.info_modal.detail_selected.saturating_sub(page);
}
KeyCode::Home if event.is_press() && tables.is_some() => {
self.info_modal.detail_selected = 0;
}
KeyCode::End if event.is_press() && tables.is_some() => {
let last = tables.as_ref().map_or(0, |t| t.len().saturating_sub(1));
self.info_modal.detail_selected = last;
}
KeyCode::Enter if event.is_press() && tables.is_some() => {
return self.open_table_from_info(tables.as_deref().unwrap_or_default());
}
KeyCode::Down | KeyCode::Char('j') if event.is_press() && detail_tab => {
self.info_modal.detail_scroll_by(1);
}
KeyCode::Up | KeyCode::Char('k') if event.is_press() && detail_tab => {
self.info_modal.detail_scroll_by(-1);
}
KeyCode::PageDown if event.is_press() && detail_tab => {
self.info_modal.detail_page(true);
}
KeyCode::PageUp if event.is_press() && detail_tab => {
self.info_modal.detail_page(false);
}
KeyCode::Home if event.is_press() && detail_tab => {
self.info_modal.detail_scroll = 0;
}
KeyCode::End if event.is_press() && detail_tab => {
self.info_modal.detail_scroll = usize::MAX;
}
_ => {}
}
None
}
fn open_table_from_info(&mut self, keys: &[String]) -> Option<AppEvent> {
let name = keys.get(self.info_modal.detail_selected)?.clone();
let detail = self.data_table_state.as_ref()?.format_detail()?;
if !detail.tables.contains(&name) {
self.flash_note("Not a table".to_string());
return None;
}
if detail.table.as_ref() == Some(&name) {
self.flash_note("Already open".to_string());
return None;
}
self.info_modal.close();
self.input_mode = InputMode::Normal;
self.switch_table(Some(name))
}
}