@@ -15,6 +15,7 @@ use dfx_core::extension::manager::ExtensionManager;
1515use indicatif:: MultiProgress ;
1616use std:: collections:: HashMap ;
1717use std:: ffi:: OsString ;
18+ use std:: io:: { IsTerminal , Write , stderr} ;
1819use std:: path:: PathBuf ;
1920use std:: time:: Instant ;
2021use util:: default_allowlisted_canisters;
@@ -72,8 +73,19 @@ fn setup_logging(opts: &CliOpts) -> (i64, slog::Logger, MultiProgress) {
7273 ( verbose_level, logger, spinners)
7374}
7475
76+ /// Returns true if colored output should be used on stderr.
77+ /// Respects the NO_COLOR environment variable (https://no-color.org/).
78+ fn use_color ( ) -> bool {
79+ std:: env:: var_os ( "NO_COLOR" ) . is_none ( ) && stderr ( ) . is_terminal ( )
80+ }
81+
7582fn print_error_and_diagnosis ( log_level : Option < i64 > , err : Error , error_diagnosis : DiagnosedError ) {
76- let mut stderr = util:: stderr_wrapper:: stderr_wrapper ( ) ;
83+ let mut stderr = stderr ( ) . lock ( ) ;
84+ let use_color = use_color ( ) ;
85+
86+ const RED : & str = "\x1b [31m" ;
87+ const YELLOW : & str = "\x1b [33m" ;
88+ const RESET : & str = "\x1b [0m" ;
7789
7890 // print error chain stack
7991 if log_level. unwrap_or_default ( ) > 0 // DEBUG or more verbose
@@ -85,43 +97,35 @@ fn print_error_and_diagnosis(log_level: Option<i64>, err: Error, error_diagnosis
8597 }
8698
8799 let ( color, prefix) = if level == 0 {
88- ( term :: color :: RED , "Error" )
100+ ( RED , "Error" )
89101 } else {
90- ( term :: color :: YELLOW , "Caused by" )
102+ ( YELLOW , "Caused by" )
91103 } ;
92- stderr
93- . fg ( color)
94- . expect ( "Failed to set stderr output color." ) ;
95- write ! ( stderr, "{prefix}: " ) . expect ( "Failed to write to stderr." ) ;
96- stderr
97- . reset ( )
98- . expect ( "Failed to reset stderr output color." ) ;
104+ if use_color {
105+ write ! ( stderr, "{color}{prefix}: {RESET}" ) . expect ( "Failed to write to stderr." ) ;
106+ } else {
107+ write ! ( stderr, "{prefix}: " ) . expect ( "Failed to write to stderr." ) ;
108+ }
99109
100110 writeln ! ( stderr, "{cause}" ) . expect ( "Failed to write to stderr." ) ;
101111 }
102112 }
103113
104114 // print diagnosis
105115 if let Some ( explanation) = error_diagnosis. explanation {
106- stderr
107- . fg ( term:: color:: RED )
108- . expect ( "Failed to set stderr output color." ) ;
109- write ! ( stderr, "Error: " ) . expect ( "Failed to write to stderr." ) ;
110- stderr
111- . reset ( )
112- . expect ( "Failed to reset stderr output color." ) ;
113-
116+ if use_color {
117+ write ! ( stderr, "{RED}Error: {RESET}" ) . expect ( "Failed to write to stderr." ) ;
118+ } else {
119+ write ! ( stderr, "Error: " ) . expect ( "Failed to write to stderr." ) ;
120+ }
114121 writeln ! ( stderr, "{explanation}" ) . expect ( "Failed to write to stderr." ) ;
115122 }
116123 if let Some ( action_suggestion) = error_diagnosis. action_suggestion {
117- stderr
118- . fg ( term:: color:: YELLOW )
119- . expect ( "Failed to set stderr output color." ) ;
120- write ! ( stderr, "To fix: " ) . expect ( "Failed to write to stderr." ) ;
121- stderr
122- . reset ( )
123- . expect ( "Failed to reset stderr output color." ) ;
124-
124+ if use_color {
125+ write ! ( stderr, "{YELLOW}To fix: {RESET}" ) . expect ( "Failed to write to stderr." ) ;
126+ } else {
127+ write ! ( stderr, "To fix: " ) . expect ( "Failed to write to stderr." ) ;
128+ }
125129 writeln ! ( stderr, "{action_suggestion}" ) . expect ( "Failed to write to stderr." ) ;
126130 }
127131}
0 commit comments