diff options
Diffstat (limited to 'color.py')
| -rw-r--r-- | color.py | 314 |
1 files changed, 159 insertions, 155 deletions
| @@ -17,196 +17,200 @@ import sys | |||
| 17 | 17 | ||
| 18 | import pager | 18 | import pager |
| 19 | 19 | ||
| 20 | COLORS = {None: -1, | 20 | COLORS = { |
| 21 | 'normal': -1, | 21 | None: -1, |
| 22 | 'black': 0, | 22 | "normal": -1, |
| 23 | 'red': 1, | 23 | "black": 0, |
| 24 | 'green': 2, | 24 | "red": 1, |
| 25 | 'yellow': 3, | 25 | "green": 2, |
| 26 | 'blue': 4, | 26 | "yellow": 3, |
| 27 | 'magenta': 5, | 27 | "blue": 4, |
| 28 | 'cyan': 6, | 28 | "magenta": 5, |
| 29 | 'white': 7} | 29 | "cyan": 6, |
| 30 | 30 | "white": 7, | |
| 31 | ATTRS = {None: -1, | 31 | } |
| 32 | 'bold': 1, | 32 | |
| 33 | 'dim': 2, | 33 | ATTRS = {None: -1, "bold": 1, "dim": 2, "ul": 4, "blink": 5, "reverse": 7} |
| 34 | 'ul': 4, | ||
| 35 | 'blink': 5, | ||
| 36 | 'reverse': 7} | ||
| 37 | 34 | ||
| 38 | RESET = "\033[m" | 35 | RESET = "\033[m" |
| 39 | 36 | ||
| 40 | 37 | ||
| 41 | def is_color(s): | 38 | def is_color(s): |
| 42 | return s in COLORS | 39 | return s in COLORS |
| 43 | 40 | ||
| 44 | 41 | ||
| 45 | def is_attr(s): | 42 | def is_attr(s): |
| 46 | return s in ATTRS | 43 | return s in ATTRS |
| 47 | 44 | ||
| 48 | 45 | ||
| 49 | def _Color(fg=None, bg=None, attr=None): | 46 | def _Color(fg=None, bg=None, attr=None): |
| 50 | fg = COLORS[fg] | 47 | fg = COLORS[fg] |
| 51 | bg = COLORS[bg] | 48 | bg = COLORS[bg] |
| 52 | attr = ATTRS[attr] | 49 | attr = ATTRS[attr] |
| 53 | 50 | ||
| 54 | if attr >= 0 or fg >= 0 or bg >= 0: | 51 | if attr >= 0 or fg >= 0 or bg >= 0: |
| 55 | need_sep = False | 52 | need_sep = False |
| 56 | code = "\033[" | 53 | code = "\033[" |
| 57 | 54 | ||
| 58 | if attr >= 0: | 55 | if attr >= 0: |
| 59 | code += chr(ord('0') + attr) | 56 | code += chr(ord("0") + attr) |
| 60 | need_sep = True | 57 | need_sep = True |
| 61 | 58 | ||
| 62 | if fg >= 0: | 59 | if fg >= 0: |
| 63 | if need_sep: | 60 | if need_sep: |
| 64 | code += ';' | 61 | code += ";" |
| 65 | need_sep = True | 62 | need_sep = True |
| 66 | 63 | ||
| 67 | if fg < 8: | 64 | if fg < 8: |
| 68 | code += '3%c' % (ord('0') + fg) | 65 | code += "3%c" % (ord("0") + fg) |
| 69 | else: | 66 | else: |
| 70 | code += '38;5;%d' % fg | 67 | code += "38;5;%d" % fg |
| 71 | 68 | ||
| 72 | if bg >= 0: | 69 | if bg >= 0: |
| 73 | if need_sep: | 70 | if need_sep: |
| 74 | code += ';' | 71 | code += ";" |
| 75 | 72 | ||
| 76 | if bg < 8: | 73 | if bg < 8: |
| 77 | code += '4%c' % (ord('0') + bg) | 74 | code += "4%c" % (ord("0") + bg) |
| 78 | else: | 75 | else: |
| 79 | code += '48;5;%d' % bg | 76 | code += "48;5;%d" % bg |
| 80 | code += 'm' | 77 | code += "m" |
| 81 | else: | 78 | else: |
| 82 | code = '' | 79 | code = "" |
| 83 | return code | 80 | return code |
| 84 | 81 | ||
| 85 | 82 | ||
| 86 | DEFAULT = None | 83 | DEFAULT = None |
| 87 | 84 | ||
| 88 | 85 | ||
| 89 | def SetDefaultColoring(state): | 86 | def SetDefaultColoring(state): |
| 90 | """Set coloring behavior to |state|. | 87 | """Set coloring behavior to |state|. |
| 91 | 88 | ||
| 92 | This is useful for overriding config options via the command line. | 89 | This is useful for overriding config options via the command line. |
| 93 | """ | 90 | """ |
| 94 | if state is None: | 91 | if state is None: |
| 95 | # Leave it alone -- return quick! | 92 | # Leave it alone -- return quick! |
| 96 | return | 93 | return |
| 97 | 94 | ||
| 98 | global DEFAULT | 95 | global DEFAULT |
| 99 | state = state.lower() | 96 | state = state.lower() |
| 100 | if state in ('auto',): | 97 | if state in ("auto",): |
| 101 | DEFAULT = state | 98 | DEFAULT = state |
| 102 | elif state in ('always', 'yes', 'true', True): | 99 | elif state in ("always", "yes", "true", True): |
| 103 | DEFAULT = 'always' | 100 | DEFAULT = "always" |
| 104 | elif state in ('never', 'no', 'false', False): | 101 | elif state in ("never", "no", "false", False): |
| 105 | DEFAULT = 'never' | 102 | DEFAULT = "never" |
| 106 | 103 | ||
| 107 | 104 | ||
| 108 | class Coloring(object): | 105 | class Coloring(object): |
| 109 | def __init__(self, config, section_type): | 106 | def __init__(self, config, section_type): |
| 110 | self._section = 'color.%s' % section_type | 107 | self._section = "color.%s" % section_type |
| 111 | self._config = config | 108 | self._config = config |
| 112 | self._out = sys.stdout | 109 | self._out = sys.stdout |
| 113 | 110 | ||
| 114 | on = DEFAULT | 111 | on = DEFAULT |
| 115 | if on is None: | 112 | if on is None: |
| 116 | on = self._config.GetString(self._section) | 113 | on = self._config.GetString(self._section) |
| 117 | if on is None: | 114 | if on is None: |
| 118 | on = self._config.GetString('color.ui') | 115 | on = self._config.GetString("color.ui") |
| 119 | 116 | ||
| 120 | if on == 'auto': | 117 | if on == "auto": |
| 121 | if pager.active or os.isatty(1): | 118 | if pager.active or os.isatty(1): |
| 122 | self._on = True | 119 | self._on = True |
| 123 | else: | 120 | else: |
| 124 | self._on = False | 121 | self._on = False |
| 125 | elif on in ('true', 'always'): | 122 | elif on in ("true", "always"): |
| 126 | self._on = True | 123 | self._on = True |
| 127 | else: | 124 | else: |
| 128 | self._on = False | 125 | self._on = False |
| 129 | 126 | ||
| 130 | def redirect(self, out): | 127 | def redirect(self, out): |
| 131 | self._out = out | 128 | self._out = out |
| 132 | 129 | ||
| 133 | @property | 130 | @property |
| 134 | def is_on(self): | 131 | def is_on(self): |
| 135 | return self._on | 132 | return self._on |
| 136 | 133 | ||
| 137 | def write(self, fmt, *args): | 134 | def write(self, fmt, *args): |
| 138 | self._out.write(fmt % args) | 135 | self._out.write(fmt % args) |
| 139 | 136 | ||
| 140 | def flush(self): | 137 | def flush(self): |
| 141 | self._out.flush() | 138 | self._out.flush() |
| 142 | 139 | ||
| 143 | def nl(self): | 140 | def nl(self): |
| 144 | self._out.write('\n') | 141 | self._out.write("\n") |
| 145 | 142 | ||
| 146 | def printer(self, opt=None, fg=None, bg=None, attr=None): | 143 | def printer(self, opt=None, fg=None, bg=None, attr=None): |
| 147 | s = self | 144 | s = self |
| 148 | c = self.colorer(opt, fg, bg, attr) | 145 | c = self.colorer(opt, fg, bg, attr) |
| 149 | 146 | ||
| 150 | def f(fmt, *args): | 147 | def f(fmt, *args): |
| 151 | s._out.write(c(fmt, *args)) | 148 | s._out.write(c(fmt, *args)) |
| 152 | return f | ||
| 153 | 149 | ||
| 154 | def nofmt_printer(self, opt=None, fg=None, bg=None, attr=None): | 150 | return f |
| 155 | s = self | ||
| 156 | c = self.nofmt_colorer(opt, fg, bg, attr) | ||
| 157 | 151 | ||
| 158 | def f(fmt): | 152 | def nofmt_printer(self, opt=None, fg=None, bg=None, attr=None): |
| 159 | s._out.write(c(fmt)) | 153 | s = self |
| 160 | return f | 154 | c = self.nofmt_colorer(opt, fg, bg, attr) |
| 161 | 155 | ||
| 162 | def colorer(self, opt=None, fg=None, bg=None, attr=None): | 156 | def f(fmt): |
| 163 | if self._on: | 157 | s._out.write(c(fmt)) |
| 164 | c = self._parse(opt, fg, bg, attr) | ||
| 165 | 158 | ||
| 166 | def f(fmt, *args): | 159 | return f |
| 167 | output = fmt % args | ||
| 168 | return ''.join([c, output, RESET]) | ||
| 169 | return f | ||
| 170 | else: | ||
| 171 | 160 | ||
| 172 | def f(fmt, *args): | 161 | def colorer(self, opt=None, fg=None, bg=None, attr=None): |
| 173 | return fmt % args | 162 | if self._on: |
| 174 | return f | 163 | c = self._parse(opt, fg, bg, attr) |
| 175 | 164 | ||
| 176 | def nofmt_colorer(self, opt=None, fg=None, bg=None, attr=None): | 165 | def f(fmt, *args): |
| 177 | if self._on: | 166 | output = fmt % args |
| 178 | c = self._parse(opt, fg, bg, attr) | 167 | return "".join([c, output, RESET]) |
| 179 | 168 | ||
| 180 | def f(fmt): | 169 | return f |
| 181 | return ''.join([c, fmt, RESET]) | ||
| 182 | return f | ||
| 183 | else: | ||
| 184 | def f(fmt): | ||
| 185 | return fmt | ||
| 186 | return f | ||
| 187 | |||
| 188 | def _parse(self, opt, fg, bg, attr): | ||
| 189 | if not opt: | ||
| 190 | return _Color(fg, bg, attr) | ||
| 191 | |||
| 192 | v = self._config.GetString('%s.%s' % (self._section, opt)) | ||
| 193 | if v is None: | ||
| 194 | return _Color(fg, bg, attr) | ||
| 195 | |||
| 196 | v = v.strip().lower() | ||
| 197 | if v == "reset": | ||
| 198 | return RESET | ||
| 199 | elif v == '': | ||
| 200 | return _Color(fg, bg, attr) | ||
| 201 | |||
| 202 | have_fg = False | ||
| 203 | for a in v.split(' '): | ||
| 204 | if is_color(a): | ||
| 205 | if have_fg: | ||
| 206 | bg = a | ||
| 207 | else: | 170 | else: |
| 208 | fg = a | ||
| 209 | elif is_attr(a): | ||
| 210 | attr = a | ||
| 211 | 171 | ||
| 212 | return _Color(fg, bg, attr) | 172 | def f(fmt, *args): |
| 173 | return fmt % args | ||
| 174 | |||
| 175 | return f | ||
| 176 | |||
| 177 | def nofmt_colorer(self, opt=None, fg=None, bg=None, attr=None): | ||
| 178 | if self._on: | ||
| 179 | c = self._parse(opt, fg, bg, attr) | ||
| 180 | |||
| 181 | def f(fmt): | ||
| 182 | return "".join([c, fmt, RESET]) | ||
| 183 | |||
| 184 | return f | ||
| 185 | else: | ||
| 186 | |||
| 187 | def f(fmt): | ||
| 188 | return fmt | ||
| 189 | |||
| 190 | return f | ||
| 191 | |||
| 192 | def _parse(self, opt, fg, bg, attr): | ||
| 193 | if not opt: | ||
| 194 | return _Color(fg, bg, attr) | ||
| 195 | |||
| 196 | v = self._config.GetString("%s.%s" % (self._section, opt)) | ||
| 197 | if v is None: | ||
| 198 | return _Color(fg, bg, attr) | ||
| 199 | |||
| 200 | v = v.strip().lower() | ||
| 201 | if v == "reset": | ||
| 202 | return RESET | ||
| 203 | elif v == "": | ||
| 204 | return _Color(fg, bg, attr) | ||
| 205 | |||
| 206 | have_fg = False | ||
| 207 | for a in v.split(" "): | ||
| 208 | if is_color(a): | ||
| 209 | if have_fg: | ||
| 210 | bg = a | ||
| 211 | else: | ||
| 212 | fg = a | ||
| 213 | elif is_attr(a): | ||
| 214 | attr = a | ||
| 215 | |||
| 216 | return _Color(fg, bg, attr) | ||
