diff options
| author | The Android Open Source Project <initial-contribution@android.com> | 2008-10-21 07:00:00 -0700 |
|---|---|---|
| committer | The Android Open Source Project <initial-contribution@android.com> | 2008-10-21 07:00:00 -0700 |
| commit | cf31fe9b4fb650b27e19f5d7ee7297e383660caf (patch) | |
| tree | d04ca6a45d579dca5e5469606c48c405aee68f4b /color.py | |
| download | git-repo-cf31fe9b4fb650b27e19f5d7ee7297e383660caf.tar.gz | |
Initial Contributionv1.0
Diffstat (limited to 'color.py')
| -rw-r--r-- | color.py | 154 |
1 files changed, 154 insertions, 0 deletions
diff --git a/color.py b/color.py new file mode 100644 index 00000000..b3a558cd --- /dev/null +++ b/color.py | |||
| @@ -0,0 +1,154 @@ | |||
| 1 | # | ||
| 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 | |||
| 16 | import os | ||
| 17 | import sys | ||
| 18 | |||
| 19 | import pager | ||
| 20 | from git_config import GitConfig | ||
| 21 | |||
| 22 | COLORS = {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 | |||
| 33 | ATTRS = {None :-1, | ||
| 34 | 'bold' : 1, | ||
| 35 | 'dim' : 2, | ||
| 36 | 'ul' : 4, | ||
| 37 | 'blink' : 5, | ||
| 38 | 'reverse': 7} | ||
| 39 | |||
| 40 | RESET = "\033[m" | ||
| 41 | |||
| 42 | def is_color(s): return s in COLORS | ||
| 43 | def is_attr(s): return s in ATTRS | ||
| 44 | |||
| 45 | def _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 | |||
| 83 | class 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) | ||
