1use anyhow::Result;
4use crossterm::event as c_event;
5
6use crate::{
7 map_keybindings,
8 thread::State,
9 Event,
10 EventHandler,
11 EventReaderFn,
12 KeyBindings,
13 KeyCode,
14 KeyEvent,
15 KeyModifiers,
16};
17
18#[cfg(test)]
19pub(crate) mod local {
20 use anyhow::Result;
21
22 use crate::{CustomEvent, CustomKeybinding, EventReaderFn};
23
24 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd)]
25 pub(crate) enum TestEvent {}
26 impl CustomEvent for TestEvent {}
27
28 pub(crate) struct TestKeybinding;
29 impl CustomKeybinding for TestKeybinding {
30 fn new(_: &config::KeyBindings) -> Self {
31 Self {}
32 }
33 }
34
35 pub(crate) type Event = super::Event<TestEvent>;
36 pub(crate) type EventHandler = super::EventHandler<TestKeybinding, TestEvent>;
37 pub(crate) type KeyBindings = super::KeyBindings<TestKeybinding, TestEvent>;
38
39 pub(crate) fn create_test_keybindings() -> KeyBindings {
40 super::create_test_keybindings::<TestKeybinding, TestEvent>(TestKeybinding {})
41 }
42
43 pub(crate) fn create_event_reader<EventGeneratorFunction>(
44 event_generator: EventGeneratorFunction,
45 ) -> impl EventReaderFn
46 where EventGeneratorFunction: Fn() -> Result<Option<Event>> + Sync + Send + 'static {
47 super::create_event_reader(event_generator)
48 }
49}
50
51#[inline]
53#[must_use]
54pub fn create_test_keybindings<TestKeybinding: crate::CustomKeybinding, CustomEvent: crate::CustomEvent>(
55 custom_key_bindings: TestKeybinding,
56) -> KeyBindings<TestKeybinding, CustomEvent> {
57 KeyBindings {
58 redo: vec![Event::from(KeyEvent::new(KeyCode::Char('y'), KeyModifiers::CONTROL))],
59 undo: vec![Event::from(KeyEvent::new(KeyCode::Char('z'), KeyModifiers::CONTROL))],
60 scroll_down: map_keybindings(&[String::from("Down")]),
61 scroll_end: map_keybindings(&[String::from("End")]),
62 scroll_home: map_keybindings(&[String::from("Home")]),
63 scroll_left: map_keybindings(&[String::from("Left")]),
64 scroll_right: map_keybindings(&[String::from("Right")]),
65 scroll_up: map_keybindings(&[String::from("Up")]),
66 scroll_step_down: map_keybindings(&[String::from("PageDown")]),
67 scroll_step_up: map_keybindings(&[String::from("PageUp")]),
68 help: map_keybindings(&[String::from("?")]),
69 search_start: map_keybindings(&[String::from("/")]),
70 search_next: map_keybindings(&[String::from("n")]),
71 search_previous: map_keybindings(&[String::from("N")]),
72 custom: custom_key_bindings,
73 }
74}
75
76#[derive(Debug)]
78#[non_exhaustive]
79pub struct TestContext<TestKeybinding: crate::CustomKeybinding, CustomEvent: crate::CustomEvent> {
80 pub event_handler: EventHandler<TestKeybinding, CustomEvent>,
82 pub state: State<CustomEvent>,
84 pub number_events: usize,
86}
87
88#[inline]
90#[allow(clippy::missing_panics_doc)]
91pub fn with_event_handler<C, TestKeybinding: crate::CustomKeybinding, CustomEvent: crate::CustomEvent>(
92 custom_key_bindings: TestKeybinding,
93 events: &[Event<CustomEvent>],
94 callback: C,
95) where
96 C: FnOnce(TestContext<TestKeybinding, CustomEvent>),
97{
98 let event_handler = EventHandler::new(create_test_keybindings(custom_key_bindings));
99 let state = State::new();
100
101 for event in events {
102 state.enqueue_event(*event);
103 }
104
105 callback(TestContext {
106 event_handler,
107 state,
108 number_events: events.len(),
109 });
110}
111
112#[allow(clippy::panic)]
123#[inline]
124pub fn create_event_reader<EventGeneratorFunction, CustomEvent>(
125 event_generator: EventGeneratorFunction,
126) -> impl EventReaderFn
127where
128 EventGeneratorFunction: Fn() -> Result<Option<Event<CustomEvent>>> + Sync + Send + 'static,
129 CustomEvent: crate::CustomEvent,
130{
131 move || {
132 match event_generator()? {
133 None => Ok(None),
134 Some(event) => {
135 match event {
136 Event::Key(key) => {
137 Ok(Some(c_event::Event::Key(c_event::KeyEvent::new(
138 key.code,
139 key.modifiers,
140 ))))
141 },
142 Event::Mouse(mouse_event) => Ok(Some(c_event::Event::Mouse(mouse_event))),
143 Event::None => Ok(None),
144 Event::Resize(width, height) => Ok(Some(c_event::Event::Resize(width, height))),
145 Event::MetaEvent(_) | Event::Standard(_) => {
146 panic!("MetaEvent and Standard are not supported, please use other event types")
147 },
148 }
149 },
150 }
151 }
152}