11"""
22Utility functions for handling terminal colors
33"""
4- import colorsys
54import os
6- from typing import Iterable , List , Mapping , NamedTuple , Tuple
5+ from typing import Iterable , List , Mapping , NamedTuple , Tuple , no_type_check
6+
7+ import colorama
78
89from .consts import ANSI_COLORS , ANSI_RGB
910
@@ -17,6 +18,15 @@ class Style(NamedTuple):
1718_Hsv = Tuple [float , float , float ]
1819
1920
21+ def support_truecolor () -> bool :
22+ return os .name != "nt" or (
23+ os .getenv ("ANSICON" ) is not None
24+ or os .getenv ("WT_SESSION" ) is not None
25+ or "ON" == os .getenv ("ConEmuANSI" )
26+ or "xterm" == os .getenv ("Term" )
27+ )
28+
29+
2030def hex_to_rgb (hex_string : str ) -> _Rgb :
2131 """Return a tuple of red, green and blue components for the color
2232 given as #rrggbb.
@@ -33,12 +43,56 @@ def rgb_to_hex(rgb: _Rgb) -> str:
3343 return "#" + "" .join ("%02x" % c for c in rgb )
3444
3545
46+ @no_type_check
3647def rgb_to_hsv (rgb : _Rgb ) -> _Hsv :
37- return colorsys .rgb_to_hsv (* rgb )
48+ r , g , b = rgb
49+ r /= 255
50+ g /= 255
51+ b /= 255
52+
53+ max_value = max (r , g , b )
54+ min_value = min (r , g , b )
55+ diff = max_value - min_value
56+
57+ h , s , v = 0 , diff / max_value if max_value > 0 else 0 , max_value
58+
59+ if max_value == min_value :
60+ h = 0
61+ elif max_value == r :
62+ h = 60 * (g - b ) / diff
63+ if g < b :
64+ h += 360
65+ elif max_value == g :
66+ h = 60 * (b - r ) / diff + 120
67+ else :
68+ h = 60 * (r - g ) / diff + 240
69+
70+ return h , (s * 100 ), (v * 100 )
3871
3972
4073def hsv_to_rgb (hsv : _Hsv ) -> _Rgb :
41- return tuple (int (c ) for c in colorsys .hsv_to_rgb (* hsv )) # type: ignore
74+ h , s , v = hsv
75+ h /= 60
76+ s /= 100
77+ v /= 100
78+ hi = int (h ) % 6
79+
80+ f = h - int (h )
81+ p = 255 * v * (1 - s )
82+ q = 255 * v * (1 - (s * f ))
83+ t = 255 * v * (1 - (s * (1 - f )))
84+ v *= 255
85+
86+ result = {
87+ 0 : (v , t , p ),
88+ 1 : (q , v , p ),
89+ 2 : (p , v , t ),
90+ 3 : (p , q , v ),
91+ 4 : (t , p , v ),
92+ 5 : (v , p , q ),
93+ }[hi ]
94+ r , g , b = result
95+ return int (r ), int (g ), int (b )
4296
4397
4498def _color_distance (left : _Hsv , right : _Hsv ) -> float :
@@ -147,10 +201,11 @@ def rgb_style(self, color: _Rgb, background: bool) -> Style:
147201 return Style ("\x1b [{};2;{};{};{}m" .format (open_bit , r , g , b ), close )
148202
149203
150- if (os .getenv ("DISABLE_TRUECOLOR" ) or os . name == "nt" ) and not os .getenv (
204+ if (os .getenv ("DISABLE_TRUECOLOR" ) or not support_truecolor () ) and not os .getenv (
151205 "ENABLE_TRUECOLOR"
152206):
153207 # Disable truecolor for windows
154208 pen = AnsiPen ()
209+ colorama .init ()
155210else :
156211 pen = TrueColorPen ()
0 commit comments