blob: 5c612accbfe695a674c48630066ef1fd610abd9d [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
20from git_config import GitConfig
21
22COLORS = {None :-1,
23 'normal' :-1,
24 'black' : 0,
25 'red' : 1,
26 'green' : 2,
27 'yellow' : 3,
28 'blue' : 4,
29 'magenta': 5,
30 'cyan' : 6,
31 'white' : 7}
32
33ATTRS = {None :-1,
34 'bold' : 1,
35 'dim' : 2,
36 'ul' : 4,
37 'blink' : 5,
38 'reverse': 7}
39
40RESET = "\033[m"
41
42def is_color(s): return s in COLORS
43def is_attr(s): return s in ATTRS
44
45def _Color(fg = None, bg = None, attr = None):
46 fg = COLORS[fg]
47 bg = COLORS[bg]
48 attr = ATTRS[attr]
49
50 if attr >= 0 or fg >= 0 or bg >= 0:
51 need_sep = False
52 code = "\033["
53
54 if attr >= 0:
55 code += chr(ord('0') + attr)
56 need_sep = True
57
58 if fg >= 0:
59 if need_sep:
60 code += ';'
61 need_sep = True
62
63 if fg < 8:
64 code += '3%c' % (ord('0') + fg)
65 else:
66 code += '38;5;%d' % fg
67
68 if bg >= 0:
69 if need_sep:
70 code += ';'
71 need_sep = True
72
73 if bg < 8:
74 code += '4%c' % (ord('0') + bg)
75 else:
76 code += '48;5;%d' % bg
77 code += 'm'
78 else:
79 code = ''
80 return code
81
82
83class Coloring(object):
84 def __init__(self, config, type):
85 self._section = 'color.%s' % type
86 self._config = config
87 self._out = sys.stdout
88
89 on = self._config.GetString(self._section)
90 if on is None:
91 on = self._config.GetString('color.ui')
92
93 if on == 'auto':
94 if pager.active or os.isatty(1):
95 self._on = True
96 else:
97 self._on = False
98 elif on in ('true', 'always'):
99 self._on = True
100 else:
101 self._on = False
102
Shawn O. Pearce350cde42009-04-16 11:21:18 -0700103 def redirect(self, out):
104 self._out = out
105
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700106 @property
107 def is_on(self):
108 return self._on
109
110 def write(self, fmt, *args):
111 self._out.write(fmt % args)
112
Shawn O. Pearcedb45da12009-04-18 13:49:13 -0700113 def flush(self):
114 self._out.flush()
115
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700116 def nl(self):
117 self._out.write('\n')
118
119 def printer(self, opt=None, fg=None, bg=None, attr=None):
120 s = self
121 c = self.colorer(opt, fg, bg, attr)
122 def f(fmt, *args):
123 s._out.write(c(fmt, *args))
124 return f
125
126 def colorer(self, opt=None, fg=None, bg=None, attr=None):
127 if self._on:
128 c = self._parse(opt, fg, bg, attr)
129 def f(fmt, *args):
130 str = fmt % args
131 return ''.join([c, str, RESET])
132 return f
133 else:
134 def f(fmt, *args):
135 return fmt % args
136 return f
137
138 def _parse(self, opt, fg, bg, attr):
139 if not opt:
140 return _Color(fg, bg, attr)
141
142 v = self._config.GetString('%s.%s' % (self._section, opt))
143 if v is None:
144 return _Color(fg, bg, attr)
145
Shawn O. Pearcea8e98a62009-02-02 16:17:02 -0800146 v = v.strip().lower()
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700147 if v == "reset":
148 return RESET
149 elif v == '':
150 return _Color(fg, bg, attr)
151
152 have_fg = False
153 for a in v.split(' '):
154 if is_color(a):
155 if have_fg: bg = a
156 else: fg = a
157 elif is_attr(a):
158 attr = a
159
160 return _Color(fg, bg, attr)