From ec1aa4fbe8c521a376d803a74cab0871cb18d0ae Mon Sep 17 00:00:00 2001 From: GarandPLG Date: Tue, 10 Mar 2026 16:29:27 +0100 Subject: [PATCH] Refactor keybinding handling and update widgets MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Remove the old `keybindings.rs` and stop re‑exporting its symbols. - Add view‑specific handling: `App::handle_key_event` now delegates to `main_menu_keybindings` when the view is `MainMenu`. - Update imports in `app.rs`, `widget.rs`, and widget modules to use the new `app::keybindings` path. - Enhance `keybindings_widget` to display ↑, ↓ and “Space” for special keys. - Change main menu layout percentages from 90/10 to 87/13. - Reorder the `clap` import in `cli.rs` for consistency. --- src/app/app.rs | 18 ++++---- src/app/keybindings.rs | 45 ------------------ src/app/keybindings/keybindings.rs | 73 ++++++++++++++++++++++++++++++ src/app/keybindings/main_menu.rs | 14 ++++++ src/app/keybindings/mod.rs | 7 +++ src/app/mod.rs | 3 -- src/app/widget.rs | 3 +- src/app/widgets/keybindings.rs | 6 ++- src/app/widgets/main_menu.rs | 5 +- src/cli.rs | 3 +- 10 files changed, 112 insertions(+), 65 deletions(-) delete mode 100644 src/app/keybindings.rs create mode 100644 src/app/keybindings/keybindings.rs create mode 100644 src/app/keybindings/main_menu.rs create mode 100644 src/app/keybindings/mod.rs diff --git a/src/app/app.rs b/src/app/app.rs index 967b3b4..453256a 100644 --- a/src/app/app.rs +++ b/src/app/app.rs @@ -1,4 +1,4 @@ -use crate::app::{Action, event_to_action}; +use crate::app::keybindings::{Action, event_to_action, main_menu_keybindings}; use clap::ValueEnum; use ratatui::{ DefaultTerminal, Frame, @@ -59,13 +59,15 @@ impl App { } fn handle_key_event(&mut self, key_event: KeyEvent) -> Result<()> { - // if key_event.kind == KeyEventKind::Press && key_event.code == KeyCode::Char('q') { - // self.exit = true; - // } - - if let Some(action) = event_to_action(&key_event) { - match action { - Action::Quit => self.exit = true, + match self.window { + View::MainMenu => main_menu_keybindings(self, &key_event), + _ => { + if let Some(action) = event_to_action(&key_event) { + match action { + Action::Quit => self.exit = true, + _ => (), + } + } } } diff --git a/src/app/keybindings.rs b/src/app/keybindings.rs deleted file mode 100644 index 277f0b2..0000000 --- a/src/app/keybindings.rs +++ /dev/null @@ -1,45 +0,0 @@ -use ratatui::crossterm::event::{KeyCode, KeyEvent, KeyEventKind, KeyModifiers}; - -use crate::app::View; - -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub enum Action { - Quit, -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub struct KeyBinding { - pub action: Action, - pub code: KeyCode, - pub kind: KeyEventKind, - pub modifiers: KeyModifiers, - pub description: &'static str, -} - -pub static KEYBINDINGS: &[KeyBinding] = &[KeyBinding { - action: Action::Quit, - code: KeyCode::Char('q'), - kind: KeyEventKind::Press, - modifiers: KeyModifiers::NONE, - description: "Quit", -}]; - -pub fn binding_for(action: Action) -> Option<&'static KeyBinding> { - KEYBINDINGS.iter().find(|b| b.action == action) -} - -pub fn event_to_action(event: &KeyEvent) -> Option { - KEYBINDINGS - .iter() - .find(|b| b.code == event.code && b.kind == event.kind && b.modifiers == event.modifiers) - .map(|b| b.action) -} - -pub fn binding_for_view(view: View) -> Vec<&'static KeyBinding> { - match view { - View::MainMenu => binding_for(Action::Quit) - .map(|b| vec![b]) - .unwrap_or_else(|| vec![]), - _ => vec![], - } -} diff --git a/src/app/keybindings/keybindings.rs b/src/app/keybindings/keybindings.rs new file mode 100644 index 0000000..ab80c3c --- /dev/null +++ b/src/app/keybindings/keybindings.rs @@ -0,0 +1,73 @@ +use crate::app::View; +use ratatui::crossterm::event::{KeyCode, KeyEvent, KeyEventKind, KeyModifiers}; + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub enum Action { + Quit, + ScrollUp, + ScrollDown, + Select, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct KeyBinding { + pub action: Action, + pub code: KeyCode, + pub kind: KeyEventKind, + pub modifiers: KeyModifiers, + pub description: &'static str, +} + +pub static KEYBINDINGS: &[KeyBinding] = &[ + KeyBinding { + action: Action::Quit, + code: KeyCode::Char('q'), + kind: KeyEventKind::Press, + modifiers: KeyModifiers::NONE, + description: "Quit", + }, + KeyBinding { + action: Action::ScrollUp, + code: KeyCode::Up, + kind: KeyEventKind::Press, + modifiers: KeyModifiers::NONE, + description: "Up", + }, + KeyBinding { + action: Action::ScrollDown, + code: KeyCode::Down, + kind: KeyEventKind::Press, + modifiers: KeyModifiers::NONE, + description: "Down", + }, + KeyBinding { + action: Action::Select, + code: KeyCode::Char(' '), + kind: KeyEventKind::Press, + modifiers: KeyModifiers::NONE, + description: "Select", + }, +]; + +pub fn binding_for(action: Action) -> Option<&'static KeyBinding> { + KEYBINDINGS.iter().find(|b| b.action == action) +} + +pub fn event_to_action(event: &KeyEvent) -> Option { + KEYBINDINGS + .iter() + .find(|b| b.code == event.code && b.kind == event.kind && b.modifiers == event.modifiers) + .map(|b| b.action) +} + +pub fn binding_for_view(view: View) -> Vec<&'static KeyBinding> { + match view { + View::MainMenu => vec![ + binding_for(Action::ScrollUp).unwrap(), + binding_for(Action::ScrollDown).unwrap(), + binding_for(Action::Select).unwrap(), + binding_for(Action::Quit).unwrap(), + ], + _ => vec![], + } +} diff --git a/src/app/keybindings/main_menu.rs b/src/app/keybindings/main_menu.rs new file mode 100644 index 0000000..76108f3 --- /dev/null +++ b/src/app/keybindings/main_menu.rs @@ -0,0 +1,14 @@ +use crate::app::{ + App, + keybindings::{Action, event_to_action}, +}; +use ratatui::crossterm::event::KeyEvent; + +pub fn main_menu_keybindings(app: &mut App, event: &KeyEvent) { + if let Some(action) = event_to_action(&event) { + match action { + Action::Quit => app.exit = true, + _ => (), + } + } +} diff --git a/src/app/keybindings/mod.rs b/src/app/keybindings/mod.rs new file mode 100644 index 0000000..7e8c674 --- /dev/null +++ b/src/app/keybindings/mod.rs @@ -0,0 +1,7 @@ +pub mod keybindings; +pub mod main_menu; + +pub use keybindings::{ + Action, KEYBINDINGS, KeyBinding, binding_for, binding_for_view, event_to_action, +}; +pub use main_menu::main_menu_keybindings; diff --git a/src/app/mod.rs b/src/app/mod.rs index f618336..f20bb68 100644 --- a/src/app/mod.rs +++ b/src/app/mod.rs @@ -4,6 +4,3 @@ pub mod widget; pub mod widgets; pub use app::{App, Event, View, handle_input_events}; -pub use keybindings::{ - Action, KEYBINDINGS, KeyBinding, binding_for, binding_for_view, event_to_action, -}; diff --git a/src/app/widget.rs b/src/app/widget.rs index 7856aea..e0cd9a9 100644 --- a/src/app/widget.rs +++ b/src/app/widget.rs @@ -1,6 +1,5 @@ -use ratatui::{buffer::Buffer, layout::Rect, widgets::Widget}; - use crate::app::{App, View, widgets::main_menu_widget}; +use ratatui::{buffer::Buffer, layout::Rect, widgets::Widget}; impl Widget for &App { fn render(self, area: Rect, buf: &mut Buffer) diff --git a/src/app/widgets/keybindings.rs b/src/app/widgets/keybindings.rs index 7d73574..7080c06 100644 --- a/src/app/widgets/keybindings.rs +++ b/src/app/widgets/keybindings.rs @@ -1,3 +1,4 @@ +use crate::app::{View, keybindings::binding_for_view}; use ratatui::{ crossterm::event::KeyCode, layout::Alignment, @@ -6,13 +7,14 @@ use ratatui::{ widgets::{Block, Borders, Paragraph}, }; -use crate::app::{View, binding_for_view}; - pub fn keybindings_widget(view: View) -> Paragraph<'static> { let lines: Vec = binding_for_view(view) .iter() .map(|b| { let key_span = match b.code { + KeyCode::Up => Span::raw("↑".to_string()), + KeyCode::Down => Span::raw("↓".to_string()), + KeyCode::Char(' ') => Span::raw("Space".to_string()), KeyCode::Char(c) => Span::raw(c.to_string()), other => Span::raw(format!("{:?}", other)), } diff --git a/src/app/widgets/main_menu.rs b/src/app/widgets/main_menu.rs index 0b69f6b..0ea594e 100644 --- a/src/app/widgets/main_menu.rs +++ b/src/app/widgets/main_menu.rs @@ -1,3 +1,4 @@ +use crate::app::{View, widgets::keybindings_widget}; use ratatui::{ buffer::Buffer, layout::{Alignment, Constraint, Layout, Rect}, @@ -5,11 +6,9 @@ use ratatui::{ widgets::{Block, Borders, Paragraph, Widget}, }; -use crate::app::{View, widgets::keybindings_widget}; - pub fn main_menu_widget(area: Rect, buf: &mut Buffer) { let vertical_layout: Layout = - Layout::vertical([Constraint::Percentage(90), Constraint::Percentage(10)]); + Layout::vertical([Constraint::Percentage(87), Constraint::Percentage(13)]); let [main_menu_area, keybindings_area] = vertical_layout.areas(area); diff --git a/src/cli.rs b/src/cli.rs index 91a59a3..04516b0 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -1,6 +1,5 @@ -use clap::Parser; - use crate::app::View; +use clap::Parser; #[derive(Parser, Debug)] #[command(version, about = "War in Tunnels", long_about = "War in Tunnels")]