1use std::io::{Error, ErrorKind};
31use std::str;
32
33use std::io::{Read, Write, stdin, stdout};
35
36use std::thread;
37use std::sync::mpsc;
38
39use crate::math::Vec2;
40
41
42#[derive(Debug, Clone, PartialEq, Eq, Hash)]
43pub enum InputEvent {
44 Key(KeyEvent),
45 Mouse(MouseEvent),
46 Unsupported(Vec<u8>)
47}
48
49
50#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
51pub enum KeyEvent {
52 Backspace,
53 Left,
54 Right,
55 Up,
56 Down,
57 Home,
58 End,
59 PageUp,
60 PageDown,
61 BackTab, Delete,
63 Insert,
64 F(u8), Char(char),
66 Alt(char),
67 Ctrl(char),
68 Null,
69 Esc
70}
71
72
73#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
75pub enum MouseEvent {
76 ButtonPressed(MouseButton, Vec2),
77 ButtonReleased(MouseButton, Vec2),
78 Hold(MouseButton, Vec2)
79}
80
81
82#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
83pub enum MouseButton {
84 Left,
85 Right,
86 Middle,
87 WheelUp,
88 WheelDown
89}
90
91
92
93fn get_real_mouse_pos(cx: u16, cy: u16) -> Vec2 {
94 vec2!(cx as i32 - 1, 2 * (cy as i32) - 2)
95}
96
97
98fn parse_event<I>(item: u8, iter: &mut I) -> Result<InputEvent, Error>
100 where I: Iterator<Item = Result<u8, Error>>
101{
102 let error = Error::new(ErrorKind::Other, "Could not parse an event");
103 match item {
104 b'\x1B' => {
105 Ok(match iter.next() {
107 Some(Ok(b'O')) => {
108 match iter.next() {
109 Some(Ok(val @ b'P'..=b'S')) => InputEvent::Key(KeyEvent::F(1 + val - b'P')),
111 _ => return Err(error),
112 }
113 }
114 Some(Ok(b'[')) => {
115 parse_csi(iter).ok_or(error)?
117 }
118 Some(Ok(c)) => {
119 let ch = parse_utf8_char(c, iter)?;
120 InputEvent::Key(KeyEvent::Alt(ch))
121 }
122 Some(Err(_)) | None => return Err(error),
123 })
124 }
125 b'\n' | b'\r' => Ok(InputEvent::Key(KeyEvent::Char('\n'))),
126 b'\t' => Ok(InputEvent::Key(KeyEvent::Char('\t'))),
127 b'\x7F' => Ok(InputEvent::Key(KeyEvent::Backspace)),
128 c @ b'\x01'..=b'\x1A' => Ok(InputEvent::Key(KeyEvent::Ctrl((c as u8 - 0x1 + b'a') as char))),
129 c @ b'\x1C'..=b'\x1F' => Ok(InputEvent::Key(KeyEvent::Ctrl((c as u8 - 0x1C + b'4') as char))),
130 b'\0' => Ok(InputEvent::Key(KeyEvent::Null)),
131 c => {
132 Ok({
133 let ch = parse_utf8_char(c, iter)?;
134 InputEvent::Key(KeyEvent::Char(ch))
135 })
136 }
137 }
138}
139
140
141fn parse_csi<I>(iter: &mut I) -> Option<InputEvent>
145 where I: Iterator<Item = Result<u8, Error>>
146{
147 Some(match iter.next() {
148 Some(Ok(b'[')) => match iter.next() {
149 Some(Ok(val @ b'A'..=b'E')) => InputEvent::Key(KeyEvent::F(1 + val - b'A')),
150 _ => return None,
151 },
152 Some(Ok(b'D')) => InputEvent::Key(KeyEvent::Left),
153 Some(Ok(b'C')) => InputEvent::Key(KeyEvent::Right),
154 Some(Ok(b'A')) => InputEvent::Key(KeyEvent::Up),
155 Some(Ok(b'B')) => InputEvent::Key(KeyEvent::Down),
156 Some(Ok(b'H')) => InputEvent::Key(KeyEvent::Home),
157 Some(Ok(b'F')) => InputEvent::Key(KeyEvent::End),
158 Some(Ok(b'Z')) => InputEvent::Key(KeyEvent::BackTab),
159 Some(Ok(b'M')) => {
160 let mut next = || iter.next().unwrap().unwrap();
162
163 let cb = next() as i8 - 32;
164 let cx = next().saturating_sub(32) as u16;
166 let cy = next().saturating_sub(32) as u16;
167 InputEvent::Mouse(match cb & 0b11 {
168 0 => {
169 if cb & 0x40 != 0 {
170 MouseEvent::ButtonPressed(MouseButton::WheelUp, get_real_mouse_pos(cx, cy))
171 } else {
172 MouseEvent::ButtonPressed(MouseButton::Left, get_real_mouse_pos(cx, cy))
173 }
174 }
175 1 => {
176 if cb & 0x40 != 0 {
177 MouseEvent::ButtonPressed(MouseButton::WheelDown, get_real_mouse_pos(cx, cy))
178 } else {
179 MouseEvent::ButtonPressed(MouseButton::Middle, get_real_mouse_pos(cx, cy))
180 }
181 }
182 2 => MouseEvent::ButtonPressed(MouseButton::Right, get_real_mouse_pos(cx, cy)),
183 3 => MouseEvent::ButtonReleased(MouseButton::Left, get_real_mouse_pos(cx, cy)),
185 _ => return None,
186 })
187 }
188 Some(Ok(b'<')) => {
189 let mut buf = Vec::new();
192 let mut c = iter.next().unwrap().unwrap();
193 while match c {
194 b'm' | b'M' => false,
195 _ => true,
196 } {
197 buf.push(c);
198 c = iter.next().unwrap().unwrap();
199 }
200 let str_buf = String::from_utf8(buf).unwrap();
201 let nums = &mut str_buf.split(';');
202
203 let cb = nums.next()
204 .unwrap()
205 .parse::<u16>()
206 .unwrap();
207 let cx = nums.next()
208 .unwrap()
209 .parse::<u16>()
210 .unwrap();
211 let cy = nums.next()
212 .unwrap()
213 .parse::<u16>()
214 .unwrap();
215
216 let event = match cb {
217 0..=2 | 64..=65 => {
218 let button = match cb {
219 0 => MouseButton::Left,
220 1 => MouseButton::Middle,
221 2 => MouseButton::Right,
222 64 => MouseButton::WheelUp,
223 65 => MouseButton::WheelDown,
224 _ => unreachable!(),
225 };
226 match c {
227 b'M' => MouseEvent::ButtonPressed(button, get_real_mouse_pos(cx, cy)),
228 b'm' => MouseEvent::ButtonReleased(MouseButton::Left, get_real_mouse_pos(cx, cy)),
230 _ => return None,
231 }
232 }
233 32 => MouseEvent::Hold(MouseButton::Left, get_real_mouse_pos(cx, cy)),
235 3 => MouseEvent::ButtonReleased(MouseButton::Left, get_real_mouse_pos(cx, cy)),
237 _ => return None,
238 };
239
240 InputEvent::Mouse(event)
241 }
242 Some(Ok(c @ b'0'..=b'9')) => {
243 let mut buf = Vec::new();
245 buf.push(c);
246 let mut c = iter.next().unwrap().unwrap();
247 while c < 64 || c > 126 {
250 buf.push(c);
251 c = iter.next().unwrap().unwrap();
252 }
253
254 match c {
255 b'M' => {
258 let str_buf = String::from_utf8(buf).unwrap();
259
260 let nums: Vec<u16> = str_buf.split(';').map(|n| n.parse().unwrap()).collect();
261
262 let cb = nums[0];
263 let cx = nums[1];
264 let cy = nums[2];
265
266 let event = match cb {
267 32 => MouseEvent::ButtonPressed(MouseButton::Left, get_real_mouse_pos(cx, cy)),
268 33 => MouseEvent::ButtonPressed(MouseButton::Middle, get_real_mouse_pos(cx, cy)),
269 34 => MouseEvent::ButtonPressed(MouseButton::Right, get_real_mouse_pos(cx, cy)),
270 35 => MouseEvent::ButtonReleased(MouseButton::Left, get_real_mouse_pos(cx, cy)),
272 64 => MouseEvent::Hold(MouseButton::Left, get_real_mouse_pos(cx, cy)),
274 96 | 97 => MouseEvent::ButtonPressed(MouseButton::WheelUp, get_real_mouse_pos(cx, cy)),
275 _ => return None,
276 };
277
278 InputEvent::Mouse(event)
279 }
280 b'~' => {
282 let str_buf = String::from_utf8(buf).unwrap();
283
284 let nums: Vec<u8> = str_buf.split(';').map(|n| n.parse().unwrap()).collect();
287
288 if nums.is_empty() {
289 return None;
290 }
291
292 if nums.len() > 1 {
295 return None;
296 }
297
298 match nums[0] {
299 1 | 7 => InputEvent::Key(KeyEvent::Home),
300 2 => InputEvent::Key(KeyEvent::Insert),
301 3 => InputEvent::Key(KeyEvent::Delete),
302 4 | 8 => InputEvent::Key(KeyEvent::End),
303 5 => InputEvent::Key(KeyEvent::PageUp),
304 6 => InputEvent::Key(KeyEvent::PageDown),
305 v @ 11..=15 => InputEvent::Key(KeyEvent::F(v - 10)),
306 v @ 17..=21 => InputEvent::Key(KeyEvent::F(v - 11)),
307 v @ 23..=24 => InputEvent::Key(KeyEvent::F(v - 12)),
308 _ => return None,
309 }
310 }
311 _ => return None,
312 }
313 }
314 _ => return None,
315 })
316}
317
318
319fn parse_utf8_char<I>(c: u8, iter: &mut I) -> Result<char, Error>
321 where I: Iterator<Item = Result<u8, Error>>
322{
323 let error = Err(Error::new(ErrorKind::Other, "Input character is not valid UTF-8"));
324 if c.is_ascii() {
325 Ok(c as char)
326 } else {
327 let bytes = &mut Vec::new();
328 bytes.push(c);
329
330 loop {
331 match iter.next() {
332 Some(Ok(next)) => {
333 bytes.push(next);
334 if let Ok(st) = str::from_utf8(bytes) {
335 return Ok(st.chars().next().unwrap());
336 }
337 if bytes.len() >= 4 {
338 return error;
339 }
340 }
341 _ => return error,
342 }
343 }
344 }
345}
346
347
348static mut INPUT_SERVER: Option<Input> = None;
350
351
352pub struct Input {
367 _server_handle: Option<thread::JoinHandle<()>>,
368 input_recv: mpsc::Receiver<InputEvent>
369}
370
371
372impl Input {
373
374 fn init() -> Self {
376 let (input_send, input_recv) = mpsc::channel();
377
378 let handle = thread::spawn(move || {
379 let mut mb = MouseButton::Left;
380 loop {
381 let mut stdin = stdin().bytes();
382
383 if let Some(Ok(item)) = stdin.next() {
384 match parse_event(item, &mut stdin) {
385 Ok(evt) => {
386 let event = match evt {
387 InputEvent::Mouse(MouseEvent::ButtonPressed(button, _)) => {
388 mb = button;
389 evt
390 }
391 InputEvent::Mouse(MouseEvent::ButtonReleased(_, pos)) =>
392 InputEvent::Mouse(MouseEvent::ButtonReleased(mb, pos)),
393 InputEvent::Mouse(MouseEvent::Hold(_, pos)) =>
394 InputEvent::Mouse(MouseEvent::Hold(mb, pos)),
395 _ => evt
396 };
397 input_send.send(event).expect("input recv dropped")
398 }
399 Err(_) => {}
400 }
401 };
402 }
403 });
404
405 Self {
406 _server_handle: Some(handle),
407 input_recv: input_recv
408 }
409 }
410
411
412 pub fn get() -> &'static mut Input {
416 unsafe {
417 match &mut INPUT_SERVER {
418 None => {
419 INPUT_SERVER = Some(Input::init());
420 Input::get()
421 },
422 Some(i) => i
423 }
424 }
425 }
426
427
428 pub fn get_event(&mut self) -> Option<InputEvent> {
431 self.input_recv.try_recv().ok()
432 }
433
434
435 pub fn get_event_blocking(&mut self) -> InputEvent {
437 self.input_recv.recv().ok().expect("Input thread was killed")
438 }
439
440
441 pub fn enable_mouse() {
443 print!("\x1b[?1000h\x1b[?1002h\x1b[?1015h\x1b[?1006h");
444 stdout().flush().expect("Could not write to stdout");
445 }
446
447
448 pub fn disable_mouse() {
450 print!("\x1b[?1006l\x1b[?1015l\x1b[?1002l\x1b[?1000l");
451 stdout().flush().expect("Could not write to stdout");
452 }
453}