1#[cfg(not(windows))]
2extern crate termios;
3#[cfg(not(windows))]
4use std::io::Read;
5#[cfg(windows)]
6pub struct Getch{}
7
8#[cfg(not(windows))]
9pub enum Getch {
10 Termios(termios::Termios),
11 None
12}
13
14#[cfg(windows)]
15extern crate libc;
16#[cfg(windows)]
17use libc::c_int;
18#[cfg(windows)]
19extern "C" {
20 fn _getch()->c_int;
21}
22
23#[cfg(not(windows))]
24use termios::{tcsetattr,ICANON,ECHO};
25
26impl Getch {
27 #[cfg(windows)]
28 pub fn new() -> Getch {
29 Getch{}
30 }
31 #[cfg(not(windows))]
32 pub fn new() -> Getch {
33 if let Ok(mut termios) = termios::Termios::from_fd(0) {
34 let c_lflag = termios.c_lflag;
35 termios.c_lflag &= !(ICANON|ECHO);
36
37 if let Ok(()) = tcsetattr(0, termios::TCSADRAIN, &termios) {
38 termios.c_lflag = c_lflag;
39 return Getch::Termios(termios)
40 }
41 }
42 Getch::None
43 }
44
45 #[cfg(windows)]
46 pub fn getch(&self) -> Result<u8, std::io::Error> {
47 loop {
48 unsafe {
49 let k= _getch();
50 if k==0 {
51 _getch();
53 } else {
54 return Ok(k as u8)
55 }
56 }
57 }
58 }
59 #[cfg(not(windows))]
60 pub fn getch(&self) -> Result<u8, std::io::Error> {
61 let mut r:[u8;1]=[0];
62 let mut stdin = std::io::stdin();
63 loop {
64 if stdin.read(&mut r[..])? == 0 { return Ok(0) }
65 else {
66 if r[0]==27 {
67 if stdin.read(&mut r[..])? == 0 { return Ok(0) }
68 if r[0] == b'[' || (r[0] >= b'0' && r[0] <= b'9') {
69 if stdin.read(&mut r[..])? == 0 { return Ok(0) }
70 while !((r[0] >= b'a' && r[0] <= b'z') || (r[0] >= b'A' && r[0] <= b'Z')) {
72 if stdin.read(&mut r[..])? == 0 { return Ok(0) }
73 }
74 if stdin.read(&mut r[..])? == 0 { return Ok(0) }
75 return Ok(r[0])
76 } else if r[0] == b'(' || r[0] == b')' || r[0] == b'#' {
77 if stdin.read(&mut r[..])? == 0 { return Ok(0) }
79 if stdin.read(&mut r[..])? == 0 { return Ok(0) }
80 return Ok(r[0])
81 } else {
82 if stdin.read(&mut r[..])? == 0 { return Ok(0) }
84 return Ok(r[0])
85 }
86 } else {
87 return Ok(r[0])
89 }
90 }
91 }
92 }
93}
94
95impl Drop for Getch {
96 #[cfg(not(windows))]
97 fn drop(&mut self) {
98 if let Getch::Termios(ref mut termios) = *self {
99 tcsetattr(0, termios::TCSADRAIN, &termios).unwrap_or(())
100 }
101 }
102 #[cfg(windows)]
103 fn drop(&mut self) {
104 }
105}