blob: b3a558cdf34b8812e0687bc19cabd130c741cc98 [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
103 @property
104 def is_on(self):
105 return self._on
106
107 def write(self, fmt, *args):
108 self._out.write(fmt % args)
109
110 def nl(self):
111 self._out.write('\n')
112
113 def printer(self, opt=None, fg=None, bg=None, attr=None):
114 s = self
115 c = self.colorer(opt, fg, bg, attr)
116 def f(fmt, *args):
117 s._out.write(c(fmt, *args))
118 return f
119
120 def colorer(self, opt=None, fg=None, bg=None, attr=None):
121 if self._on:
122 c = self._parse(opt, fg, bg, attr)
123 def f(fmt, *args):
124 str = fmt % args
125 return ''.join([c, str, RESET])
126 return f
127 else:
128 def f(fmt, *args):
129 return fmt % args
130 return f
131
132 def _parse(self, opt, fg, bg, attr):
133 if not opt:
134 return _Color(fg, bg, attr)
135
136 v = self._config.GetString('%s.%s' % (self._section, opt))
137 if v is None:
138 return _Color(fg, bg, attr)
139
140 v = v.trim().lowercase()
141 if v == "reset":
142 return RESET
143 elif v == '':
144 return _Color(fg, bg, attr)
145
146 have_fg = False
147 for a in v.split(' '):
148 if is_color(a):
149 if have_fg: bg = a
150 else: fg = a
151 elif is_attr(a):
152 attr = a
153
154 return _Color(fg, bg, attr)