##// END OF EJS Templates
Deprecate more complicated way of defining colors. (#14305)...
M Bussonnier -
r28606:5f4d6acd merge
parent child Browse files
Show More
@@ -1,210 +1,221 b''
1 """Tools for coloring text in ANSI terminals.
1 """Tools for coloring text in ANSI terminals.
2 """
2 """
3
3
4 #*****************************************************************************
4 #*****************************************************************************
5 # Copyright (C) 2002-2006 Fernando Perez. <fperez@colorado.edu>
5 # Copyright (C) 2002-2006 Fernando Perez. <fperez@colorado.edu>
6 #
6 #
7 # Distributed under the terms of the BSD License. The full license is in
7 # Distributed under the terms of the BSD License. The full license is in
8 # the file COPYING, distributed as part of this software.
8 # the file COPYING, distributed as part of this software.
9 #*****************************************************************************
9 #*****************************************************************************
10
10
11
11
12 import os
12 import os
13 import warnings
13
14
14 from IPython.utils.ipstruct import Struct
15 from IPython.utils.ipstruct import Struct
15
16
16 __all__ = ["TermColors", "InputTermColors", "ColorScheme", "ColorSchemeTable"]
17 __all__ = ["TermColors", "InputTermColors", "ColorScheme", "ColorSchemeTable"]
17
18
18 _sentinel = object()
19 _sentinel = object()
19
20
20 color_templates = (
21 color_templates = (
21 # Dark colors
22 # Dark colors
22 ("Black" , "0;30"),
23 ("Black" , "0;30"),
23 ("Red" , "0;31"),
24 ("Red" , "0;31"),
24 ("Green" , "0;32"),
25 ("Green" , "0;32"),
25 ("Brown" , "0;33"),
26 ("Brown" , "0;33"),
26 ("Blue" , "0;34"),
27 ("Blue" , "0;34"),
27 ("Purple" , "0;35"),
28 ("Purple" , "0;35"),
28 ("Cyan" , "0;36"),
29 ("Cyan" , "0;36"),
29 ("LightGray" , "0;37"),
30 ("LightGray" , "0;37"),
30 # Light colors
31 # Light colors
31 ("DarkGray" , "1;30"),
32 ("DarkGray" , "1;30"),
32 ("LightRed" , "1;31"),
33 ("LightRed" , "1;31"),
33 ("LightGreen" , "1;32"),
34 ("LightGreen" , "1;32"),
34 ("Yellow" , "1;33"),
35 ("Yellow" , "1;33"),
35 ("LightBlue" , "1;34"),
36 ("LightBlue" , "1;34"),
36 ("LightPurple" , "1;35"),
37 ("LightPurple" , "1;35"),
37 ("LightCyan" , "1;36"),
38 ("LightCyan" , "1;36"),
38 ("White" , "1;37"),
39 ("White" , "1;37"),
39 # Blinking colors. Probably should not be used in anything serious.
40 # Blinking colors. Probably should not be used in anything serious.
40 ("BlinkBlack" , "5;30"),
41 ("BlinkBlack" , "5;30"),
41 ("BlinkRed" , "5;31"),
42 ("BlinkRed" , "5;31"),
42 ("BlinkGreen" , "5;32"),
43 ("BlinkGreen" , "5;32"),
43 ("BlinkYellow" , "5;33"),
44 ("BlinkYellow" , "5;33"),
44 ("BlinkBlue" , "5;34"),
45 ("BlinkBlue" , "5;34"),
45 ("BlinkPurple" , "5;35"),
46 ("BlinkPurple" , "5;35"),
46 ("BlinkCyan" , "5;36"),
47 ("BlinkCyan" , "5;36"),
47 ("BlinkLightGray", "5;37"),
48 ("BlinkLightGray", "5;37"),
48 )
49 )
49
50
50 def make_color_table(in_class):
51 def make_color_table(in_class):
51 """Build a set of color attributes in a class.
52 """Build a set of color attributes in a class.
52
53
53 Helper function for building the :class:`TermColors` and
54 Helper function for building the :class:`TermColors` and
54 :class`InputTermColors`.
55 :class`InputTermColors`.
55 """
56 """
56 for name,value in color_templates:
57 for name,value in color_templates:
57 setattr(in_class,name,in_class._base % value)
58 setattr(in_class,name,in_class._base % value)
58
59
59 class TermColors:
60 class TermColors:
60 """Color escape sequences.
61 """Color escape sequences.
61
62
62 This class defines the escape sequences for all the standard (ANSI?)
63 This class defines the escape sequences for all the standard (ANSI?)
63 colors in terminals. Also defines a NoColor escape which is just the null
64 colors in terminals. Also defines a NoColor escape which is just the null
64 string, suitable for defining 'dummy' color schemes in terminals which get
65 string, suitable for defining 'dummy' color schemes in terminals which get
65 confused by color escapes.
66 confused by color escapes.
66
67
67 This class should be used as a mixin for building color schemes."""
68 This class should be used as a mixin for building color schemes."""
68
69
69 NoColor = '' # for color schemes in color-less terminals.
70 NoColor = '' # for color schemes in color-less terminals.
70 Normal = '\033[0m' # Reset normal coloring
71 Normal = '\033[0m' # Reset normal coloring
71 _base = '\033[%sm' # Template for all other colors
72 _base = '\033[%sm' # Template for all other colors
72
73
73 # Build the actual color table as a set of class attributes:
74 # Build the actual color table as a set of class attributes:
74 make_color_table(TermColors)
75 make_color_table(TermColors)
75
76
76 class InputTermColors:
77 class InputTermColors:
77 """Color escape sequences for input prompts.
78 """Color escape sequences for input prompts.
78
79
79 This class is similar to TermColors, but the escapes are wrapped in \\001
80 This class is similar to TermColors, but the escapes are wrapped in \\001
80 and \\002 so that readline can properly know the length of each line and
81 and \\002 so that readline can properly know the length of each line and
81 can wrap lines accordingly. Use this class for any colored text which
82 can wrap lines accordingly. Use this class for any colored text which
82 needs to be used in input prompts, such as in calls to raw_input().
83 needs to be used in input prompts, such as in calls to raw_input().
83
84
84 This class defines the escape sequences for all the standard (ANSI?)
85 This class defines the escape sequences for all the standard (ANSI?)
85 colors in terminals. Also defines a NoColor escape which is just the null
86 colors in terminals. Also defines a NoColor escape which is just the null
86 string, suitable for defining 'dummy' color schemes in terminals which get
87 string, suitable for defining 'dummy' color schemes in terminals which get
87 confused by color escapes.
88 confused by color escapes.
88
89
89 This class should be used as a mixin for building color schemes."""
90 This class should be used as a mixin for building color schemes."""
90
91
91 NoColor = '' # for color schemes in color-less terminals.
92 NoColor = '' # for color schemes in color-less terminals.
92
93
93 if os.name == 'nt' and os.environ.get('TERM','dumb') == 'emacs':
94 if os.name == 'nt' and os.environ.get('TERM','dumb') == 'emacs':
94 # (X)emacs on W32 gets confused with \001 and \002 so we remove them
95 # (X)emacs on W32 gets confused with \001 and \002 so we remove them
95 Normal = '\033[0m' # Reset normal coloring
96 Normal = '\033[0m' # Reset normal coloring
96 _base = '\033[%sm' # Template for all other colors
97 _base = '\033[%sm' # Template for all other colors
97 else:
98 else:
98 Normal = '\001\033[0m\002' # Reset normal coloring
99 Normal = '\001\033[0m\002' # Reset normal coloring
99 _base = '\001\033[%sm\002' # Template for all other colors
100 _base = '\001\033[%sm\002' # Template for all other colors
100
101
101 # Build the actual color table as a set of class attributes:
102 # Build the actual color table as a set of class attributes:
102 make_color_table(InputTermColors)
103 make_color_table(InputTermColors)
103
104
104 class NoColors:
105 class NoColors:
105 """This defines all the same names as the colour classes, but maps them to
106 """This defines all the same names as the colour classes, but maps them to
106 empty strings, so it can easily be substituted to turn off colours."""
107 empty strings, so it can easily be substituted to turn off colours."""
107 NoColor = ''
108 NoColor = ''
108 Normal = ''
109 Normal = ''
109
110
110 for name, value in color_templates:
111 for name, value in color_templates:
111 setattr(NoColors, name, '')
112 setattr(NoColors, name, '')
112
113
113 class ColorScheme:
114 class ColorScheme:
114 """Generic color scheme class. Just a name and a Struct."""
115 """Generic color scheme class. Just a name and a Struct."""
115
116
116 name: str
117 name: str
117 colors: Struct
118 colors: Struct
118
119
119 def __init__(self,__scheme_name_,colordict=None,**colormap):
120 def __init__(self, __scheme_name_, colordict=None, **colormap):
120 self.name = __scheme_name_
121 self.name = __scheme_name_
122 if colormap:
123 warnings.warn(
124 "Passing each colors as a kwarg to ColorScheme is "
125 "considered for deprecation. Please pass a "
126 "a single dict as second parameter. If you are using this"
127 "feature, please comment an subscribe to issue "
128 "https://github.com/ipython/ipython/issues/14304",
129 PendingDeprecationWarning,
130 stacklevel=2,
131 )
121 if colordict is None:
132 if colordict is None:
122 self.colors = Struct(**colormap)
133 self.colors = Struct(**colormap)
123 else:
134 else:
124 self.colors = Struct(colordict)
135 self.colors = Struct(colordict)
125
136
126 def copy(self,name=None):
137 def copy(self,name=None):
127 """Return a full copy of the object, optionally renaming it."""
138 """Return a full copy of the object, optionally renaming it."""
128 if name is None:
139 if name is None:
129 name = self.name
140 name = self.name
130 return ColorScheme(name, self.colors.dict())
141 return ColorScheme(name, self.colors.dict())
131
142
132 class ColorSchemeTable(dict):
143 class ColorSchemeTable(dict):
133 """General class to handle tables of color schemes.
144 """General class to handle tables of color schemes.
134
145
135 It's basically a dict of color schemes with a couple of shorthand
146 It's basically a dict of color schemes with a couple of shorthand
136 attributes and some convenient methods.
147 attributes and some convenient methods.
137
148
138 active_scheme_name -> obvious
149 active_scheme_name -> obvious
139 active_colors -> actual color table of the active scheme"""
150 active_colors -> actual color table of the active scheme"""
140
151
141 def __init__(self, scheme_list=None, default_scheme=''):
152 def __init__(self, scheme_list=None, default_scheme=''):
142 """Create a table of color schemes.
153 """Create a table of color schemes.
143
154
144 The table can be created empty and manually filled or it can be
155 The table can be created empty and manually filled or it can be
145 created with a list of valid color schemes AND the specification for
156 created with a list of valid color schemes AND the specification for
146 the default active scheme.
157 the default active scheme.
147 """
158 """
148
159
149 # create object attributes to be set later
160 # create object attributes to be set later
150 self.active_scheme_name = ''
161 self.active_scheme_name = ''
151 self.active_colors = None
162 self.active_colors = None
152
163
153 if scheme_list:
164 if scheme_list:
154 if default_scheme == '':
165 if default_scheme == '':
155 raise ValueError('you must specify the default color scheme')
166 raise ValueError('you must specify the default color scheme')
156 for scheme in scheme_list:
167 for scheme in scheme_list:
157 self.add_scheme(scheme)
168 self.add_scheme(scheme)
158 self.set_active_scheme(default_scheme)
169 self.set_active_scheme(default_scheme)
159
170
160 def copy(self):
171 def copy(self):
161 """Return full copy of object"""
172 """Return full copy of object"""
162 return ColorSchemeTable(self.values(),self.active_scheme_name)
173 return ColorSchemeTable(self.values(),self.active_scheme_name)
163
174
164 def __setitem__(self, key: str, value: ColorScheme):
175 def __setitem__(self, key: str, value: ColorScheme):
165 assert isinstance(key, str)
176 assert isinstance(key, str)
166 assert isinstance(value, ColorScheme)
177 assert isinstance(value, ColorScheme)
167 super().__setitem__(key, value)
178 super().__setitem__(key, value)
168
179
169 def add_scheme(self, new_scheme):
180 def add_scheme(self, new_scheme):
170 """Add a new color scheme to the table."""
181 """Add a new color scheme to the table."""
171 if not isinstance(new_scheme, ColorScheme):
182 if not isinstance(new_scheme, ColorScheme):
172 raise ValueError('ColorSchemeTable only accepts ColorScheme instances')
183 raise ValueError('ColorSchemeTable only accepts ColorScheme instances')
173 self[new_scheme.name] = new_scheme
184 self[new_scheme.name] = new_scheme
174
185
175 def set_active_scheme(self, scheme, case_sensitive=_sentinel):
186 def set_active_scheme(self, scheme, case_sensitive=_sentinel):
176 """Set the currently active scheme.
187 """Set the currently active scheme.
177
188
178 Names are by default compared in a case-insensitive way, but this can
189 Names are by default compared in a case-insensitive way, but this can
179 be changed by setting the parameter case_sensitive to true."""
190 be changed by setting the parameter case_sensitive to true."""
180
191
181 if case_sensitive is _sentinel:
192 if case_sensitive is _sentinel:
182 case_sensitive = False
193 case_sensitive = False
183 else:
194 else:
184 warnings.warn(
195 warnings.warn(
185 "set_active_scheme(case_sensitive=...) is Pending "
196 "set_active_scheme(case_sensitive=...) is Pending "
186 "deprecation. Please comment on "
197 "deprecation. Please comment on "
187 "https://github.com/ipython/ipython/issues/14306 "
198 "https://github.com/ipython/ipython/issues/14306 "
188 "to let the ipython maintainer that you are affected.",
199 "to let the ipython maintainer that you are affected.",
189 PendingDeprecationWarning,
200 PendingDeprecationWarning,
190 stacklevel=2,
201 stacklevel=2,
191 )
202 )
192
203
193 scheme_names = list(self.keys())
204 scheme_names = list(self.keys())
194 if case_sensitive:
205 if case_sensitive:
195 valid_schemes = scheme_names
206 valid_schemes = scheme_names
196 scheme_test = scheme
207 scheme_test = scheme
197 else:
208 else:
198 valid_schemes = [s.lower() for s in scheme_names]
209 valid_schemes = [s.lower() for s in scheme_names]
199 scheme_test = scheme.lower()
210 scheme_test = scheme.lower()
200 try:
211 try:
201 scheme_idx = valid_schemes.index(scheme_test)
212 scheme_idx = valid_schemes.index(scheme_test)
202 except ValueError as e:
213 except ValueError as e:
203 raise ValueError('Unrecognized color scheme: ' + scheme + \
214 raise ValueError('Unrecognized color scheme: ' + scheme + \
204 '\nValid schemes: '+str(scheme_names).replace("'', ",'')) from e
215 '\nValid schemes: '+str(scheme_names).replace("'', ",'')) from e
205 else:
216 else:
206 active = scheme_names[scheme_idx]
217 active = scheme_names[scheme_idx]
207 self.active_scheme_name = active
218 self.active_scheme_name = active
208 self.active_colors = self[active].colors
219 self.active_colors = self[active].colors
209 # Now allow using '' as an index for the current active scheme
220 # Now allow using '' as an index for the current active scheme
210 self[''] = self[active]
221 self[''] = self[active]
General Comments 0
You need to be logged in to leave comments. Login now