##// END OF EJS Templates
Cleaner version of color table by P. Wang.
Fernando Perez -
Show More
@@ -1,179 +1,180 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Tools for coloring text in ANSI terminals.
2 """Tools for coloring text in ANSI terminals.
3
3
4 $Id: ColorANSI.py 2167 2007-03-21 06:57:50Z fperez $"""
4 $Id: ColorANSI.py 2167 2007-03-21 06:57:50Z fperez $"""
5
5
6 #*****************************************************************************
6 #*****************************************************************************
7 # Copyright (C) 2002-2006 Fernando Perez. <fperez@colorado.edu>
7 # Copyright (C) 2002-2006 Fernando Perez. <fperez@colorado.edu>
8 #
8 #
9 # Distributed under the terms of the BSD License. The full license is in
9 # Distributed under the terms of the BSD License. The full license is in
10 # the file COPYING, distributed as part of this software.
10 # the file COPYING, distributed as part of this software.
11 #*****************************************************************************
11 #*****************************************************************************
12
12
13 from IPython import Release
13 from IPython import Release
14 __author__ = '%s <%s>' % Release.authors['Fernando']
14 __author__ = '%s <%s>' % Release.authors['Fernando']
15 __license__ = Release.license
15 __license__ = Release.license
16
16
17 __all__ = ['TermColors','InputTermColors','ColorScheme','ColorSchemeTable']
17 __all__ = ['TermColors','InputTermColors','ColorScheme','ColorSchemeTable']
18
18
19 import os
19 import os
20
20
21 from IPython.ipstruct import Struct
21 from IPython.ipstruct import Struct
22
22
23 def make_color_table(in_class):
23 def make_color_table(in_class):
24 """Build a set of color attributes in a class.
24 """Build a set of color attributes in a class.
25
25
26 Helper function for building the *TermColors classes."""
26 Helper function for building the *TermColors classes."""
27
27
28 color_templates = (
28 color_templates = (
29 # Dark colors
29 ("Black" , "0;30"),
30 ("Black" , "0;30"),
30 ("Red" , "0;31"),
31 ("Red" , "0;31"),
31 ("Green" , "0;32"),
32 ("Green" , "0;32"),
32 ("Brown" , "0;33"),
33 ("Brown" , "0;33"),
33 ("Blue" , "0;34"),
34 ("Blue" , "0;34"),
34 ("Purple" , "0;35"),
35 ("Purple" , "0;35"),
35 ("Cyan" , "0;36"),
36 ("Cyan" , "0;36"),
36 ("LightGray" , "0;37"),
37 ("LightGray" , "0;37"),
38 # Light colors
37 ("DarkGray" , "1;30"),
39 ("DarkGray" , "1;30"),
38 ("LightRed" , "1;31"),
40 ("LightRed" , "1;31"),
39 ("LightGreen" , "1;32"),
41 ("LightGreen" , "1;32"),
40 ("Yellow" , "1;33"),
42 ("Yellow" , "1;33"),
41 ("LightBlue" , "1;34"),
43 ("LightBlue" , "1;34"),
42 ("LightPurple" , "1;35"),
44 ("LightPurple" , "1;35"),
43 ("LightCyan" , "1;36"),
45 ("LightCyan" , "1;36"),
44 ("White" , "1;37"), )
46 ("White" , "1;37"),
45
47 # Blinking colors. Probably should not be used in anything serious.
46 for name,value in color_templates:
48 ("BlinkBlack" , "5;30"),
47 setattr(in_class,name,in_class._base % value)
49 ("BlinkRed" , "5;31"),
48
50 ("BlinkGreen" , "5;32"),
49 # Automatically add Blink versions of the above colors. This
51 ("BlinkYellow" , "5;33"),
50 # just involves setting the attribute field (before the first
52 ("BlinkBlue" , "5;34"),
51 # semicolon) to '5'.
53 ("BlinkPurple" , "5;35"),
52 # Note: this is a little easter egg contributed by Peter Wang from
54 ("BlinkCyan" , "5;36"),
53 # Enthought at the Scipy2008 sprint :)
55 ("BlinkLightGray", "5;37"),
54 value = '5'+value[1:]
56 )
55 setattr(in_class,"Blink"+name,in_class._base % value)
56
57
57
58
58 class TermColors:
59 class TermColors:
59 """Color escape sequences.
60 """Color escape sequences.
60
61
61 This class defines the escape sequences for all the standard (ANSI?)
62 This class defines the escape sequences for all the standard (ANSI?)
62 colors in terminals. Also defines a NoColor escape which is just the null
63 colors in terminals. Also defines a NoColor escape which is just the null
63 string, suitable for defining 'dummy' color schemes in terminals which get
64 string, suitable for defining 'dummy' color schemes in terminals which get
64 confused by color escapes.
65 confused by color escapes.
65
66
66 This class should be used as a mixin for building color schemes."""
67 This class should be used as a mixin for building color schemes."""
67
68
68 NoColor = '' # for color schemes in color-less terminals.
69 NoColor = '' # for color schemes in color-less terminals.
69 Normal = '\033[0m' # Reset normal coloring
70 Normal = '\033[0m' # Reset normal coloring
70 _base = '\033[%sm' # Template for all other colors
71 _base = '\033[%sm' # Template for all other colors
71
72
72 # Build the actual color table as a set of class attributes:
73 # Build the actual color table as a set of class attributes:
73 make_color_table(TermColors)
74 make_color_table(TermColors)
74
75
75 class InputTermColors:
76 class InputTermColors:
76 """Color escape sequences for input prompts.
77 """Color escape sequences for input prompts.
77
78
78 This class is similar to TermColors, but the escapes are wrapped in \001
79 This class is similar to TermColors, but the escapes are wrapped in \001
79 and \002 so that readline can properly know the length of each line and
80 and \002 so that readline can properly know the length of each line and
80 can wrap lines accordingly. Use this class for any colored text which
81 can wrap lines accordingly. Use this class for any colored text which
81 needs to be used in input prompts, such as in calls to raw_input().
82 needs to be used in input prompts, such as in calls to raw_input().
82
83
83 This class defines the escape sequences for all the standard (ANSI?)
84 This class defines the escape sequences for all the standard (ANSI?)
84 colors in terminals. Also defines a NoColor escape which is just the null
85 colors in terminals. Also defines a NoColor escape which is just the null
85 string, suitable for defining 'dummy' color schemes in terminals which get
86 string, suitable for defining 'dummy' color schemes in terminals which get
86 confused by color escapes.
87 confused by color escapes.
87
88
88 This class should be used as a mixin for building color schemes."""
89 This class should be used as a mixin for building color schemes."""
89
90
90 NoColor = '' # for color schemes in color-less terminals.
91 NoColor = '' # for color schemes in color-less terminals.
91
92
92 if os.name == 'nt' and os.environ.get('TERM','dumb') == 'emacs':
93 if os.name == 'nt' and os.environ.get('TERM','dumb') == 'emacs':
93 # (X)emacs on W32 gets confused with \001 and \002 so we remove them
94 # (X)emacs on W32 gets confused with \001 and \002 so we remove them
94 Normal = '\033[0m' # Reset normal coloring
95 Normal = '\033[0m' # Reset normal coloring
95 _base = '\033[%sm' # Template for all other colors
96 _base = '\033[%sm' # Template for all other colors
96 else:
97 else:
97 Normal = '\001\033[0m\002' # Reset normal coloring
98 Normal = '\001\033[0m\002' # Reset normal coloring
98 _base = '\001\033[%sm\002' # Template for all other colors
99 _base = '\001\033[%sm\002' # Template for all other colors
99
100
100 # Build the actual color table as a set of class attributes:
101 # Build the actual color table as a set of class attributes:
101 make_color_table(InputTermColors)
102 make_color_table(InputTermColors)
102
103
103 class ColorScheme:
104 class ColorScheme:
104 """Generic color scheme class. Just a name and a Struct."""
105 """Generic color scheme class. Just a name and a Struct."""
105 def __init__(self,__scheme_name_,colordict=None,**colormap):
106 def __init__(self,__scheme_name_,colordict=None,**colormap):
106 self.name = __scheme_name_
107 self.name = __scheme_name_
107 if colordict is None:
108 if colordict is None:
108 self.colors = Struct(**colormap)
109 self.colors = Struct(**colormap)
109 else:
110 else:
110 self.colors = Struct(colordict)
111 self.colors = Struct(colordict)
111
112
112 def copy(self,name=None):
113 def copy(self,name=None):
113 """Return a full copy of the object, optionally renaming it."""
114 """Return a full copy of the object, optionally renaming it."""
114 if name is None:
115 if name is None:
115 name = self.name
116 name = self.name
116 return ColorScheme(name,self.colors.__dict__)
117 return ColorScheme(name,self.colors.__dict__)
117
118
118 class ColorSchemeTable(dict):
119 class ColorSchemeTable(dict):
119 """General class to handle tables of color schemes.
120 """General class to handle tables of color schemes.
120
121
121 It's basically a dict of color schemes with a couple of shorthand
122 It's basically a dict of color schemes with a couple of shorthand
122 attributes and some convenient methods.
123 attributes and some convenient methods.
123
124
124 active_scheme_name -> obvious
125 active_scheme_name -> obvious
125 active_colors -> actual color table of the active scheme"""
126 active_colors -> actual color table of the active scheme"""
126
127
127 def __init__(self,scheme_list=None,default_scheme=''):
128 def __init__(self,scheme_list=None,default_scheme=''):
128 """Create a table of color schemes.
129 """Create a table of color schemes.
129
130
130 The table can be created empty and manually filled or it can be
131 The table can be created empty and manually filled or it can be
131 created with a list of valid color schemes AND the specification for
132 created with a list of valid color schemes AND the specification for
132 the default active scheme.
133 the default active scheme.
133 """
134 """
134
135
135 # create object attributes to be set later
136 # create object attributes to be set later
136 self.active_scheme_name = ''
137 self.active_scheme_name = ''
137 self.active_colors = None
138 self.active_colors = None
138
139
139 if scheme_list:
140 if scheme_list:
140 if default_scheme == '':
141 if default_scheme == '':
141 raise ValueError,'you must specify the default color scheme'
142 raise ValueError,'you must specify the default color scheme'
142 for scheme in scheme_list:
143 for scheme in scheme_list:
143 self.add_scheme(scheme)
144 self.add_scheme(scheme)
144 self.set_active_scheme(default_scheme)
145 self.set_active_scheme(default_scheme)
145
146
146 def copy(self):
147 def copy(self):
147 """Return full copy of object"""
148 """Return full copy of object"""
148 return ColorSchemeTable(self.values(),self.active_scheme_name)
149 return ColorSchemeTable(self.values(),self.active_scheme_name)
149
150
150 def add_scheme(self,new_scheme):
151 def add_scheme(self,new_scheme):
151 """Add a new color scheme to the table."""
152 """Add a new color scheme to the table."""
152 if not isinstance(new_scheme,ColorScheme):
153 if not isinstance(new_scheme,ColorScheme):
153 raise ValueError,'ColorSchemeTable only accepts ColorScheme instances'
154 raise ValueError,'ColorSchemeTable only accepts ColorScheme instances'
154 self[new_scheme.name] = new_scheme
155 self[new_scheme.name] = new_scheme
155
156
156 def set_active_scheme(self,scheme,case_sensitive=0):
157 def set_active_scheme(self,scheme,case_sensitive=0):
157 """Set the currently active scheme.
158 """Set the currently active scheme.
158
159
159 Names are by default compared in a case-insensitive way, but this can
160 Names are by default compared in a case-insensitive way, but this can
160 be changed by setting the parameter case_sensitive to true."""
161 be changed by setting the parameter case_sensitive to true."""
161
162
162 scheme_names = self.keys()
163 scheme_names = self.keys()
163 if case_sensitive:
164 if case_sensitive:
164 valid_schemes = scheme_names
165 valid_schemes = scheme_names
165 scheme_test = scheme
166 scheme_test = scheme
166 else:
167 else:
167 valid_schemes = [s.lower() for s in scheme_names]
168 valid_schemes = [s.lower() for s in scheme_names]
168 scheme_test = scheme.lower()
169 scheme_test = scheme.lower()
169 try:
170 try:
170 scheme_idx = valid_schemes.index(scheme_test)
171 scheme_idx = valid_schemes.index(scheme_test)
171 except ValueError:
172 except ValueError:
172 raise ValueError,'Unrecognized color scheme: ' + scheme + \
173 raise ValueError,'Unrecognized color scheme: ' + scheme + \
173 '\nValid schemes: '+str(scheme_names).replace("'', ",'')
174 '\nValid schemes: '+str(scheme_names).replace("'', ",'')
174 else:
175 else:
175 active = scheme_names[scheme_idx]
176 active = scheme_names[scheme_idx]
176 self.active_scheme_name = active
177 self.active_scheme_name = active
177 self.active_colors = self[active].colors
178 self.active_colors = self[active].colors
178 # Now allow using '' as an index for the current active scheme
179 # Now allow using '' as an index for the current active scheme
179 self[''] = self[active]
180 self[''] = self[active]
General Comments 0
You need to be logged in to leave comments. Login now