Skip to main content

nms_copilot/map/
input.rs

1//! Crossterm event handling for the interactive map.
2
3use crossterm::event::{self, Event, KeyCode, KeyEvent, KeyModifiers};
4use std::time::Duration;
5
6use super::state::MapState;
7
8/// Map action produced by input handling.
9pub enum MapAction {
10    /// No action (timeout or ignored event).
11    None,
12    /// Terminal was resized.
13    Resized(u16, u16),
14}
15
16/// Poll for input events and update map state accordingly.
17///
18/// Returns `MapAction::Resized` when the terminal size changes,
19/// so the caller can trigger a re-render.
20pub fn handle_input(state: &mut MapState) -> std::io::Result<MapAction> {
21    if !event::poll(Duration::from_millis(100))? {
22        return Ok(MapAction::None);
23    }
24
25    match event::read()? {
26        Event::Key(key) => {
27            handle_key(key, state);
28            Ok(MapAction::None)
29        }
30        Event::Resize(w, h) => {
31            state.resize(w, h);
32            Ok(MapAction::Resized(w, h))
33        }
34        _ => Ok(MapAction::None),
35    }
36}
37
38/// Process a key event and update map state.
39fn handle_key(key: KeyEvent, state: &mut MapState) {
40    // Toggle help overlay handles its own key
41    if state.show_help {
42        state.show_help = false;
43        return;
44    }
45
46    match key.code {
47        // Navigation
48        KeyCode::Up => state.move_cursor(0, -1),
49        KeyCode::Down => state.move_cursor(0, 1),
50        KeyCode::Left => state.move_cursor(-1, 0),
51        KeyCode::Right => state.move_cursor(1, 0),
52
53        // Zoom
54        KeyCode::Enter | KeyCode::Char('+') => state.zoom_in(),
55        KeyCode::Esc | KeyCode::Char('-') if !state.zoom_out() => {
56            state.should_quit = true;
57        }
58
59        // Commands
60        KeyCode::Char('q') => state.should_quit = true,
61        KeyCode::Char('c') if key.modifiers == KeyModifiers::NONE => {
62            state.center_on_player();
63        }
64        KeyCode::Char('?') => state.show_help = !state.show_help,
65
66        // Ctrl+C also quits
67        KeyCode::Char('c') if key.modifiers.contains(KeyModifiers::CONTROL) => {
68            state.should_quit = true;
69        }
70
71        _ => {}
72    }
73}