@@ -80,6 +80,60 @@ pub fn read_secure() -> io::Result<String> {
8080 } )
8181}
8282
83+ fn read_single_byte ( fd : i32 ) -> io:: Result < Option < u8 > > {
84+ let mut readfds = core:: mem:: MaybeUninit :: uninit ( ) ;
85+ unsafe {
86+ libc:: FD_SET ( fd, readfds. as_mut_ptr ( ) ) ;
87+ } ;
88+ let mut readfds = unsafe { readfds. assume_init ( ) } ;
89+
90+ // zero timeout, i.e check if there is something to be read right now
91+ let mut timeout = libc:: timeval {
92+ tv_sec : 0 ,
93+ tv_usec : 0 ,
94+ } ;
95+
96+ let ret = unsafe {
97+ libc:: select (
98+ fd + 1 ,
99+ & mut readfds as * mut _ ,
100+ std:: ptr:: null_mut ( ) ,
101+ std:: ptr:: null_mut ( ) ,
102+ & mut timeout,
103+ )
104+ } ;
105+ if ret < 0 {
106+ return Err ( io:: Error :: last_os_error ( ) ) ;
107+ }
108+
109+ let is_ready = unsafe { libc:: FD_ISSET ( fd, & mut readfds as * mut _ ) } ;
110+
111+ if is_ready {
112+ //there is something to be read
113+
114+ // let mut buf: [u8; 1] = [0];
115+ // let read = unsafe { libc::read(fd, buf.as_mut_ptr() as *mut libc::c_void, 1) };
116+
117+ //read only 1 byte
118+ let mut byte: u8 = 0 ;
119+ let read = unsafe { libc:: read ( fd, & mut byte as * mut u8 as _ , 1 ) } ;
120+
121+ if read < 0 {
122+ Err ( io:: Error :: last_os_error ( ) )
123+ } else if byte == b'\x03' {
124+ Err ( io:: Error :: new (
125+ io:: ErrorKind :: Interrupted ,
126+ "read interrupted" ,
127+ ) )
128+ } else {
129+ Ok ( Some ( byte) )
130+ }
131+ } else {
132+ //there is nothing to be read
133+ Ok ( None )
134+ }
135+ }
136+
83137pub fn read_single_key ( ) -> io:: Result < Key > {
84138 let tty_f;
85139 let fd = unsafe {
@@ -92,74 +146,118 @@ pub fn read_single_key() -> io::Result<Key> {
92146 } ;
93147 let mut buf = [ 0u8 ; 20 ] ;
94148 let mut termios = core:: mem:: MaybeUninit :: uninit ( ) ;
95- c_result ( || unsafe { libc:: tcgetattr ( fd, termios. as_mut_ptr ( ) ) } ) ?;
149+ c_result ( || unsafe { libc:: tcgetattr ( fd, termios. as_mut_ptr ( ) ) } ) ?;
96150 let mut termios = unsafe { termios. assume_init ( ) } ;
97151 let original = termios;
98152 unsafe { libc:: cfmakeraw ( & mut termios) } ;
99153 c_result ( || unsafe { libc:: tcsetattr ( fd, libc:: TCSADRAIN , & termios) } ) ?;
100- let rv = unsafe {
101- let read = libc:: read ( fd, buf. as_mut_ptr ( ) as * mut libc:: c_void , 1 ) ;
102- if read < 0 {
103- Err ( io:: Error :: last_os_error ( ) )
104- } else if buf[ 0 ] == b'\x1b' {
105- // read 19 more bytes if the first byte was the ESC code
106- let read = libc:: read ( fd, buf[ 1 ..] . as_mut_ptr ( ) as * mut libc:: c_void , 19 ) ;
107- if read < 0 {
108- Err ( io:: Error :: last_os_error ( ) )
109- } else if buf[ 1 ] == b'\x03' {
110- Err ( io:: Error :: new (
111- io:: ErrorKind :: Interrupted ,
112- "read interrupted" ,
113- ) )
114- } else {
115- Ok ( key_from_escape_codes ( & buf[ ..( read + 1 ) as usize ] ) )
116- }
117- } else if buf[ 0 ] & 224u8 == 192u8 {
118- // a two byte unicode character
119- let read = libc:: read ( fd, buf[ 1 ..] . as_mut_ptr ( ) as * mut libc:: c_void , 1 ) ;
120- if read < 0 {
121- Err ( io:: Error :: last_os_error ( ) )
122- } else if buf[ 1 ] == b'\x03' {
123- Err ( io:: Error :: new (
124- io:: ErrorKind :: Interrupted ,
125- "read interrupted" ,
126- ) )
154+
155+ let byte = read_single_byte ( fd) ?;
156+ let rv = match byte {
157+ Some ( b'\x1b' ) => {
158+ // Escape was read, keep reading in case we find a familiar key
159+ if let Some ( b1) = read_single_byte ( fd) ? {
160+ if b1 == b'[' {
161+ if let Some ( b2) = read_single_byte ( fd) ? {
162+ match b2 {
163+ b'A' => Ok ( Key :: ArrowUp ) ,
164+ b'B' => Ok ( Key :: ArrowDown ) ,
165+ b'C' => Ok ( Key :: ArrowRight ) ,
166+ b'D' => Ok ( Key :: ArrowLeft ) ,
167+ b'H' => Ok ( Key :: Home ) ,
168+ b'F' => Ok ( Key :: End ) ,
169+ b'3' => {
170+ if let Some ( b'~' ) = read_single_byte ( fd) ? {
171+ Ok ( Key :: Del )
172+ } else {
173+ Ok ( Key :: Escape )
174+ }
175+ }
176+ _ => Ok ( Key :: Escape ) ,
177+ }
178+ } else {
179+ // \x1b[ and no more input
180+ Ok ( Key :: Escape )
181+ }
182+ } else {
183+ // char after escape is not [
184+ Ok ( Key :: Escape )
185+ }
127186 } else {
128- Ok ( key_from_escape_codes ( & buf[ ..2 as usize ] ) )
187+ //nothing after escape
188+ Ok ( Key :: Escape )
129189 }
130- } else if buf[ 0 ] & 240u8 == 224u8 {
131- // a three byte unicode character
132- let read = libc:: read ( fd, buf[ 1 ..] . as_mut_ptr ( ) as * mut libc:: c_void , 2 ) ;
133- if read < 0 {
134- Err ( io:: Error :: last_os_error ( ) )
135- } else if buf[ 1 ] == b'\x03' {
136- Err ( io:: Error :: new (
137- io:: ErrorKind :: Interrupted ,
138- "read interrupted" ,
139- ) )
190+ }
191+ Some ( byte) => {
192+ buf[ 0 ] = byte;
193+ if byte & 224u8 == 192u8 {
194+ // a two byte unicode character
195+ let read = unsafe { libc:: read ( fd, buf[ 1 ..] . as_mut_ptr ( ) as * mut libc:: c_void , 1 ) } ;
196+ if read < 0 {
197+ Err ( io:: Error :: last_os_error ( ) )
198+ } else if buf[ 1 ] == b'\x03' {
199+ Err ( io:: Error :: new (
200+ io:: ErrorKind :: Interrupted ,
201+ "read interrupted" ,
202+ ) )
203+ } else {
204+ Ok ( key_from_escape_codes ( & buf[ ..2 as usize ] ) )
205+ }
206+ } else if byte & 240u8 == 224u8 {
207+ // a three byte unicode character
208+ let read = unsafe { libc:: read ( fd, buf[ 1 ..] . as_mut_ptr ( ) as * mut libc:: c_void , 2 ) } ;
209+ if read < 0 {
210+ Err ( io:: Error :: last_os_error ( ) )
211+ } else if buf[ 1 ] == b'\x03' {
212+ Err ( io:: Error :: new (
213+ io:: ErrorKind :: Interrupted ,
214+ "read interrupted" ,
215+ ) )
216+ } else {
217+ Ok ( key_from_escape_codes ( & buf[ ..3 as usize ] ) )
218+ }
219+ } else if byte & 248u8 == 240u8 {
220+ // a four byte unicode character
221+ let read = unsafe { libc:: read ( fd, buf[ 1 ..] . as_mut_ptr ( ) as * mut libc:: c_void , 3 ) } ;
222+ if read < 0 {
223+ Err ( io:: Error :: last_os_error ( ) )
224+ } else if buf[ 1 ] == b'\x03' {
225+ Err ( io:: Error :: new (
226+ io:: ErrorKind :: Interrupted ,
227+ "read interrupted" ,
228+ ) )
229+ } else {
230+ Ok ( key_from_escape_codes ( & buf[ ..4 as usize ] ) )
231+ }
140232 } else {
141- Ok ( key_from_escape_codes ( & buf [ .. 3 as usize ] ) )
233+ Ok ( key_from_escape_codes ( & [ byte ] ) )
142234 }
143- } else if buf[ 0 ] & 248u8 == 240u8 {
144- // a four byte unicode character
145- let read = libc:: read ( fd, buf[ 1 ..] . as_mut_ptr ( ) as * mut libc:: c_void , 3 ) ;
146- if read < 0 {
147- Err ( io:: Error :: last_os_error ( ) )
148- } else if buf[ 1 ] == b'\x03' {
149- Err ( io:: Error :: new (
150- io:: ErrorKind :: Interrupted ,
151- "read interrupted" ,
152- ) )
153- } else {
154- Ok ( key_from_escape_codes ( & buf[ ..4 as usize ] ) )
235+ }
236+ None => {
237+ //there is no subsequent byte ready to be read, block and wait for input
238+
239+ let mut readfds = core:: mem:: MaybeUninit :: uninit ( ) ;
240+ unsafe {
241+ libc:: FD_SET ( fd, readfds. as_mut_ptr ( ) ) ;
242+ } ;
243+ let mut readfds = unsafe { readfds. assume_init ( ) } ;
244+
245+ // block until there is something to be read
246+ let ret = unsafe {
247+ libc:: select (
248+ fd + 1 ,
249+ & mut readfds as * mut _ ,
250+ std:: ptr:: null_mut ( ) ,
251+ std:: ptr:: null_mut ( ) ,
252+ // null timeout pointer means that it will block indefinitely
253+ std:: ptr:: null_mut ( ) ,
254+ )
255+ } ;
256+ if ret < 0 {
257+ return Err ( io:: Error :: last_os_error ( ) ) ;
155258 }
156- } else if buf[ 0 ] == b'\x03' {
157- Err ( io:: Error :: new (
158- io:: ErrorKind :: Interrupted ,
159- "read interrupted" ,
160- ) )
161- } else {
162- Ok ( key_from_escape_codes ( & buf[ ..read as usize ] ) )
259+
260+ read_single_key ( )
163261 }
164262 } ;
165263 c_result ( || unsafe { libc:: tcsetattr ( fd, libc:: TCSADRAIN , & original) } ) ?;
@@ -178,17 +276,17 @@ pub fn read_single_key() -> io::Result<Key> {
178276
179277pub fn key_from_escape_codes ( buf : & [ u8 ] ) -> Key {
180278 match buf {
181- b"\x1b [D" => Key :: ArrowLeft ,
182- b"\x1b [C" => Key :: ArrowRight ,
279+ b"\x1b " => Key :: Escape ,
183280 b"\x1b [A" => Key :: ArrowUp ,
184281 b"\x1b [B" => Key :: ArrowDown ,
185- b"\n " | b"\r " => Key :: Enter ,
186- b"\x1b " => Key :: Escape ,
187- b"\x7f " => Key :: Backspace ,
282+ b"\x1b [C" => Key :: ArrowRight ,
283+ b"\x1b [D" => Key :: ArrowLeft ,
188284 b"\x1b [H" => Key :: Home ,
189285 b"\x1b [F" => Key :: End ,
190- b"\t " => Key :: Tab ,
191286 b"\x1b [3~" => Key :: Del ,
287+ b"\n " | b"\r " => Key :: Enter ,
288+ b"\x7f " => Key :: Backspace ,
289+ b"\t " => Key :: Tab ,
192290 buf => {
193291 if let Ok ( s) = str:: from_utf8 ( buf) {
194292 if let Some ( c) = s. chars ( ) . next ( ) {
0 commit comments