blob: 9b3365be1af023e8ac778909fd41451e7d2808de [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
39RESET = "\033[m"
40
41def is_color(s): return s in COLORS
42def is_attr(s): return s in ATTRS
43
44def _Color(fg = None, bg = None, attr = None):
45 fg = COLORS[fg]
46 bg = COLORS[bg]
47 attr = ATTRS[attr]
48
49 if attr >= 0 or fg >= 0 or bg >= 0:
50 need_sep = False
51 code = "\033["
52
53 if attr >= 0:
54 code += chr(ord('0') + attr)
55 need_sep = True
56
57 if fg >= 0:
58 if need_sep:
59 code += ';'
60 need_sep = True
61
62 if fg < 8:
63 code += '3%c' % (ord('0') + fg)
64 else:
65 code += '38;5;%d' % fg
66
67 if bg >= 0:
68 if need_sep:
69 code += ';'
70 need_sep = True
71
72 if bg < 8:
73 code += '4%c' % (ord('0') + bg)
74 else:
75 code += '48;5;%d' % bg
76 code += 'm'
77 else:
78 code = ''
79 return code
80
81
82class Coloring(object):
83 def __init__(self, config, type):
84 self._section = 'color.%s' % type
85 self._config = config
86 self._out = sys.stdout
87
88 on = self._config.GetString(self._section)
89 if on is None:
90 on = self._config.GetString('color.ui')
91
92 if on == 'auto':
93 if pager.active or os.isatty(1):
94 self._on = True
95 else:
96 self._on = False
97 elif on in ('true', 'always'):
98 self._on = True
99 else:
100 self._on = False
101
Shawn O. Pearce350cde42009-04-16 11:21:18 -0700102 def redirect(self, out):
103 self._out = out
104
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700105 @property
106 def is_on(self):
107 return self._on
108
109 def write(self, fmt, *args):
110 self._out.write(fmt % args)
111
Shawn O. Pearcedb45da12009-04-18 13:49:13 -0700112 def flush(self):
113 self._out.flush()
114
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700115 def nl(self):
116 self._out.write('\n')
117
118 def printer(self, opt=None, fg=None, bg=None, attr=None):
119 s = self
120 c = self.colorer(opt, fg, bg, attr)
121 def f(fmt, *args):
122 s._out.write(c(fmt, *args))
123 return f
124
125 def colorer(self, opt=None, fg=None, bg=None, attr=None):
126 if self._on:
127 c = self._parse(opt, fg, bg, attr)
128 def f(fmt, *args):
129 str = fmt % args
130 return ''.join([c, str, RESET])
131 return f
132 else:
133 def f(fmt, *args):
134 return fmt % args
135 return f
136
137 def _parse(self, opt, fg, bg, attr):
138 if not opt:
139 return _Color(fg, bg, attr)
140
141 v = self._config.GetString('%s.%s' % (self._section, opt))
142 if v is None:
143 return _Color(fg, bg, attr)
144
Shawn O. Pearcea8e98a62009-02-02 16:17:02 -0800145 v = v.strip().lower()
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700146 if v == "reset":
147 return RESET
148 elif v == '':
149 return _Color(fg, bg, attr)
150
151 have_fg = False
152 for a in v.split(' '):
153 if is_color(a):
154 if have_fg: bg = a
155 else: fg = a
156 elif is_attr(a):
157 attr = a
158
159 return _Color(fg, bg, attr)