Initial Contribution
diff --git a/color.py b/color.py
new file mode 100644
index 0000000..b3a558c
--- /dev/null
+++ b/color.py
@@ -0,0 +1,154 @@
+#
+# Copyright (C) 2008 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import os
+import sys
+
+import pager
+from git_config import GitConfig
+
+COLORS = {None :-1,
+ 'normal' :-1,
+ 'black' : 0,
+ 'red' : 1,
+ 'green' : 2,
+ 'yellow' : 3,
+ 'blue' : 4,
+ 'magenta': 5,
+ 'cyan' : 6,
+ 'white' : 7}
+
+ATTRS = {None :-1,
+ 'bold' : 1,
+ 'dim' : 2,
+ 'ul' : 4,
+ 'blink' : 5,
+ 'reverse': 7}
+
+RESET = "\033[m"
+
+def is_color(s): return s in COLORS
+def is_attr(s): return s in ATTRS
+
+def _Color(fg = None, bg = None, attr = None):
+ fg = COLORS[fg]
+ bg = COLORS[bg]
+ attr = ATTRS[attr]
+
+ if attr >= 0 or fg >= 0 or bg >= 0:
+ need_sep = False
+ code = "\033["
+
+ if attr >= 0:
+ code += chr(ord('0') + attr)
+ need_sep = True
+
+ if fg >= 0:
+ if need_sep:
+ code += ';'
+ need_sep = True
+
+ if fg < 8:
+ code += '3%c' % (ord('0') + fg)
+ else:
+ code += '38;5;%d' % fg
+
+ if bg >= 0:
+ if need_sep:
+ code += ';'
+ need_sep = True
+
+ if bg < 8:
+ code += '4%c' % (ord('0') + bg)
+ else:
+ code += '48;5;%d' % bg
+ code += 'm'
+ else:
+ code = ''
+ return code
+
+
+class Coloring(object):
+ def __init__(self, config, type):
+ self._section = 'color.%s' % type
+ self._config = config
+ self._out = sys.stdout
+
+ on = self._config.GetString(self._section)
+ if on is None:
+ on = self._config.GetString('color.ui')
+
+ if on == 'auto':
+ if pager.active or os.isatty(1):
+ self._on = True
+ else:
+ self._on = False
+ elif on in ('true', 'always'):
+ self._on = True
+ else:
+ self._on = False
+
+ @property
+ def is_on(self):
+ return self._on
+
+ def write(self, fmt, *args):
+ self._out.write(fmt % args)
+
+ def nl(self):
+ self._out.write('\n')
+
+ def printer(self, opt=None, fg=None, bg=None, attr=None):
+ s = self
+ c = self.colorer(opt, fg, bg, attr)
+ def f(fmt, *args):
+ s._out.write(c(fmt, *args))
+ return f
+
+ def colorer(self, opt=None, fg=None, bg=None, attr=None):
+ if self._on:
+ c = self._parse(opt, fg, bg, attr)
+ def f(fmt, *args):
+ str = fmt % args
+ return ''.join([c, str, RESET])
+ return f
+ else:
+ def f(fmt, *args):
+ return fmt % args
+ return f
+
+ def _parse(self, opt, fg, bg, attr):
+ if not opt:
+ return _Color(fg, bg, attr)
+
+ v = self._config.GetString('%s.%s' % (self._section, opt))
+ if v is None:
+ return _Color(fg, bg, attr)
+
+ v = v.trim().lowercase()
+ if v == "reset":
+ return RESET
+ elif v == '':
+ return _Color(fg, bg, attr)
+
+ have_fg = False
+ for a in v.split(' '):
+ if is_color(a):
+ if have_fg: bg = a
+ else: fg = a
+ elif is_attr(a):
+ attr = a
+
+ return _Color(fg, bg, attr)