wireman_event_handler/
lib.rs

1mod crossterm;
2pub mod key_event;
3use std::collections::HashMap;
4use std::fmt::Display;
5
6use ::crossterm::event::MouseEvent;
7pub use key_event::KeyCode;
8pub use key_event::KeyEvent;
9pub use key_event::{KeyModifier, KeyModifiers};
10use std::fmt::Write as _;
11
12/// A trait for handling events with associated contexts.
13pub trait EventHandler {
14    /// The context in which events are handled.
15    type Context;
16
17    /// The type of events to handle.
18    type Event;
19
20    /// Handles a specific app event with the given context.
21    ///
22    /// # Arguments
23    ///
24    /// * `event` - The event to handle.
25    /// * `ctx` - The context in which the event is handled.
26    fn handle_event(event: &Self::Event, ctx: &mut Self::Context);
27
28    /// Passes through key events without any specific handling.
29    ///
30    /// This method is optional and can be used to simply pass through character events without
31    /// registering any specific handling logic.
32    fn pass_through_key_events(_: &KeyEvent, _: &mut Self::Context) {}
33
34    /// Passes through mouse events without any specific handling.
35    ///
36    /// This method is optional and can be used to simply pass through character events without
37    /// registering any specific handling logic.
38    fn pass_through_mouse_events(_: &MouseEvent, _: &mut Self::Context) {}
39
40    /// Passes through paste events without any specific handling.
41    ///
42    /// This method is optional and can be used to simply pass through character events without
43    /// registering any specific handling logic.
44    fn pass_through_paste_events(_: String, _: &mut Self::Context) {}
45
46    /// Retrieves the key event mappings to their corresponding application events.
47    ///
48    /// Returns a map of key events to application events.
49    fn key_event_mappings(ctx: &Self::Context) -> Vec<(KeyEvent, Self::Event)>;
50
51    /// Handles a key event by dispatching it to the corresponding application event handler.
52    ///
53    /// # Arguments
54    ///
55    /// * `ctx` - The context in which the key event is handled.
56    /// * `event` - The key event to handle.
57    fn handle_key_event<T: Into<KeyEvent>>(ctx: &mut Self::Context, event: T) {
58        let mappings = Self::key_event_mappings(ctx);
59        let event = event.into();
60        if let Some(item) = mappings.iter().find(|item| item.0 == event) {
61            Self::handle_event(&item.1, ctx);
62        } else {
63            Self::pass_through_key_events(&event, ctx);
64        }
65    }
66
67    /// Handles a mouse event by dispatching it to the corresponding application event handler.
68    ///
69    /// # Arguments
70    ///
71    /// * `ctx` - The context in which the mouse event is handled.
72    /// * `event` - The mouse event to handle.
73    fn handle_mouse_event<T: Into<MouseEvent>>(ctx: &mut Self::Context, event: T) {
74        let event = event.into();
75        Self::pass_through_mouse_events(&event, ctx);
76    }
77
78    /// Handles a paste event by dispatching it to the corresponding application event handler.
79    ///
80    /// # Arguments
81    ///
82    /// * `ctx` - The context in which the paste event is handled.
83    /// * `text` - The text to paste.
84    fn handle_paste_event(ctx: &mut Self::Context, text: String) {
85        Self::pass_through_paste_events(text, ctx);
86    }
87
88    /// Converts the key event mappings into a vector of string representations, i.e.
89    /// (app event as string, key event as string).
90    ///
91    /// This method formats each key event and corresponding app event
92    /// as strings and returns them as a vector of tuples. If multiple key events
93    /// map to the same app event, they are merged into a single entry where
94    /// the keys are concatenated together.
95    fn format_event_mappings_as_strings(ctx: &Self::Context) -> Vec<(String, String)>
96    where
97        Self::Event: Display,
98    {
99        let mappings = Self::key_event_mappings(ctx);
100        let mut formatted_events: Vec<(String, String)> = Vec::new();
101        let mut event_indices: HashMap<String, usize> = HashMap::new();
102
103        for (key_event, event) in mappings {
104            let key_event_str = key_event.to_string();
105            let event_str = event.to_string();
106
107            if let Some(&index) = event_indices.get(&event_str) {
108                let mut s = String::new();
109                let _ = write!(s, ", {key_event_str}");
110                formatted_events[index].0.push_str(&s);
111            } else {
112                formatted_events.push((key_event_str, event_str.clone()));
113                event_indices.insert(event_str, formatted_events.len() - 1);
114            }
115        }
116
117        formatted_events
118    }
119}