blob: 7fa21d23cd633b2a7aef30211527a8c96d8c5d9a [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
113 def nl(self):
114 self._out.write('\n')
115
116 def printer(self, opt=None, fg=None, bg=None, attr=None):
117 s = self
118 c = self.colorer(opt, fg, bg, attr)
119 def f(fmt, *args):
120 s._out.write(c(fmt, *args))
121 return f
122
123 def colorer(self, opt=None, fg=None, bg=None, attr=None):
124 if self._on:
125 c = self._parse(opt, fg, bg, attr)
126 def f(fmt, *args):
127 str = fmt % args
128 return ''.join([c, str, RESET])
129 return f
130 else:
131 def f(fmt, *args):
132 return fmt % args
133 return f
134
135 def _parse(self, opt, fg, bg, attr):
136 if not opt:
137 return _Color(fg, bg, attr)
138
139 v = self._config.GetString('%s.%s' % (self._section, opt))
140 if v is None:
141 return _Color(fg, bg, attr)
142
Shawn O. Pearcea8e98a62009-02-02 16:17:02 -0800143 v = v.strip().lower()
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700144 if v == "reset":
145 return RESET
146 elif v == '':
147 return _Color(fg, bg, attr)
148
149 have_fg = False
150 for a in v.split(' '):
151 if is_color(a):
152 if have_fg: bg = a
153 else: fg = a
154 elif is_attr(a):
155 attr = a
156
157 return _Color(fg, bg, attr)