1+ use console:: Term ;
2+ use indicatif:: TermLike ;
13use std:: {
24 io:: { self , Write } ,
35 mem:: MaybeUninit ,
@@ -6,8 +8,8 @@ use std::{
68 sync:: { Arc , Mutex , MutexGuard } ,
79} ;
810
9- pub ( crate ) use termcolor:: Color ;
10- use termcolor:: { ColorChoice , ColorSpec , StandardStream , StandardStreamLock , WriteColor } ;
11+ pub ( crate ) use termcolor:: { Color , ColorChoice } ;
12+ use termcolor:: { ColorSpec , StandardStream , StandardStreamLock , WriteColor } ;
1113
1214use super :: Process ;
1315#[ cfg( feature = "test" ) ]
@@ -53,6 +55,8 @@ pub struct ColorableTerminal {
5355 // source is important because otherwise parallel constructed terminals
5456 // would not be locked out.
5557 inner : Arc < Mutex < TerminalInner > > ,
58+ is_a_tty : bool ,
59+ color_choice : ColorChoice ,
5660}
5761
5862/// Internal state for ColorableTerminal
@@ -84,10 +88,11 @@ impl ColorableTerminal {
8488 /// then color commands will be sent to the stream.
8589 /// Otherwise color commands are discarded.
8690 pub ( super ) fn new ( stream : StreamSelector , process : & Process ) -> Self {
91+ let is_a_tty = stream. is_a_tty ( process) ;
8792 let choice = match process. var ( "RUSTUP_TERM_COLOR" ) {
8893 Ok ( s) if s. eq_ignore_ascii_case ( "always" ) => ColorChoice :: Always ,
8994 Ok ( s) if s. eq_ignore_ascii_case ( "never" ) => ColorChoice :: Never ,
90- _ if stream . is_a_tty ( process ) => ColorChoice :: Auto ,
95+ _ if is_a_tty => ColorChoice :: Auto ,
9196 _ => ColorChoice :: Never ,
9297 } ;
9398 let inner = match stream {
@@ -104,6 +109,8 @@ impl ColorableTerminal {
104109 } ;
105110 ColorableTerminal {
106111 inner : Arc :: new ( Mutex :: new ( inner) ) ,
112+ is_a_tty,
113+ color_choice : choice,
107114 }
108115 }
109116
@@ -179,6 +186,14 @@ impl ColorableTerminal {
179186 } ;
180187 Ok ( ( ) )
181188 }
189+
190+ pub fn is_a_tty ( & self ) -> bool {
191+ self . is_a_tty
192+ }
193+
194+ pub fn color_choice ( & self ) -> ColorChoice {
195+ self . color_choice
196+ }
182197}
183198
184199#[ derive( Copy , Clone , Debug ) ]
@@ -223,6 +238,81 @@ impl io::Write for ColorableTerminalLocked {
223238 }
224239}
225240
241+ impl TermLike for ColorableTerminal {
242+ fn width ( & self ) -> u16 {
243+ Term :: stdout ( ) . size ( ) . 1
244+ }
245+
246+ fn move_cursor_up ( & self , n : usize ) -> io:: Result < ( ) > {
247+ // As the ProgressBar may try to move the cursor up by 0 lines,
248+ // we need to handle that case to avoid writing an escape sequence
249+ // that would mess up the terminal.
250+ if n == 0 {
251+ return Ok ( ( ) ) ;
252+ }
253+ let mut t = self . lock ( ) ;
254+ write ! ( t, "\x1b [{n}A" ) ?;
255+ t. flush ( )
256+ }
257+
258+ fn move_cursor_down ( & self , n : usize ) -> io:: Result < ( ) > {
259+ if n == 0 {
260+ return Ok ( ( ) ) ;
261+ }
262+ let mut t = self . lock ( ) ;
263+ write ! ( t, "\x1b [{n}B" ) ?;
264+ t. flush ( )
265+ }
266+
267+ fn move_cursor_right ( & self , n : usize ) -> io:: Result < ( ) > {
268+ if n == 0 {
269+ return Ok ( ( ) ) ;
270+ }
271+ let mut t = self . lock ( ) ;
272+ write ! ( t, "\x1b [{n}C" ) ?;
273+ t. flush ( )
274+ }
275+
276+ fn move_cursor_left ( & self , n : usize ) -> io:: Result < ( ) > {
277+ if n == 0 {
278+ return Ok ( ( ) ) ;
279+ }
280+ let mut t = self . lock ( ) ;
281+ write ! ( t, "\x1b [{n}D" ) ?;
282+ t. flush ( )
283+ }
284+
285+ fn write_line ( & self , line : & str ) -> io:: Result < ( ) > {
286+ let mut t = self . lock ( ) ;
287+ t. write_all ( line. as_bytes ( ) ) ?;
288+ t. write_all ( b"\n " ) ?;
289+ t. flush ( )
290+ }
291+
292+ fn write_str ( & self , s : & str ) -> io:: Result < ( ) > {
293+ let mut t = self . lock ( ) ;
294+ t. write_all ( s. as_bytes ( ) ) ?;
295+ t. flush ( )
296+ }
297+
298+ fn clear_line ( & self ) -> io:: Result < ( ) > {
299+ let mut t = self . lock ( ) ;
300+ t. write_all ( b"\r \x1b [2K" ) ?;
301+ t. flush ( )
302+ }
303+
304+ fn flush ( & self ) -> io:: Result < ( ) > {
305+ let mut t = self . lock ( ) ;
306+ t. flush ( )
307+ }
308+ }
309+
310+ impl std:: fmt:: Debug for ColorableTerminal {
311+ fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
312+ write ! ( f, "ColorableTerminal {{ inner: ... }}" )
313+ }
314+ }
315+
226316#[ cfg( test) ]
227317mod tests {
228318 use std:: collections:: HashMap ;
0 commit comments