|
38
|
1 |
""" |
|
|
2 |
termcolors.py |
|
|
3 |
""" |
|
|
4 |
|
|
|
5 |
color_names = ('black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white') |
|
|
6 |
foreground = dict([(color_names[x], '3%s' % x) for x in range(8)]) |
|
|
7 |
background = dict([(color_names[x], '4%s' % x) for x in range(8)]) |
|
|
8 |
|
|
|
9 |
RESET = '0' |
|
|
10 |
opt_dict = {'bold': '1', 'underscore': '4', 'blink': '5', 'reverse': '7', 'conceal': '8'} |
|
|
11 |
|
|
|
12 |
def colorize(text='', opts=(), **kwargs): |
|
|
13 |
""" |
|
|
14 |
Returns your text, enclosed in ANSI graphics codes. |
|
|
15 |
|
|
|
16 |
Depends on the keyword arguments 'fg' and 'bg', and the contents of |
|
|
17 |
the opts tuple/list. |
|
|
18 |
|
|
|
19 |
Returns the RESET code if no parameters are given. |
|
|
20 |
|
|
|
21 |
Valid colors: |
|
|
22 |
'black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white' |
|
|
23 |
|
|
|
24 |
Valid options: |
|
|
25 |
'bold' |
|
|
26 |
'underscore' |
|
|
27 |
'blink' |
|
|
28 |
'reverse' |
|
|
29 |
'conceal' |
|
|
30 |
'noreset' - string will not be auto-terminated with the RESET code |
|
|
31 |
|
|
|
32 |
Examples: |
|
|
33 |
colorize('hello', fg='red', bg='blue', opts=('blink',)) |
|
|
34 |
colorize() |
|
|
35 |
colorize('goodbye', opts=('underscore',)) |
|
|
36 |
print colorize('first line', fg='red', opts=('noreset',)) |
|
|
37 |
print 'this should be red too' |
|
|
38 |
print colorize('and so should this') |
|
|
39 |
print 'this should not be red' |
|
|
40 |
""" |
|
|
41 |
code_list = [] |
|
|
42 |
if text == '' and len(opts) == 1 and opts[0] == 'reset': |
|
|
43 |
return '\x1b[%sm' % RESET |
|
|
44 |
for k, v in kwargs.iteritems(): |
|
|
45 |
if k == 'fg': |
|
|
46 |
code_list.append(foreground[v]) |
|
|
47 |
elif k == 'bg': |
|
|
48 |
code_list.append(background[v]) |
|
|
49 |
for o in opts: |
|
|
50 |
if o in opt_dict: |
|
|
51 |
code_list.append(opt_dict[o]) |
|
|
52 |
if 'noreset' not in opts: |
|
|
53 |
text = text + '\x1b[%sm' % RESET |
|
|
54 |
return ('\x1b[%sm' % ';'.join(code_list)) + text |
|
|
55 |
|
|
|
56 |
def make_style(opts=(), **kwargs): |
|
|
57 |
""" |
|
|
58 |
Returns a function with default parameters for colorize() |
|
|
59 |
|
|
|
60 |
Example: |
|
|
61 |
bold_red = make_style(opts=('bold',), fg='red') |
|
|
62 |
print bold_red('hello') |
|
|
63 |
KEYWORD = make_style(fg='yellow') |
|
|
64 |
COMMENT = make_style(fg='blue', opts=('bold',)) |
|
|
65 |
""" |
|
|
66 |
return lambda text: colorize(text, opts, **kwargs) |
|
|
67 |
|
|
|
68 |
NOCOLOR_PALETTE = 'nocolor' |
|
|
69 |
DARK_PALETTE = 'dark' |
|
|
70 |
LIGHT_PALETTE = 'light' |
|
|
71 |
|
|
|
72 |
PALETTES = { |
|
|
73 |
NOCOLOR_PALETTE: { |
|
|
74 |
'ERROR': {}, |
|
|
75 |
'NOTICE': {}, |
|
|
76 |
'SQL_FIELD': {}, |
|
|
77 |
'SQL_COLTYPE': {}, |
|
|
78 |
'SQL_KEYWORD': {}, |
|
|
79 |
'SQL_TABLE': {}, |
|
|
80 |
'HTTP_INFO': {}, |
|
|
81 |
'HTTP_SUCCESS': {}, |
|
|
82 |
'HTTP_REDIRECT': {}, |
|
|
83 |
'HTTP_NOT_MODIFIED': {}, |
|
|
84 |
'HTTP_BAD_REQUEST': {}, |
|
|
85 |
'HTTP_NOT_FOUND': {}, |
|
|
86 |
'HTTP_SERVER_ERROR': {}, |
|
|
87 |
}, |
|
|
88 |
DARK_PALETTE: { |
|
|
89 |
'ERROR': { 'fg': 'red', 'opts': ('bold',) }, |
|
|
90 |
'NOTICE': { 'fg': 'red' }, |
|
|
91 |
'SQL_FIELD': { 'fg': 'green', 'opts': ('bold',) }, |
|
|
92 |
'SQL_COLTYPE': { 'fg': 'green' }, |
|
|
93 |
'SQL_KEYWORD': { 'fg': 'yellow' }, |
|
|
94 |
'SQL_TABLE': { 'opts': ('bold',) }, |
|
|
95 |
'HTTP_INFO': { 'opts': ('bold',) }, |
|
|
96 |
'HTTP_SUCCESS': { }, |
|
|
97 |
'HTTP_REDIRECT': { 'fg': 'green' }, |
|
|
98 |
'HTTP_NOT_MODIFIED': { 'fg': 'cyan' }, |
|
|
99 |
'HTTP_BAD_REQUEST': { 'fg': 'red', 'opts': ('bold',) }, |
|
|
100 |
'HTTP_NOT_FOUND': { 'fg': 'yellow' }, |
|
|
101 |
'HTTP_SERVER_ERROR': { 'fg': 'magenta', 'opts': ('bold',) }, |
|
|
102 |
}, |
|
|
103 |
LIGHT_PALETTE: { |
|
|
104 |
'ERROR': { 'fg': 'red', 'opts': ('bold',) }, |
|
|
105 |
'NOTICE': { 'fg': 'red' }, |
|
|
106 |
'SQL_FIELD': { 'fg': 'green', 'opts': ('bold',) }, |
|
|
107 |
'SQL_COLTYPE': { 'fg': 'green' }, |
|
|
108 |
'SQL_KEYWORD': { 'fg': 'blue' }, |
|
|
109 |
'SQL_TABLE': { 'opts': ('bold',) }, |
|
|
110 |
'HTTP_INFO': { 'opts': ('bold',) }, |
|
|
111 |
'HTTP_SUCCESS': { }, |
|
|
112 |
'HTTP_REDIRECT': { 'fg': 'green', 'opts': ('bold',) }, |
|
|
113 |
'HTTP_NOT_MODIFIED': { 'fg': 'green' }, |
|
|
114 |
'HTTP_BAD_REQUEST': { 'fg': 'red', 'opts': ('bold',) }, |
|
|
115 |
'HTTP_NOT_FOUND': { 'fg': 'red' }, |
|
|
116 |
'HTTP_SERVER_ERROR': { 'fg': 'magenta', 'opts': ('bold',) }, |
|
|
117 |
} |
|
|
118 |
} |
|
|
119 |
DEFAULT_PALETTE = DARK_PALETTE |
|
|
120 |
|
|
|
121 |
def parse_color_setting(config_string): |
|
|
122 |
"""Parse a DJANGO_COLORS environment variable to produce the system palette |
|
|
123 |
|
|
|
124 |
The general form of a pallete definition is: |
|
|
125 |
|
|
|
126 |
"palette;role=fg;role=fg/bg;role=fg,option,option;role=fg/bg,option,option" |
|
|
127 |
|
|
|
128 |
where: |
|
|
129 |
palette is a named palette; one of 'light', 'dark', or 'nocolor'. |
|
|
130 |
role is a named style used by Django |
|
|
131 |
fg is a background color. |
|
|
132 |
bg is a background color. |
|
|
133 |
option is a display options. |
|
|
134 |
|
|
|
135 |
Specifying a named palette is the same as manually specifying the individual |
|
|
136 |
definitions for each role. Any individual definitions following the pallete |
|
|
137 |
definition will augment the base palette definition. |
|
|
138 |
|
|
|
139 |
Valid roles: |
|
|
140 |
'error', 'notice', 'sql_field', 'sql_coltype', 'sql_keyword', 'sql_table', |
|
|
141 |
'http_info', 'http_success', 'http_redirect', 'http_bad_request', |
|
|
142 |
'http_not_found', 'http_server_error' |
|
|
143 |
|
|
|
144 |
Valid colors: |
|
|
145 |
'black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white' |
|
|
146 |
|
|
|
147 |
Valid options: |
|
|
148 |
'bold', 'underscore', 'blink', 'reverse', 'conceal' |
|
|
149 |
|
|
|
150 |
""" |
|
|
151 |
if not config_string: |
|
|
152 |
return PALETTES[DEFAULT_PALETTE] |
|
|
153 |
|
|
|
154 |
# Split the color configuration into parts |
|
|
155 |
parts = config_string.lower().split(';') |
|
|
156 |
palette = PALETTES[NOCOLOR_PALETTE].copy() |
|
|
157 |
for part in parts: |
|
|
158 |
if part in PALETTES: |
|
|
159 |
# A default palette has been specified |
|
|
160 |
palette.update(PALETTES[part]) |
|
|
161 |
elif '=' in part: |
|
|
162 |
# Process a palette defining string |
|
|
163 |
definition = {} |
|
|
164 |
|
|
|
165 |
# Break the definition into the role, |
|
|
166 |
# plus the list of specific instructions. |
|
|
167 |
# The role must be in upper case |
|
|
168 |
role, instructions = part.split('=') |
|
|
169 |
role = role.upper() |
|
|
170 |
|
|
|
171 |
styles = instructions.split(',') |
|
|
172 |
styles.reverse() |
|
|
173 |
|
|
|
174 |
# The first instruction can contain a slash |
|
|
175 |
# to break apart fg/bg. |
|
|
176 |
colors = styles.pop().split('/') |
|
|
177 |
colors.reverse() |
|
|
178 |
fg = colors.pop() |
|
|
179 |
if fg in color_names: |
|
|
180 |
definition['fg'] = fg |
|
|
181 |
if colors and colors[-1] in color_names: |
|
|
182 |
definition['bg'] = colors[-1] |
|
|
183 |
|
|
|
184 |
# All remaining instructions are options |
|
|
185 |
opts = tuple(s for s in styles if s in opt_dict.keys()) |
|
|
186 |
if opts: |
|
|
187 |
definition['opts'] = opts |
|
|
188 |
|
|
|
189 |
# The nocolor palette has all available roles. |
|
|
190 |
# Use that palette as the basis for determining |
|
|
191 |
# if the role is valid. |
|
|
192 |
if role in PALETTES[NOCOLOR_PALETTE] and definition: |
|
|
193 |
palette[role] = definition |
|
|
194 |
|
|
|
195 |
# If there are no colors specified, return the empty palette. |
|
|
196 |
if palette == PALETTES[NOCOLOR_PALETTE]: |
|
|
197 |
return None |
|
|
198 |
return palette |