@@ -161,9 +161,23 @@ pub fn style<D: Display>(val: D) -> StyledContent<D> {
161
161
///
162
162
/// This does not always provide a good result.
163
163
pub fn available_color_count ( ) -> u16 {
164
- env:: var ( "TERM" )
165
- . map ( |x| if x. contains ( "256color" ) { 256 } else { 8 } )
166
- . unwrap_or ( 8 )
164
+ #[ cfg( windows) ]
165
+ {
166
+ // Check if we're running in a pseudo TTY, which supports true color.
167
+ // Fall back to env vars otherwise for other terminals on Windows.
168
+ if crate :: ansi_support:: supports_ansi ( ) {
169
+ return u16:: MAX ;
170
+ }
171
+ }
172
+
173
+ const DEFAULT : u16 = 8 ;
174
+ env:: var ( "COLORTERM" )
175
+ . or_else ( |_| env:: var ( "TERM" ) )
176
+ . map_or ( DEFAULT , |x| match x {
177
+ _ if x. contains ( "24bit" ) || x. contains ( "truecolor" ) => u16:: MAX ,
178
+ _ if x. contains ( "256" ) => 256 ,
179
+ _ => DEFAULT ,
180
+ } )
167
181
}
168
182
169
183
/// Forces colored output on or off globally, overriding NO_COLOR.
@@ -519,3 +533,89 @@ impl_display!(for ResetColor);
519
533
fn parse_next_u8 < ' a > ( iter : & mut impl Iterator < Item = & ' a str > ) -> Option < u8 > {
520
534
iter. next ( ) . and_then ( |s| s. parse ( ) . ok ( ) )
521
535
}
536
+
537
+ #[ cfg( test) ]
538
+ mod tests {
539
+ use super :: * ;
540
+
541
+ // On Windows many env var tests will fail so we need to conditionally check for ANSI support.
542
+ // This allows other terminals on Windows to still assert env var support.
543
+ macro_rules! skip_windows_ansi_supported {
544
+ ( ) => {
545
+ #[ cfg( windows) ]
546
+ {
547
+ if crate :: ansi_support:: supports_ansi( ) {
548
+ return ;
549
+ }
550
+ }
551
+ } ;
552
+ }
553
+
554
+ #[ cfg_attr( windows, test) ]
555
+ #[ cfg( windows) ]
556
+ fn windows_always_truecolor ( ) {
557
+ // This should always be true on supported Windows 10+,
558
+ // but downlevel Windows clients and other terminals may fail `cargo test` otherwise.
559
+ if crate :: ansi_support:: supports_ansi ( ) {
560
+ assert_eq ! ( u16 :: MAX , available_color_count( ) ) ;
561
+ } ;
562
+ }
563
+
564
+ #[ test]
565
+ fn colorterm_overrides_term ( ) {
566
+ skip_windows_ansi_supported ! ( ) ;
567
+ temp_env:: with_vars (
568
+ [
569
+ ( "COLORTERM" , Some ( "truecolor" ) ) ,
570
+ ( "TERM" , Some ( "xterm-256color" ) ) ,
571
+ ] ,
572
+ || {
573
+ assert_eq ! ( u16 :: MAX , available_color_count( ) ) ;
574
+ } ,
575
+ ) ;
576
+ }
577
+
578
+ #[ test]
579
+ fn term_24bits ( ) {
580
+ skip_windows_ansi_supported ! ( ) ;
581
+ temp_env:: with_vars (
582
+ [ ( "COLORTERM" , None ) , ( "TERM" , Some ( "xterm-24bits" ) ) ] ,
583
+ || {
584
+ assert_eq ! ( u16 :: MAX , available_color_count( ) ) ;
585
+ } ,
586
+ ) ;
587
+ }
588
+
589
+ #[ test]
590
+ fn term_256color ( ) {
591
+ skip_windows_ansi_supported ! ( ) ;
592
+ temp_env:: with_vars (
593
+ [ ( "COLORTERM" , None ) , ( "TERM" , Some ( "xterm-256color" ) ) ] ,
594
+ || {
595
+ assert_eq ! ( 256u16 , available_color_count( ) ) ;
596
+ } ,
597
+ ) ;
598
+ }
599
+
600
+ #[ test]
601
+ fn default_color_count ( ) {
602
+ skip_windows_ansi_supported ! ( ) ;
603
+ temp_env:: with_vars ( [ ( "COLORTERM" , None :: < & str > ) , ( "TERM" , None ) ] , || {
604
+ assert_eq ! ( 8 , available_color_count( ) ) ;
605
+ } ) ;
606
+ }
607
+
608
+ #[ test]
609
+ fn unsupported_term_colorterm_values ( ) {
610
+ skip_windows_ansi_supported ! ( ) ;
611
+ temp_env:: with_vars (
612
+ [
613
+ ( "COLORTERM" , Some ( "gibberish" ) ) ,
614
+ ( "TERM" , Some ( "gibberish" ) ) ,
615
+ ] ,
616
+ || {
617
+ assert_eq ! ( 8u16 , available_color_count( ) ) ;
618
+ } ,
619
+ ) ;
620
+ }
621
+ }
0 commit comments