1use tracing::trace;
3
4#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
5pub enum Arrow {
6 Up,
7 Down,
8 Left,
9 Right,
10}
11
12impl Arrow {
13 pub fn flip(&self) -> Self {
14 match self {
15 Self::Up => Self::Down,
16 Self::Down => Self::Up,
17 Self::Left => Self::Right,
18 Self::Right => Self::Left,
19 }
20 }
21}
22
23#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
25pub enum Input {
26 Char(char),
27 Ctrl(char),
28 Alt(char),
29 CtrlAlt(char),
30 Tab,
31 BackTab,
32 AltReturn,
33 Return,
34 Backspace,
35 Arrow(Arrow),
36 Del,
37 Home,
38 End,
39 PageUp,
40 PageDown,
41 Esc,
42 Mouse(MouseEvent),
43}
44
45impl Input {
46 pub fn from_char(c: char) -> Self {
47 match c {
48 '\x1b' => Input::Esc,
49 '\n' | '\r' => Input::Return,
50 '\x7f' => Input::Backspace,
51 '\t' => Input::Tab,
52 c @ '\x01'..='\x1A' => Input::Ctrl((c as u8 - 0x1 + b'a') as char),
53 c @ '\x1C'..='\x1F' => Input::Ctrl((c as u8 - 0x1C + b'4') as char),
54 _ => Input::Char(c),
55 }
56 }
57
58 pub fn try_from_seq2(c1: char, c2: char) -> Option<Self> {
59 match (c1, c2) {
60 ('O', 'H') => Some(Input::Home),
61 ('O', 'F') => Some(Input::End),
62
63 ('[', 'A') => Some(Input::Arrow(Arrow::Up)),
64 ('[', 'B') => Some(Input::Arrow(Arrow::Down)),
65 ('[', 'C') => Some(Input::Arrow(Arrow::Right)),
66 ('[', 'D') => Some(Input::Arrow(Arrow::Left)),
67 ('[', 'H') => Some(Input::Home),
68 ('[', 'Z') => Some(Input::BackTab),
69 ('\x1b', c) if c.is_ascii() => match Self::from_char(c) {
70 Input::Char(c) => Some(Input::Alt(c)),
71 Input::Ctrl(c) => Some(Input::CtrlAlt(c)),
72 Input::Return => Some(Input::AltReturn),
73 _ => None,
74 },
75 _ => None,
76 }
77 }
78
79 pub fn try_from_bracket_tilde(c: char) -> Option<Self> {
80 match c {
81 '1' | '7' => Some(Input::Home),
82 '4' | '8' => Some(Input::End),
83 '3' => Some(Input::Del),
84 '5' => Some(Input::PageUp),
85 '6' => Some(Input::PageDown),
86 _ => None,
87 }
88 }
89}
90
91#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
92pub enum MouseButton {
93 Left,
94 Middle,
95 Right,
96 WheelUp,
97 WheelDown,
98}
99
100#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
101pub enum MouseMod {
102 NoMod,
103 Alt,
104 Ctrl,
105 AltCtrl,
106}
107
108#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
109pub enum MouseEventKind {
110 Press,
111 Hold,
112 Release,
113}
114
115#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
116pub struct MouseEvent {
117 pub k: MouseEventKind,
118 pub m: MouseMod,
119 pub b: MouseButton,
120 pub x: usize,
121 pub y: usize,
122}
123
124impl MouseEvent {
125 pub(crate) fn try_from_raw(b: usize, x: usize, y: usize, c: char) -> Option<Self> {
126 use MouseButton::*;
127 use MouseEventKind::*;
128 use MouseMod::*;
129
130 let (k, m, b) = match (b, c) {
131 (0, 'M') => (Press, NoMod, Left),
133 (1, 'M') => (Press, NoMod, Middle),
134 (2, 'M') => (Press, NoMod, Right),
135 (64, 'M') => (Press, NoMod, WheelUp),
136 (65, 'M') => (Press, NoMod, WheelDown),
137
138 (0, 'm') | (3, _) => (Release, NoMod, Left),
139 (1, 'm') => (Release, NoMod, Middle),
140 (2, 'm') => (Release, NoMod, Right),
141 (64, 'm') => (Release, NoMod, WheelUp),
142 (65, 'm') => (Release, NoMod, WheelDown),
143
144 (32, _) => (Hold, NoMod, Left),
145 (33, _) => (Hold, NoMod, Middle),
146 (34, _) => (Hold, NoMod, Right),
147
148 (8, 'M') => (Press, Alt, Left),
150 (9, 'M') => (Press, Alt, Middle),
151 (10, 'M') => (Press, Alt, Right),
152 (72, 'M') => (Press, Alt, WheelUp),
153 (73, 'M') => (Press, Alt, WheelDown),
154
155 (8, 'm') => (Release, Alt, Left),
156 (9, 'm') => (Release, Alt, Middle),
157 (10, 'm') => (Release, Alt, Right),
158 (72, 'm') => (Release, Alt, WheelUp),
159 (73, 'm') => (Release, Alt, WheelDown),
160
161 (40, _) => (Hold, Alt, Left),
162 (41, _) => (Hold, Alt, Middle),
163 (42, _) => (Hold, Alt, Right),
164
165 (16, 'M') => (Press, Ctrl, Left),
167 (17, 'M') => (Press, Ctrl, Middle),
168 (18, 'M') => (Press, Ctrl, Right),
169 (80, 'M') => (Press, Ctrl, WheelUp),
170 (81, 'M') => (Press, Ctrl, WheelDown),
171
172 (16, 'm') => (Release, Ctrl, Left),
173 (17, 'm') => (Release, Ctrl, Middle),
174 (18, 'm') => (Release, Ctrl, Right),
175 (80, 'm') => (Release, Ctrl, WheelUp),
176 (81, 'm') => (Release, Ctrl, WheelDown),
177
178 (48, _) => (Hold, Ctrl, Left),
179 (49, _) => (Hold, Ctrl, Middle),
180 (50, _) => (Hold, Ctrl, Right),
181
182 (24, 'M') => (Press, AltCtrl, Left),
184 (25, 'M') => (Press, AltCtrl, Middle),
185 (26, 'M') => (Press, AltCtrl, Right),
186 (88, 'M') => (Press, AltCtrl, WheelUp),
187 (89, 'M') => (Press, AltCtrl, WheelDown),
188
189 (24, 'm') => (Release, AltCtrl, Left),
190 (25, 'm') => (Release, AltCtrl, Middle),
191 (26, 'm') => (Release, AltCtrl, Right),
192 (88, 'm') => (Release, AltCtrl, WheelUp),
193 (89, 'm') => (Release, AltCtrl, WheelDown),
194
195 (56, _) => (Hold, AltCtrl, Left),
196 (57, _) => (Hold, AltCtrl, Middle),
197 (58, _) => (Hold, AltCtrl, Right),
198
199 _ => {
200 trace!("unmapped mouse input: b=b m=m");
201 return None;
202 }
203 };
204
205 Some(MouseEvent { k, m, b, x, y })
206 }
207}