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}