blob: 0218aab80f729e906ae2238284cdf4ae4e4a297b [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
Anthony Kingbdf7ed22015-03-28 21:10:17 +000021COLORS = {None: -1,
22 'normal': -1,
23 'black': 0,
24 'red': 1,
25 'green': 2,
26 'yellow': 3,
27 'blue': 4,
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070028 'magenta': 5,
Anthony Kingbdf7ed22015-03-28 21:10:17 +000029 'cyan': 6,
30 'white': 7}
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070031
Anthony Kingbdf7ed22015-03-28 21:10:17 +000032ATTRS = {None: -1,
33 'bold': 1,
34 'dim': 2,
35 'ul': 4,
36 'blink': 5,
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070037 'reverse': 7}
38
Anthony Kingbdf7ed22015-03-28 21:10:17 +000039RESET = "\033[m"
40
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
Anthony Kingbdf7ed22015-03-28 21:10:17 +000045
David Pursehouse8a68ff92012-09-24 12:15:13 +090046def is_attr(s):
David Pursehousec1b86a22012-11-14 11:36:51 +090047 return s in ATTRS
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070048
Anthony Kingbdf7ed22015-03-28 21:10:17 +000049
50def _Color(fg=None, bg=None, attr=None):
David Pursehousec1b86a22012-11-14 11:36:51 +090051 fg = COLORS[fg]
52 bg = COLORS[bg]
53 attr = ATTRS[attr]
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070054
David Pursehousec1b86a22012-11-14 11:36:51 +090055 if attr >= 0 or fg >= 0 or bg >= 0:
56 need_sep = False
Anthony Kingbdf7ed22015-03-28 21:10:17 +000057 code = "\033["
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070058
David Pursehousec1b86a22012-11-14 11:36:51 +090059 if attr >= 0:
60 code += chr(ord('0') + attr)
61 need_sep = True
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070062
David Pursehousec1b86a22012-11-14 11:36:51 +090063 if fg >= 0:
64 if need_sep:
65 code += ';'
66 need_sep = True
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070067
David Pursehousec1b86a22012-11-14 11:36:51 +090068 if fg < 8:
69 code += '3%c' % (ord('0') + fg)
70 else:
71 code += '38;5;%d' % fg
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070072
David Pursehousec1b86a22012-11-14 11:36:51 +090073 if bg >= 0:
74 if need_sep:
75 code += ';'
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070076
David Pursehousec1b86a22012-11-14 11:36:51 +090077 if bg < 8:
78 code += '4%c' % (ord('0') + bg)
79 else:
80 code += '48;5;%d' % bg
81 code += 'm'
82 else:
83 code = ''
84 return code
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070085
Mike Frysinger902665b2014-12-22 15:17:59 -050086DEFAULT = None
87
Anthony Kingbdf7ed22015-03-28 21:10:17 +000088
Mike Frysinger902665b2014-12-22 15:17:59 -050089def SetDefaultColoring(state):
90 """Set coloring behavior to |state|.
91
92 This is useful for overriding config options via the command line.
93 """
94 if state is None:
95 # Leave it alone -- return quick!
96 return
97
98 global DEFAULT
99 state = state.lower()
100 if state in ('auto',):
101 DEFAULT = state
102 elif state in ('always', 'yes', 'true', True):
103 DEFAULT = 'always'
104 elif state in ('never', 'no', 'false', False):
105 DEFAULT = 'never'
106
107
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700108class Coloring(object):
David Pursehouse8a68ff92012-09-24 12:15:13 +0900109 def __init__(self, config, section_type):
110 self._section = 'color.%s' % section_type
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700111 self._config = config
112 self._out = sys.stdout
113
Mike Frysinger902665b2014-12-22 15:17:59 -0500114 on = DEFAULT
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700115 if on is None:
Mike Frysinger902665b2014-12-22 15:17:59 -0500116 on = self._config.GetString(self._section)
117 if on is None:
118 on = self._config.GetString('color.ui')
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700119
120 if on == 'auto':
121 if pager.active or os.isatty(1):
122 self._on = True
123 else:
124 self._on = False
125 elif on in ('true', 'always'):
126 self._on = True
127 else:
128 self._on = False
129
Shawn O. Pearce350cde42009-04-16 11:21:18 -0700130 def redirect(self, out):
131 self._out = out
132
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700133 @property
134 def is_on(self):
135 return self._on
136
137 def write(self, fmt, *args):
138 self._out.write(fmt % args)
139
Shawn O. Pearcedb45da12009-04-18 13:49:13 -0700140 def flush(self):
141 self._out.flush()
142
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700143 def nl(self):
144 self._out.write('\n')
145
146 def printer(self, opt=None, fg=None, bg=None, attr=None):
147 s = self
148 c = self.colorer(opt, fg, bg, attr)
Anthony Kingbdf7ed22015-03-28 21:10:17 +0000149
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700150 def f(fmt, *args):
151 s._out.write(c(fmt, *args))
152 return f
153
Olof Johanssonb7541502013-02-26 07:36:03 +0100154 def nofmt_printer(self, opt=None, fg=None, bg=None, attr=None):
155 s = self
156 c = self.nofmt_colorer(opt, fg, bg, attr)
Anthony Kingbdf7ed22015-03-28 21:10:17 +0000157
Olof Johanssonb7541502013-02-26 07:36:03 +0100158 def f(fmt):
159 s._out.write(c(fmt))
160 return f
161
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700162 def colorer(self, opt=None, fg=None, bg=None, attr=None):
163 if self._on:
164 c = self._parse(opt, fg, bg, attr)
Anthony Kingbdf7ed22015-03-28 21:10:17 +0000165
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700166 def f(fmt, *args):
David Pursehouse8a68ff92012-09-24 12:15:13 +0900167 output = fmt % args
168 return ''.join([c, output, RESET])
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700169 return f
170 else:
Anthony Kingbdf7ed22015-03-28 21:10:17 +0000171
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700172 def f(fmt, *args):
173 return fmt % args
174 return f
175
Olof Johanssonb7541502013-02-26 07:36:03 +0100176 def nofmt_colorer(self, opt=None, fg=None, bg=None, attr=None):
177 if self._on:
178 c = self._parse(opt, fg, bg, attr)
Anthony Kingbdf7ed22015-03-28 21:10:17 +0000179
Olof Johanssonb7541502013-02-26 07:36:03 +0100180 def f(fmt):
181 return ''.join([c, fmt, RESET])
182 return f
183 else:
184 def f(fmt):
185 return fmt
186 return f
187
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700188 def _parse(self, opt, fg, bg, attr):
189 if not opt:
190 return _Color(fg, bg, attr)
191
192 v = self._config.GetString('%s.%s' % (self._section, opt))
193 if v is None:
194 return _Color(fg, bg, attr)
195
Shawn O. Pearcea8e98a62009-02-02 16:17:02 -0800196 v = v.strip().lower()
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700197 if v == "reset":
198 return RESET
199 elif v == '':
200 return _Color(fg, bg, attr)
201
202 have_fg = False
203 for a in v.split(' '):
204 if is_color(a):
David Pursehouse8a68ff92012-09-24 12:15:13 +0900205 if have_fg:
206 bg = a
207 else:
208 fg = a
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700209 elif is_attr(a):
210 attr = a
211
212 return _Color(fg, bg, attr)