crossterm/event/
filter.rs

1use crate::event::InternalEvent;
2
3/// Interface for filtering an `InternalEvent`.
4pub(crate) trait Filter: Send + Sync + 'static {
5    /// Returns whether the given event fulfills the filter.
6    fn eval(&self, event: &InternalEvent) -> bool;
7}
8
9#[cfg(unix)]
10#[derive(Debug, Clone)]
11pub(crate) struct CursorPositionFilter;
12
13#[cfg(unix)]
14impl Filter for CursorPositionFilter {
15    fn eval(&self, event: &InternalEvent) -> bool {
16        matches!(*event, InternalEvent::CursorPosition(_, _))
17    }
18}
19
20#[cfg(unix)]
21#[derive(Debug, Clone)]
22pub(crate) struct KeyboardEnhancementFlagsFilter;
23
24#[cfg(unix)]
25impl Filter for KeyboardEnhancementFlagsFilter {
26    fn eval(&self, event: &InternalEvent) -> bool {
27        // This filter checks for either a KeyboardEnhancementFlags response or
28        // a PrimaryDeviceAttributes response. If we receive the PrimaryDeviceAttributes
29        // response but not KeyboardEnhancementFlags, the terminal does not support
30        // progressive keyboard enhancement.
31        matches!(
32            *event,
33            InternalEvent::KeyboardEnhancementFlags(_) | InternalEvent::PrimaryDeviceAttributes
34        )
35    }
36}
37
38#[cfg(unix)]
39#[derive(Debug, Clone)]
40pub(crate) struct PrimaryDeviceAttributesFilter;
41
42#[cfg(unix)]
43impl Filter for PrimaryDeviceAttributesFilter {
44    fn eval(&self, event: &InternalEvent) -> bool {
45        matches!(*event, InternalEvent::PrimaryDeviceAttributes)
46    }
47}
48
49#[derive(Debug, Clone)]
50pub(crate) struct EventFilter;
51
52impl Filter for EventFilter {
53    #[cfg(unix)]
54    fn eval(&self, event: &InternalEvent) -> bool {
55        matches!(*event, InternalEvent::Event(_))
56    }
57
58    #[cfg(windows)]
59    fn eval(&self, _: &InternalEvent) -> bool {
60        true
61    }
62}
63
64#[derive(Debug, Clone)]
65pub(crate) struct InternalEventFilter;
66
67impl Filter for InternalEventFilter {
68    fn eval(&self, _: &InternalEvent) -> bool {
69        true
70    }
71}
72
73#[cfg(test)]
74#[cfg(unix)]
75mod tests {
76    use super::{
77        super::Event, CursorPositionFilter, EventFilter, Filter, InternalEvent,
78        InternalEventFilter, KeyboardEnhancementFlagsFilter, PrimaryDeviceAttributesFilter,
79    };
80
81    #[test]
82    fn test_cursor_position_filter_filters_cursor_position() {
83        assert!(!CursorPositionFilter.eval(&InternalEvent::Event(Event::Resize(10, 10))));
84        assert!(CursorPositionFilter.eval(&InternalEvent::CursorPosition(0, 0)));
85    }
86
87    #[test]
88    fn test_keyboard_enhancement_status_filter_filters_keyboard_enhancement_status() {
89        assert!(!KeyboardEnhancementFlagsFilter.eval(&InternalEvent::Event(Event::Resize(10, 10))));
90        assert!(
91            KeyboardEnhancementFlagsFilter.eval(&InternalEvent::KeyboardEnhancementFlags(
92                crate::event::KeyboardEnhancementFlags::DISAMBIGUATE_ESCAPE_CODES
93            ))
94        );
95        assert!(KeyboardEnhancementFlagsFilter.eval(&InternalEvent::PrimaryDeviceAttributes));
96    }
97
98    #[test]
99    fn test_primary_device_attributes_filter_filters_primary_device_attributes() {
100        assert!(!PrimaryDeviceAttributesFilter.eval(&InternalEvent::Event(Event::Resize(10, 10))));
101        assert!(PrimaryDeviceAttributesFilter.eval(&InternalEvent::PrimaryDeviceAttributes));
102    }
103
104    #[test]
105    fn test_event_filter_filters_events() {
106        assert!(EventFilter.eval(&InternalEvent::Event(Event::Resize(10, 10))));
107        assert!(!EventFilter.eval(&InternalEvent::CursorPosition(0, 0)));
108    }
109
110    #[test]
111    fn test_event_filter_filters_internal_events() {
112        assert!(InternalEventFilter.eval(&InternalEvent::Event(Event::Resize(10, 10))));
113        assert!(InternalEventFilter.eval(&InternalEvent::CursorPosition(0, 0)));
114    }
115}