4242{
4343 loop {
4444 print ! ( "{before}" ) ;
45- io :: stdout ( ) . flush ( ) . unwrap ( ) ;
45+ flush ( ) ;
4646
4747 let mut cli = String :: new ( ) ;
4848 io:: stdin ( ) . read_line ( & mut cli) . unwrap ( ) ;
@@ -109,75 +109,78 @@ pub fn select(
109109) -> Option < Vec < bool > > {
110110 loop {
111111 let mut matrix: Vec < bool > = vec ! [ ] ;
112+ let mut i = 0 ;
112113 let stdout = Term :: buffered_stdout ( ) ;
113114
114- println ! ( "{}\n " , before, ) ;
115+ // print everything
116+ println ! ( "{}" , before, ) ;
115117
116118 for i in options {
117119 println ! ( "[ ] {}" , i) ;
118120 matrix. push ( false ) ;
119121 }
120122
121- stdout . move_cursor_up ( options . len ( ) ) . unwrap ( ) ;
122- stdout . flush ( ) . unwrap ( ) ;
123- let mut i = 0 ;
123+ // move the cursor to the first item
124+ move_cursor_up ( options . len ( ) ) ;
125+ move_cursor_right ( options [ i ] . len ( ) + 4 ) ;
124126
127+ // input reaction loop
125128 loop {
126129 if let Ok ( character) = stdout. read_key ( ) {
127130 match character {
128131 Key :: ArrowUp | Key :: Char ( 'w' ) => {
129132 if i > 0 {
130- stdout. move_cursor_up ( 1 ) . unwrap ( ) ;
133+ move_cursor_up ( 1 ) ;
134+ move_cursor_left ( options[ i] . len ( ) + 4 ) ;
131135 i -= 1 ;
136+ move_cursor_right ( options[ i] . len ( ) + 4 ) ;
132137 }
133138 }
134139 Key :: ArrowDown | Key :: Char ( 's' ) => {
135140 if i < options. len ( ) - 1 {
136- stdout. move_cursor_down ( 1 ) . unwrap ( ) ;
141+ move_cursor_down ( 1 ) ;
142+ move_cursor_left ( options[ i] . len ( ) + 4 ) ;
137143 i += 1 ;
144+ move_cursor_right ( options[ i] . len ( ) + 4 ) ;
138145 }
139146 }
140147 Key :: Char ( ' ' ) => {
141- stdout . clear_line ( ) . unwrap ( ) ;
148+ clear_line ( ) ;
142149 if matrix[ i] {
143- stdout . write_line ( & format ! ( "[ ] {}" , options[ i] ) ) . unwrap ( ) ;
150+ print ! ( "[ ] {}" , options[ i] ) ;
144151 matrix[ i] = false ;
145152 } else {
146- stdout
147- . write_line ( & format ! ( "[{}] {}" , style( "*" ) . cyan( ) , options[ i] ) )
148- . unwrap ( ) ;
153+ print ! ( "[{}] {}" , style( "*" ) . cyan( ) , options[ i] ) ;
149154 matrix[ i] = true ;
150155 }
151- stdout. move_cursor_up ( 1 ) . unwrap ( ) ;
152- stdout. flush ( ) . unwrap ( ) ;
156+ flush ( ) ;
153157 }
154158 Key :: Enter => {
155159 break ;
156160 }
157161 _ => { }
158162 }
159163 }
160- stdout. flush ( ) . unwrap ( ) ;
161164 }
162165
166+ // process input
163167 if matrix. iter ( ) . filter ( |& & selected| selected) . count ( ) > 1 && !multiple {
164- reset ( stdout , "\n Please Select only one!\n " , options. len ( ) ) ;
168+ reset ( "\n Please Select only one!\n " , options. len ( ) ) ;
165169 } else if allow_empty && matrix. iter ( ) . all ( |& x| !x) {
166- reset ( stdout , "" , options. len ( ) ) ;
170+ reset ( "" , options. len ( ) ) ;
167171 return None ;
168172 } else if !matrix. iter ( ) . all ( |& x| !x) {
169- reset ( stdout , "" , options. len ( ) ) ;
173+ reset ( "" , options. len ( ) ) ;
170174 return Some ( matrix) ;
171175 } else {
172- reset ( stdout , "\n Please Select any option!\n " , options. len ( ) ) ;
176+ reset ( "\n Please Select any option!\n " , options. len ( ) ) ;
173177 }
174178 }
175179}
176180
177181// Internal function for resetting the console.
178- fn reset ( stdout : Term , mes : & str , len : usize ) {
179- stdout. move_cursor_down ( len) . unwrap ( ) ;
180- stdout. flush ( ) . unwrap ( ) ;
182+ fn reset ( mes : & str , len : usize ) {
183+ move_cursor_down ( len) ;
181184 println ! ( "{mes}" ) ;
182185}
183186
@@ -237,7 +240,7 @@ pub fn spinner(mut time: f64, spinner_type: SpinnerType) {
237240 while time > 0.0 {
238241 clear_line ( ) ;
239242 print ! ( "{}" , frames[ i] ) ;
240- io :: stdout ( ) . flush ( ) . unwrap ( ) ;
243+ flush ( ) ;
241244 thread:: sleep ( Duration :: from_secs_f64 ( 0.075 ) ) ;
242245 time -= 0.075 ;
243246 if i < frames. len ( ) - 1 {
@@ -250,6 +253,20 @@ pub fn spinner(mut time: f64, spinner_type: SpinnerType) {
250253 clear_line ( ) ;
251254}
252255
256+ /// Flushes the output buffer, ensuring that all content is written to the console.
257+ ///
258+ /// # Example
259+ ///
260+ /// ```rust
261+ /// use console_utils::flush;
262+ ///
263+ /// // Flush the output buffer to ensure content is displayed immediately
264+ /// flush();
265+ /// ```
266+ pub fn flush ( ) {
267+ io:: stdout ( ) . flush ( ) . unwrap ( ) ;
268+ }
269+
253270/// Clears the current line in the console.
254271///
255272/// This function uses ANSI escape codes to clear the entire line and move the cursor to the
@@ -265,7 +282,111 @@ pub fn spinner(mut time: f64, spinner_type: SpinnerType) {
265282/// ```
266283pub fn clear_line ( ) {
267284 print ! ( "\r \x1b [2K" ) ;
268- io:: stdout ( ) . flush ( ) . unwrap ( ) ;
285+ flush ( ) ;
286+ }
287+
288+ /// Moves the cursor down by the specified number of lines.
289+ ///
290+ /// # Arguments
291+ ///
292+ /// * `n` - The number of lines to move the cursor down.
293+ ///
294+ /// # Example
295+ ///
296+ /// ```rust
297+ /// use console_utils::move_cursor_down;
298+ ///
299+ /// // Move the cursor down by 2 lines
300+ /// move_cursor_down(2);
301+ /// ```
302+ pub fn move_cursor_down ( n : usize ) {
303+ if n > 0 {
304+ print ! ( "\x1b [{}B" , n) ;
305+ flush ( ) ;
306+ }
307+ }
308+
309+ /// Moves the cursor up by the specified number of lines.
310+ ///
311+ /// # Arguments
312+ ///
313+ /// * `n` - The number of lines to move the cursor up.
314+ ///
315+ /// # Example
316+ ///
317+ /// ```rust
318+ /// use console_utils::move_cursor_up;
319+ ///
320+ /// // Move the cursor up by 3 lines
321+ /// move_cursor_up(3);
322+ /// ```
323+ pub fn move_cursor_up ( n : usize ) {
324+ if n > 0 {
325+ print ! ( "\x1b [{}A" , n) ;
326+ flush ( ) ;
327+ }
328+ }
329+
330+ /// Moves the cursor to the left by the specified number of characters.
331+ ///
332+ /// # Arguments
333+ ///
334+ /// * `n` - The number of characters to move the cursor to the left.
335+ ///
336+ /// # Example
337+ ///
338+ /// ```rust
339+ /// use console_utils::move_cursor_left;
340+ ///
341+ /// // Move the cursor left by 4 characters
342+ /// move_cursor_left(4);
343+ /// ```
344+ pub fn move_cursor_left ( n : usize ) {
345+ if n > 0 {
346+ print ! ( "\x1b [{}D" , n) ;
347+ flush ( ) ;
348+ }
349+ }
350+
351+ /// Moves the cursor to the right by the specified number of characters.
352+ ///
353+ /// # Arguments
354+ ///
355+ /// * `n` - The number of characters to move the cursor to the right.
356+ ///
357+ /// # Example
358+ ///
359+ /// ```rust
360+ /// use console_utils::move_cursor_right;
361+ ///
362+ /// // Move the cursor right by 5 characters
363+ /// move_cursor_right(5);
364+ /// ```
365+ pub fn move_cursor_right ( n : usize ) {
366+ if n > 0 {
367+ print ! ( "\x1b [{}C" , n) ;
368+ flush ( ) ;
369+ }
370+ }
371+
372+ /// Moves the cursor to the specified position on the console.
373+ ///
374+ /// # Arguments
375+ ///
376+ /// * `x` - The horizontal position (column) to move the cursor to.
377+ /// * `y` - The vertical position (row) to move the cursor to.
378+ ///
379+ /// # Example
380+ ///
381+ /// ```rust
382+ /// use console_utils::move_cursor_to;
383+ ///
384+ /// // Move the cursor to column 3, row 5
385+ /// move_cursor_to(3, 5);
386+ /// ```
387+ pub fn move_cursor_to ( x : usize , y : usize ) {
388+ print ! ( "\x1B [{};{}H" , y + 1 , x + 1 ) ;
389+ flush ( ) ;
269390}
270391
271392/// Reveals a string gradually, printing one character at a time with a specified time interval.
@@ -288,7 +409,7 @@ pub fn clear_line() {
288409pub fn reveal ( str : & str , time_between : f64 ) {
289410 for i in 0 ..str. len ( ) {
290411 print ! ( "{}" , str . chars( ) . nth( i) . unwrap_or( ' ' ) ) ;
291- io :: stdout ( ) . flush ( ) . unwrap ( ) ;
412+ flush ( ) ;
292413 thread:: sleep ( Duration :: from_secs_f64 ( time_between) ) ;
293414 }
294415}
0 commit comments