77
88use crate :: result:: { Error , Result } ;
99use crate :: uart:: Uart ;
10+ use core:: time:: Duration ;
1011
11- pub fn readline < ' a > (
12- prompt : & str ,
12+ #[ derive( Debug , Eq , PartialEq ) ]
13+ pub enum Prompt {
14+ Tenex ,
15+ Spinner ,
16+ Pulser ,
17+ }
18+
19+ const BS : u8 = 8 ;
20+ const TAB : u8 = 9 ;
21+ const NL : u8 = 10 ;
22+ const CR : u8 = 13 ;
23+ const CTLU : u8 = 21 ;
24+ const CTLW : u8 = 23 ;
25+ const ESC : u8 = 27 ;
26+ const DEL : u8 = 127 ;
27+
28+ pub fn readline < ' a , F > (
29+ prompt : F ,
1330 uart : & mut Uart ,
1431 line : & ' a mut [ u8 ] ,
15- ) -> Result < & ' a str > {
16- const BS : u8 = 8 ;
17- const TAB : u8 = 9 ;
18- const NL : u8 = 10 ;
19- const CR : u8 = 13 ;
20- const CTLU : u8 = 21 ;
21- const CTLW : u8 = 23 ;
22- const DEL : u8 = 127 ;
32+ ) -> Result < & ' a str >
33+ where
34+ F : FnOnce ( & mut Uart ) -> usize ,
35+ {
36+ readline_timeout ( prompt, uart, Duration :: ZERO , line)
37+ }
2338
39+ pub fn readline_timeout < ' a , F > (
40+ prompt : F ,
41+ uart : & mut Uart ,
42+ timeout : Duration ,
43+ line : & ' a mut [ u8 ] ,
44+ ) -> Result < & ' a str >
45+ where
46+ F : FnOnce ( & mut Uart ) -> usize ,
47+ {
2448 fn find_prev_col ( line : & [ u8 ] , start : usize ) -> usize {
2549 line. iter ( )
2650 . fold ( start, |v, & b| v + if b == TAB { 8 - ( v & 0b111 ) } else { 1 } )
2751 }
2852
29- fn backspace (
53+ fn backup (
3054 uart : & mut Uart ,
3155 line : & [ u8 ] ,
3256 start : usize ,
@@ -43,11 +67,7 @@ pub fn readline<'a>(
4367 _ => ( col - 1 , true ) ,
4468 } ;
4569 for _ in pcol..col {
46- uart. putb ( BS ) ;
47- if overstrike {
48- uart. putb ( b' ' ) ;
49- uart. putb ( BS ) ;
50- }
70+ backspace ( uart, overstrike) ;
5171 }
5272 ( pcol, line. len ( ) - 1 )
5373 }
@@ -60,43 +80,47 @@ pub fn readline<'a>(
6080 return Ok ( "" ) ;
6181 }
6282
63- let start = prompt. len ( ) ;
64- uart. puts ( prompt) ;
83+ let start = prompt ( uart) ;
6584
6685 let mut k = 0 ;
6786 let mut col = start;
6887 while k < line. len ( ) {
69- match uart. getb ( ) {
70- CR | NL => {
88+ match uart. getb_timeout ( timeout) {
89+ None => {
90+ if k == 0 {
91+ return Err ( Error :: Timeout ) ;
92+ }
93+ }
94+ Some ( CR | NL ) => {
7195 uart. putb ( CR ) ;
7296 uart. putb ( NL ) ;
7397 break ;
7498 }
75- BS | DEL => {
99+ Some ( BS | DEL ) => {
76100 if k > 0 {
77- ( col, k) = backspace ( uart, & line[ ..k] , start, col) ;
101+ ( col, k) = backup ( uart, & line[ ..k] , start, col) ;
78102 }
79103 }
80- CTLU => {
104+ Some ( CTLU ) => {
81105 while k > 0 {
82- ( col, k) = backspace ( uart, & line[ ..k] , start, col) ;
106+ ( col, k) = backup ( uart, & line[ ..k] , start, col) ;
83107 }
84108 }
85- CTLW => {
109+ Some ( CTLW ) => {
86110 while k > 0 && line[ k - 1 ] . is_ascii_whitespace ( ) {
87- ( col, k) = backspace ( uart, & line[ ..k] , start, col) ;
111+ ( col, k) = backup ( uart, & line[ ..k] , start, col) ;
88112 }
89113 if k > 0 {
90114 let cond = isword ( line[ k - 1 ] ) ;
91115 while k > 0
92116 && !line[ k - 1 ] . is_ascii_whitespace ( )
93117 && isword ( line[ k - 1 ] ) == cond
94118 {
95- ( col, k) = backspace ( uart, & line[ ..k] , start, col) ;
119+ ( col, k) = backup ( uart, & line[ ..k] , start, col) ;
96120 }
97121 }
98122 }
99- TAB => {
123+ Some ( TAB ) => {
100124 line[ k] = TAB ;
101125 k += 1 ;
102126 let ncol = ( 8 + col) & !0b111 ;
@@ -105,7 +129,7 @@ pub fn readline<'a>(
105129 }
106130 col = ncol;
107131 }
108- b => {
132+ Some ( b ) => {
109133 line[ k] = b;
110134 k += 1 ;
111135 uart. putb ( b) ;
@@ -117,10 +141,45 @@ pub fn readline<'a>(
117141 core:: str:: from_utf8 ( & line[ ..k] ) . map_err ( |_| Error :: Utf8 )
118142}
119143
144+ pub fn backspace ( term : & mut Uart , overstrike : bool ) {
145+ term. putb ( BS ) ;
146+ if overstrike {
147+ term. putb ( b' ' ) ;
148+ term. putb ( BS ) ;
149+ }
150+ }
151+
120152pub fn clear ( term : & mut Uart ) {
121- const ESC : u8 = 27 ;
122153 term. putb ( ESC ) ;
123154 term. puts ( "[H" ) ;
124155 term. putb ( ESC ) ;
125156 term. puts ( "[2J" ) ;
126157}
158+
159+ pub fn cycle (
160+ term : & mut Uart ,
161+ prefix : & [ u8 ] ,
162+ cycle : & [ u8 ] ,
163+ suffix : & [ u8 ] ,
164+ wait : Duration ,
165+ ) {
166+ fn erase ( term : & mut Uart , bs : & [ u8 ] ) {
167+ for & b in bs. iter ( ) . rev ( ) {
168+ backspace ( term, b != b' ' ) ;
169+ }
170+ }
171+ let _ = term. putbs ( prefix) ;
172+ for & b in cycle. iter ( ) . cycle ( ) {
173+ term. putb ( b) ;
174+ let _ = term. putbs ( suffix) ;
175+ match term. wait_data_ready ( wait) {
176+ Ok ( true ) | Err ( _) => break ,
177+ _ => { }
178+ }
179+ erase ( term, suffix) ;
180+ erase ( term, & [ b] ) ;
181+ }
182+ erase ( term, suffix) ;
183+ erase ( term, & [ 0 ] ) ;
184+ erase ( term, prefix) ;
185+ }
0 commit comments