blob: b27992866a0b7eeed03a42e231c46fbde41ae507 [file] [log] [blame]
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -07001#
2# Copyright (C) 2008 The Android Open Source Project
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15
16import os
17import sys
18
19import pager
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070020
21COLORS = {None :-1,
22 'normal' :-1,
23 'black' : 0,
24 'red' : 1,
25 'green' : 2,
26 'yellow' : 3,
27 'blue' : 4,
28 'magenta': 5,
29 'cyan' : 6,
30 'white' : 7}
31
32ATTRS = {None :-1,
33 'bold' : 1,
34 'dim' : 2,
35 'ul' : 4,
36 'blink' : 5,
37 'reverse': 7}
38
David Pursehouse1d947b32012-10-25 12:23:11 +090039RESET = "\033[m" # pylint: disable=W1401
40 # backslash is not anomalous
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070041
David Pursehouse8a68ff92012-09-24 12:15:13 +090042def is_color(s):
David Pursehousec1b86a22012-11-14 11:36:51 +090043 return s in COLORS
David Pursehouse8a68ff92012-09-24 12:15:13 +090044
45def is_attr(s):
David Pursehousec1b86a22012-11-14 11:36:51 +090046 return s in ATTRS
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070047
48def _Color(fg = None, bg = None, attr = None):
David Pursehousec1b86a22012-11-14 11:36:51 +090049 fg = COLORS[fg]
50 bg = COLORS[bg]
51 attr = ATTRS[attr]
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070052
David Pursehousec1b86a22012-11-14 11:36:51 +090053 if attr >= 0 or fg >= 0 or bg >= 0:
54 need_sep = False
55 code = "\033[" #pylint: disable=W1401
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070056
David Pursehousec1b86a22012-11-14 11:36:51 +090057 if attr >= 0:
58 code += chr(ord('0') + attr)
59 need_sep = True
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070060
David Pursehousec1b86a22012-11-14 11:36:51 +090061 if fg >= 0:
62 if need_sep:
63 code += ';'
64 need_sep = True
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070065
David Pursehousec1b86a22012-11-14 11:36:51 +090066 if fg < 8:
67 code += '3%c' % (ord('0') + fg)
68 else:
69 code += '38;5;%d' % fg
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070070
David Pursehousec1b86a22012-11-14 11:36:51 +090071 if bg >= 0:
72 if need_sep:
73 code += ';'
74 need_sep = True
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070075
David Pursehousec1b86a22012-11-14 11:36:51 +090076 if bg < 8:
77 code += '4%c' % (ord('0') + bg)
78 else:
79 code += '48;5;%d' % bg
80 code += 'm'
81 else:
82 code = ''
83 return code
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070084
85
Mike Frysinger902665b2014-12-22 15:17:59 -050086DEFAULT = None
87
88def SetDefaultColoring(state):
89 """Set coloring behavior to |state|.
90
91 This is useful for overriding config options via the command line.
92 """
93 if state is None:
94 # Leave it alone -- return quick!
95 return
96
97 global DEFAULT
98 state = state.lower()
99 if state in ('auto',):
100 DEFAULT = state
101 elif state in ('always', 'yes', 'true', True):
102 DEFAULT = 'always'
103 elif state in ('never', 'no', 'false', False):
104 DEFAULT = 'never'
105
106
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700107class Coloring(object):
David Pursehouse8a68ff92012-09-24 12:15:13 +0900108 def __init__(self, config, section_type):
109 self._section = 'color.%s' % section_type
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700110 self._config = config
111 self._out = sys.stdout
112
Mike Frysinger902665b2014-12-22 15:17:59 -0500113 on = DEFAULT
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700114 if on is None:
Mike Frysinger902665b2014-12-22 15:17:59 -0500115 on = self._config.GetString(self._section)
116 if on is None:
117 on = self._config.GetString('color.ui')
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700118
119 if on == 'auto':
120 if pager.active or os.isatty(1):
121 self._on = True
122 else:
123 self._on = False
124 elif on in ('true', 'always'):
125 self._on = True
126 else:
127 self._on = False
128
Shawn O. Pearce350cde42009-04-16 11:21:18 -0700129 def redirect(self, out):
130 self._out = out
131
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700132 @property
133 def is_on(self):
134 return self._on
135
136 def write(self, fmt, *args):
137 self._out.write(fmt % args)
138
Shawn O. Pearcedb45da12009-04-18 13:49:13 -0700139 def flush(self):
140 self._out.flush()
141
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700142 def nl(self):
143 self._out.write('\n')
144
145 def printer(self, opt=None, fg=None, bg=None, attr=None):
146 s = self
147 c = self.colorer(opt, fg, bg, attr)
148 def f(fmt, *args):
149 s._out.write(c(fmt, *args))
150 return f
151
Olof Johanssonb7541502013-02-26 07:36:03 +0100152 def nofmt_printer(self, opt=None, fg=None, bg=None, attr=None):
153 s = self
154 c = self.nofmt_colorer(opt, fg, bg, attr)
155 def f(fmt):
156 s._out.write(c(fmt))
157 return f
158
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700159 def colorer(self, opt=None, fg=None, bg=None, attr=None):
160 if self._on:
161 c = self._parse(opt, fg, bg, attr)
162 def f(fmt, *args):
David Pursehouse8a68ff92012-09-24 12:15:13 +0900163 output = fmt % args
164 return ''.join([c, output, RESET])
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700165 return f
166 else:
167 def f(fmt, *args):
168 return fmt % args
169 return f
170
Olof Johanssonb7541502013-02-26 07:36:03 +0100171 def nofmt_colorer(self, opt=None, fg=None, bg=None, attr=None):
172 if self._on:
173 c = self._parse(opt, fg, bg, attr)
174 def f(fmt):
175 return ''.join([c, fmt, RESET])
176 return f
177 else:
178 def f(fmt):
179 return fmt
180 return f
181
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700182 def _parse(self, opt, fg, bg, attr):
183 if not opt:
184 return _Color(fg, bg, attr)
185
186 v = self._config.GetString('%s.%s' % (self._section, opt))
187 if v is None:
188 return _Color(fg, bg, attr)
189
Shawn O. Pearcea8e98a62009-02-02 16:17:02 -0800190 v = v.strip().lower()
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700191 if v == "reset":
192 return RESET
193 elif v == '':
194 return _Color(fg, bg, attr)
195
196 have_fg = False
197 for a in v.split(' '):
198 if is_color(a):
David Pursehouse8a68ff92012-09-24 12:15:13 +0900199 if have_fg:
200 bg = a
201 else:
202 fg = a
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700203 elif is_attr(a):
204 attr = a
205
206 return _Color(fg, bg, attr)