Mercurial > hg
comparison mercurial/color.py @ 43077:687b865b95ad
formatting: byteify all mercurial/ and hgext/ string literals
Done with
python3.7 contrib/byteify-strings.py -i $(hg files 'set:mercurial/**.py - mercurial/thirdparty/** + hgext/**.py - hgext/fsmonitor/pywatchman/** - mercurial/__init__.py')
black -l 80 -t py33 -S $(hg files 'set:**.py - mercurial/thirdparty/** - "contrib/python-zstandard/**" - hgext/fsmonitor/pywatchman/**')
# skip-blame mass-reformatting only
Differential Revision: https://phab.mercurial-scm.org/D6972
author | Augie Fackler <augie@google.com> |
---|---|
date | Sun, 06 Oct 2019 09:48:39 -0400 |
parents | 2372284d9457 |
children | c59eb1560c44 |
comparison
equal
deleted
inserted
replaced
43076:2372284d9457 | 43077:687b865b95ad |
---|---|
22 import curses | 22 import curses |
23 | 23 |
24 # Mapping from effect name to terminfo attribute name (or raw code) or | 24 # Mapping from effect name to terminfo attribute name (or raw code) or |
25 # color number. This will also force-load the curses module. | 25 # color number. This will also force-load the curses module. |
26 _baseterminfoparams = { | 26 _baseterminfoparams = { |
27 'none': (True, 'sgr0', ''), | 27 b'none': (True, b'sgr0', b''), |
28 'standout': (True, 'smso', ''), | 28 b'standout': (True, b'smso', b''), |
29 'underline': (True, 'smul', ''), | 29 b'underline': (True, b'smul', b''), |
30 'reverse': (True, 'rev', ''), | 30 b'reverse': (True, b'rev', b''), |
31 'inverse': (True, 'rev', ''), | 31 b'inverse': (True, b'rev', b''), |
32 'blink': (True, 'blink', ''), | 32 b'blink': (True, b'blink', b''), |
33 'dim': (True, 'dim', ''), | 33 b'dim': (True, b'dim', b''), |
34 'bold': (True, 'bold', ''), | 34 b'bold': (True, b'bold', b''), |
35 'invisible': (True, 'invis', ''), | 35 b'invisible': (True, b'invis', b''), |
36 'italic': (True, 'sitm', ''), | 36 b'italic': (True, b'sitm', b''), |
37 'black': (False, curses.COLOR_BLACK, ''), | 37 b'black': (False, curses.COLOR_BLACK, b''), |
38 'red': (False, curses.COLOR_RED, ''), | 38 b'red': (False, curses.COLOR_RED, b''), |
39 'green': (False, curses.COLOR_GREEN, ''), | 39 b'green': (False, curses.COLOR_GREEN, b''), |
40 'yellow': (False, curses.COLOR_YELLOW, ''), | 40 b'yellow': (False, curses.COLOR_YELLOW, b''), |
41 'blue': (False, curses.COLOR_BLUE, ''), | 41 b'blue': (False, curses.COLOR_BLUE, b''), |
42 'magenta': (False, curses.COLOR_MAGENTA, ''), | 42 b'magenta': (False, curses.COLOR_MAGENTA, b''), |
43 'cyan': (False, curses.COLOR_CYAN, ''), | 43 b'cyan': (False, curses.COLOR_CYAN, b''), |
44 'white': (False, curses.COLOR_WHITE, ''), | 44 b'white': (False, curses.COLOR_WHITE, b''), |
45 } | 45 } |
46 except ImportError: | 46 except ImportError: |
47 curses = None | 47 curses = None |
48 _baseterminfoparams = {} | 48 _baseterminfoparams = {} |
49 | 49 |
50 # start and stop parameters for effects | 50 # start and stop parameters for effects |
51 _effects = { | 51 _effects = { |
52 'none': 0, | 52 b'none': 0, |
53 'black': 30, | 53 b'black': 30, |
54 'red': 31, | 54 b'red': 31, |
55 'green': 32, | 55 b'green': 32, |
56 'yellow': 33, | 56 b'yellow': 33, |
57 'blue': 34, | 57 b'blue': 34, |
58 'magenta': 35, | 58 b'magenta': 35, |
59 'cyan': 36, | 59 b'cyan': 36, |
60 'white': 37, | 60 b'white': 37, |
61 'bold': 1, | 61 b'bold': 1, |
62 'italic': 3, | 62 b'italic': 3, |
63 'underline': 4, | 63 b'underline': 4, |
64 'inverse': 7, | 64 b'inverse': 7, |
65 'dim': 2, | 65 b'dim': 2, |
66 'black_background': 40, | 66 b'black_background': 40, |
67 'red_background': 41, | 67 b'red_background': 41, |
68 'green_background': 42, | 68 b'green_background': 42, |
69 'yellow_background': 43, | 69 b'yellow_background': 43, |
70 'blue_background': 44, | 70 b'blue_background': 44, |
71 'purple_background': 45, | 71 b'purple_background': 45, |
72 'cyan_background': 46, | 72 b'cyan_background': 46, |
73 'white_background': 47, | 73 b'white_background': 47, |
74 } | 74 } |
75 | 75 |
76 _defaultstyles = { | 76 _defaultstyles = { |
77 'grep.match': 'red bold', | 77 b'grep.match': b'red bold', |
78 'grep.linenumber': 'green', | 78 b'grep.linenumber': b'green', |
79 'grep.rev': 'blue', | 79 b'grep.rev': b'blue', |
80 'grep.sep': 'cyan', | 80 b'grep.sep': b'cyan', |
81 'grep.filename': 'magenta', | 81 b'grep.filename': b'magenta', |
82 'grep.user': 'magenta', | 82 b'grep.user': b'magenta', |
83 'grep.date': 'magenta', | 83 b'grep.date': b'magenta', |
84 'grep.inserted': 'green bold', | 84 b'grep.inserted': b'green bold', |
85 'grep.deleted': 'red bold', | 85 b'grep.deleted': b'red bold', |
86 'bookmarks.active': 'green', | 86 b'bookmarks.active': b'green', |
87 'branches.active': 'none', | 87 b'branches.active': b'none', |
88 'branches.closed': 'black bold', | 88 b'branches.closed': b'black bold', |
89 'branches.current': 'green', | 89 b'branches.current': b'green', |
90 'branches.inactive': 'none', | 90 b'branches.inactive': b'none', |
91 'diff.changed': 'white', | 91 b'diff.changed': b'white', |
92 'diff.deleted': 'red', | 92 b'diff.deleted': b'red', |
93 'diff.deleted.changed': 'red bold underline', | 93 b'diff.deleted.changed': b'red bold underline', |
94 'diff.deleted.unchanged': 'red', | 94 b'diff.deleted.unchanged': b'red', |
95 'diff.diffline': 'bold', | 95 b'diff.diffline': b'bold', |
96 'diff.extended': 'cyan bold', | 96 b'diff.extended': b'cyan bold', |
97 'diff.file_a': 'red bold', | 97 b'diff.file_a': b'red bold', |
98 'diff.file_b': 'green bold', | 98 b'diff.file_b': b'green bold', |
99 'diff.hunk': 'magenta', | 99 b'diff.hunk': b'magenta', |
100 'diff.inserted': 'green', | 100 b'diff.inserted': b'green', |
101 'diff.inserted.changed': 'green bold underline', | 101 b'diff.inserted.changed': b'green bold underline', |
102 'diff.inserted.unchanged': 'green', | 102 b'diff.inserted.unchanged': b'green', |
103 'diff.tab': '', | 103 b'diff.tab': b'', |
104 'diff.trailingwhitespace': 'bold red_background', | 104 b'diff.trailingwhitespace': b'bold red_background', |
105 'changeset.public': '', | 105 b'changeset.public': b'', |
106 'changeset.draft': '', | 106 b'changeset.draft': b'', |
107 'changeset.secret': '', | 107 b'changeset.secret': b'', |
108 'diffstat.deleted': 'red', | 108 b'diffstat.deleted': b'red', |
109 'diffstat.inserted': 'green', | 109 b'diffstat.inserted': b'green', |
110 'formatvariant.name.mismatchconfig': 'red', | 110 b'formatvariant.name.mismatchconfig': b'red', |
111 'formatvariant.name.mismatchdefault': 'yellow', | 111 b'formatvariant.name.mismatchdefault': b'yellow', |
112 'formatvariant.name.uptodate': 'green', | 112 b'formatvariant.name.uptodate': b'green', |
113 'formatvariant.repo.mismatchconfig': 'red', | 113 b'formatvariant.repo.mismatchconfig': b'red', |
114 'formatvariant.repo.mismatchdefault': 'yellow', | 114 b'formatvariant.repo.mismatchdefault': b'yellow', |
115 'formatvariant.repo.uptodate': 'green', | 115 b'formatvariant.repo.uptodate': b'green', |
116 'formatvariant.config.special': 'yellow', | 116 b'formatvariant.config.special': b'yellow', |
117 'formatvariant.config.default': 'green', | 117 b'formatvariant.config.default': b'green', |
118 'formatvariant.default': '', | 118 b'formatvariant.default': b'', |
119 'histedit.remaining': 'red bold', | 119 b'histedit.remaining': b'red bold', |
120 'ui.addremove.added': 'green', | 120 b'ui.addremove.added': b'green', |
121 'ui.addremove.removed': 'red', | 121 b'ui.addremove.removed': b'red', |
122 'ui.error': 'red', | 122 b'ui.error': b'red', |
123 'ui.prompt': 'yellow', | 123 b'ui.prompt': b'yellow', |
124 'log.changeset': 'yellow', | 124 b'log.changeset': b'yellow', |
125 'patchbomb.finalsummary': '', | 125 b'patchbomb.finalsummary': b'', |
126 'patchbomb.from': 'magenta', | 126 b'patchbomb.from': b'magenta', |
127 'patchbomb.to': 'cyan', | 127 b'patchbomb.to': b'cyan', |
128 'patchbomb.subject': 'green', | 128 b'patchbomb.subject': b'green', |
129 'patchbomb.diffstats': '', | 129 b'patchbomb.diffstats': b'', |
130 'rebase.rebased': 'blue', | 130 b'rebase.rebased': b'blue', |
131 'rebase.remaining': 'red bold', | 131 b'rebase.remaining': b'red bold', |
132 'resolve.resolved': 'green bold', | 132 b'resolve.resolved': b'green bold', |
133 'resolve.unresolved': 'red bold', | 133 b'resolve.unresolved': b'red bold', |
134 'shelve.age': 'cyan', | 134 b'shelve.age': b'cyan', |
135 'shelve.newest': 'green bold', | 135 b'shelve.newest': b'green bold', |
136 'shelve.name': 'blue bold', | 136 b'shelve.name': b'blue bold', |
137 'status.added': 'green bold', | 137 b'status.added': b'green bold', |
138 'status.clean': 'none', | 138 b'status.clean': b'none', |
139 'status.copied': 'none', | 139 b'status.copied': b'none', |
140 'status.deleted': 'cyan bold underline', | 140 b'status.deleted': b'cyan bold underline', |
141 'status.ignored': 'black bold', | 141 b'status.ignored': b'black bold', |
142 'status.modified': 'blue bold', | 142 b'status.modified': b'blue bold', |
143 'status.removed': 'red bold', | 143 b'status.removed': b'red bold', |
144 'status.unknown': 'magenta bold underline', | 144 b'status.unknown': b'magenta bold underline', |
145 'tags.normal': 'green', | 145 b'tags.normal': b'green', |
146 'tags.local': 'black bold', | 146 b'tags.local': b'black bold', |
147 } | 147 } |
148 | 148 |
149 | 149 |
150 def loadcolortable(ui, extname, colortable): | 150 def loadcolortable(ui, extname, colortable): |
151 _defaultstyles.update(colortable) | 151 _defaultstyles.update(colortable) |
156 | 156 |
157 # If we failed to load curses, we go ahead and return. | 157 # If we failed to load curses, we go ahead and return. |
158 if curses is None: | 158 if curses is None: |
159 return | 159 return |
160 # Otherwise, see what the config file says. | 160 # Otherwise, see what the config file says. |
161 if mode not in ('auto', 'terminfo'): | 161 if mode not in (b'auto', b'terminfo'): |
162 return | 162 return |
163 ui._terminfoparams.update(_baseterminfoparams) | 163 ui._terminfoparams.update(_baseterminfoparams) |
164 | 164 |
165 for key, val in ui.configitems('color'): | 165 for key, val in ui.configitems(b'color'): |
166 if key.startswith('color.'): | 166 if key.startswith(b'color.'): |
167 newval = (False, int(val), '') | 167 newval = (False, int(val), b'') |
168 ui._terminfoparams[key[6:]] = newval | 168 ui._terminfoparams[key[6:]] = newval |
169 elif key.startswith('terminfo.'): | 169 elif key.startswith(b'terminfo.'): |
170 newval = (True, '', val.replace('\\E', '\x1b')) | 170 newval = (True, b'', val.replace(b'\\E', b'\x1b')) |
171 ui._terminfoparams[key[9:]] = newval | 171 ui._terminfoparams[key[9:]] = newval |
172 try: | 172 try: |
173 curses.setupterm() | 173 curses.setupterm() |
174 except curses.error: | 174 except curses.error: |
175 ui._terminfoparams.clear() | 175 ui._terminfoparams.clear() |
179 if not b: | 179 if not b: |
180 continue | 180 continue |
181 if not c and not curses.tigetstr(pycompat.sysstr(e)): | 181 if not c and not curses.tigetstr(pycompat.sysstr(e)): |
182 # Most terminals don't support dim, invis, etc, so don't be | 182 # Most terminals don't support dim, invis, etc, so don't be |
183 # noisy and use ui.debug(). | 183 # noisy and use ui.debug(). |
184 ui.debug("no terminfo entry for %s\n" % e) | 184 ui.debug(b"no terminfo entry for %s\n" % e) |
185 del ui._terminfoparams[key] | 185 del ui._terminfoparams[key] |
186 if not curses.tigetstr(r'setaf') or not curses.tigetstr(r'setab'): | 186 if not curses.tigetstr(r'setaf') or not curses.tigetstr(r'setab'): |
187 # Only warn about missing terminfo entries if we explicitly asked for | 187 # Only warn about missing terminfo entries if we explicitly asked for |
188 # terminfo mode and we're in a formatted terminal. | 188 # terminfo mode and we're in a formatted terminal. |
189 if mode == "terminfo" and formatted: | 189 if mode == b"terminfo" and formatted: |
190 ui.warn( | 190 ui.warn( |
191 _( | 191 _( |
192 "no terminfo entry for setab/setaf: reverting to " | 192 b"no terminfo entry for setab/setaf: reverting to " |
193 "ECMA-48 color\n" | 193 b"ECMA-48 color\n" |
194 ) | 194 ) |
195 ) | 195 ) |
196 ui._terminfoparams.clear() | 196 ui._terminfoparams.clear() |
197 | 197 |
198 | 198 |
201 | 201 |
202 That function both set the colormode for the ui object and read | 202 That function both set the colormode for the ui object and read |
203 the configuration looking for custom colors and effect definitions.""" | 203 the configuration looking for custom colors and effect definitions.""" |
204 mode = _modesetup(ui) | 204 mode = _modesetup(ui) |
205 ui._colormode = mode | 205 ui._colormode = mode |
206 if mode and mode != 'debug': | 206 if mode and mode != b'debug': |
207 configstyles(ui) | 207 configstyles(ui) |
208 | 208 |
209 | 209 |
210 def _modesetup(ui): | 210 def _modesetup(ui): |
211 if ui.plain('color'): | 211 if ui.plain(b'color'): |
212 return None | 212 return None |
213 config = ui.config('ui', 'color') | 213 config = ui.config(b'ui', b'color') |
214 if config == 'debug': | 214 if config == b'debug': |
215 return 'debug' | 215 return b'debug' |
216 | 216 |
217 auto = config == 'auto' | 217 auto = config == b'auto' |
218 always = False | 218 always = False |
219 if not auto and stringutil.parsebool(config): | 219 if not auto and stringutil.parsebool(config): |
220 # We want the config to behave like a boolean, "on" is actually auto, | 220 # We want the config to behave like a boolean, "on" is actually auto, |
221 # but "always" value is treated as a special case to reduce confusion. | 221 # but "always" value is treated as a special case to reduce confusion. |
222 if ui.configsource('ui', 'color') == '--color' or config == 'always': | 222 if ( |
223 ui.configsource(b'ui', b'color') == b'--color' | |
224 or config == b'always' | |
225 ): | |
223 always = True | 226 always = True |
224 else: | 227 else: |
225 auto = True | 228 auto = True |
226 | 229 |
227 if not always and not auto: | 230 if not always and not auto: |
228 return None | 231 return None |
229 | 232 |
230 formatted = always or ( | 233 formatted = always or ( |
231 encoding.environ.get('TERM') != 'dumb' and ui.formatted() | 234 encoding.environ.get(b'TERM') != b'dumb' and ui.formatted() |
232 ) | 235 ) |
233 | 236 |
234 mode = ui.config('color', 'mode') | 237 mode = ui.config(b'color', b'mode') |
235 | 238 |
236 # If pager is active, color.pagermode overrides color.mode. | 239 # If pager is active, color.pagermode overrides color.mode. |
237 if getattr(ui, 'pageractive', False): | 240 if getattr(ui, 'pageractive', False): |
238 mode = ui.config('color', 'pagermode', mode) | 241 mode = ui.config(b'color', b'pagermode', mode) |
239 | 242 |
240 realmode = mode | 243 realmode = mode |
241 if pycompat.iswindows: | 244 if pycompat.iswindows: |
242 from . import win32 | 245 from . import win32 |
243 | 246 |
244 term = encoding.environ.get('TERM') | 247 term = encoding.environ.get(b'TERM') |
245 # TERM won't be defined in a vanilla cmd.exe environment. | 248 # TERM won't be defined in a vanilla cmd.exe environment. |
246 | 249 |
247 # UNIX-like environments on Windows such as Cygwin and MSYS will | 250 # UNIX-like environments on Windows such as Cygwin and MSYS will |
248 # set TERM. They appear to make a best effort attempt at setting it | 251 # set TERM. They appear to make a best effort attempt at setting it |
249 # to something appropriate. However, not all environments with TERM | 252 # to something appropriate. However, not all environments with TERM |
250 # defined support ANSI. | 253 # defined support ANSI. |
251 ansienviron = term and 'xterm' in term | 254 ansienviron = term and b'xterm' in term |
252 | 255 |
253 if mode == 'auto': | 256 if mode == b'auto': |
254 # Since "ansi" could result in terminal gibberish, we error on the | 257 # Since "ansi" could result in terminal gibberish, we error on the |
255 # side of selecting "win32". However, if w32effects is not defined, | 258 # side of selecting "win32". However, if w32effects is not defined, |
256 # we almost certainly don't support "win32", so don't even try. | 259 # we almost certainly don't support "win32", so don't even try. |
257 # w32effects is not populated when stdout is redirected, so checking | 260 # w32effects is not populated when stdout is redirected, so checking |
258 # it first avoids win32 calls in a state known to error out. | 261 # it first avoids win32 calls in a state known to error out. |
259 if ansienviron or not w32effects or win32.enablevtmode(): | 262 if ansienviron or not w32effects or win32.enablevtmode(): |
260 realmode = 'ansi' | 263 realmode = b'ansi' |
261 else: | 264 else: |
262 realmode = 'win32' | 265 realmode = b'win32' |
263 # An empty w32effects is a clue that stdout is redirected, and thus | 266 # An empty w32effects is a clue that stdout is redirected, and thus |
264 # cannot enable VT mode. | 267 # cannot enable VT mode. |
265 elif mode == 'ansi' and w32effects and not ansienviron: | 268 elif mode == b'ansi' and w32effects and not ansienviron: |
266 win32.enablevtmode() | 269 win32.enablevtmode() |
267 elif mode == 'auto': | 270 elif mode == b'auto': |
268 realmode = 'ansi' | 271 realmode = b'ansi' |
269 | 272 |
270 def modewarn(): | 273 def modewarn(): |
271 # only warn if color.mode was explicitly set and we're in | 274 # only warn if color.mode was explicitly set and we're in |
272 # a formatted terminal | 275 # a formatted terminal |
273 if mode == realmode and formatted: | 276 if mode == realmode and formatted: |
274 ui.warn(_('warning: failed to set color mode to %s\n') % mode) | 277 ui.warn(_(b'warning: failed to set color mode to %s\n') % mode) |
275 | 278 |
276 if realmode == 'win32': | 279 if realmode == b'win32': |
277 ui._terminfoparams.clear() | 280 ui._terminfoparams.clear() |
278 if not w32effects: | 281 if not w32effects: |
279 modewarn() | 282 modewarn() |
280 return None | 283 return None |
281 elif realmode == 'ansi': | 284 elif realmode == b'ansi': |
282 ui._terminfoparams.clear() | 285 ui._terminfoparams.clear() |
283 elif realmode == 'terminfo': | 286 elif realmode == b'terminfo': |
284 _terminfosetup(ui, mode, formatted) | 287 _terminfosetup(ui, mode, formatted) |
285 if not ui._terminfoparams: | 288 if not ui._terminfoparams: |
286 ## FIXME Shouldn't we return None in this case too? | 289 ## FIXME Shouldn't we return None in this case too? |
287 modewarn() | 290 modewarn() |
288 realmode = 'ansi' | 291 realmode = b'ansi' |
289 else: | 292 else: |
290 return None | 293 return None |
291 | 294 |
292 if always or (auto and formatted): | 295 if always or (auto and formatted): |
293 return realmode | 296 return realmode |
294 return None | 297 return None |
295 | 298 |
296 | 299 |
297 def configstyles(ui): | 300 def configstyles(ui): |
298 ui._styles.update(_defaultstyles) | 301 ui._styles.update(_defaultstyles) |
299 for status, cfgeffects in ui.configitems('color'): | 302 for status, cfgeffects in ui.configitems(b'color'): |
300 if '.' not in status or status.startswith(('color.', 'terminfo.')): | 303 if b'.' not in status or status.startswith((b'color.', b'terminfo.')): |
301 continue | 304 continue |
302 cfgeffects = ui.configlist('color', status) | 305 cfgeffects = ui.configlist(b'color', status) |
303 if cfgeffects: | 306 if cfgeffects: |
304 good = [] | 307 good = [] |
305 for e in cfgeffects: | 308 for e in cfgeffects: |
306 if valideffect(ui, e): | 309 if valideffect(ui, e): |
307 good.append(e) | 310 good.append(e) |
308 else: | 311 else: |
309 ui.warn( | 312 ui.warn( |
310 _( | 313 _( |
311 "ignoring unknown color/effect %s " | 314 b"ignoring unknown color/effect %s " |
312 "(configured in color.%s)\n" | 315 b"(configured in color.%s)\n" |
313 ) | 316 ) |
314 % (stringutil.pprint(e), status) | 317 % (stringutil.pprint(e), status) |
315 ) | 318 ) |
316 ui._styles[status] = ' '.join(good) | 319 ui._styles[status] = b' '.join(good) |
317 | 320 |
318 | 321 |
319 def _activeeffects(ui): | 322 def _activeeffects(ui): |
320 '''Return the effects map for the color mode set on the ui.''' | 323 '''Return the effects map for the color mode set on the ui.''' |
321 if ui._colormode == 'win32': | 324 if ui._colormode == b'win32': |
322 return w32effects | 325 return w32effects |
323 elif ui._colormode is not None: | 326 elif ui._colormode is not None: |
324 return _effects | 327 return _effects |
325 return {} | 328 return {} |
326 | 329 |
327 | 330 |
328 def valideffect(ui, effect): | 331 def valideffect(ui, effect): |
329 'Determine if the effect is valid or not.' | 332 b'Determine if the effect is valid or not.' |
330 return (not ui._terminfoparams and effect in _activeeffects(ui)) or ( | 333 return (not ui._terminfoparams and effect in _activeeffects(ui)) or ( |
331 effect in ui._terminfoparams or effect[:-11] in ui._terminfoparams | 334 effect in ui._terminfoparams or effect[:-11] in ui._terminfoparams |
332 ) | 335 ) |
333 | 336 |
334 | 337 |
335 def _effect_str(ui, effect): | 338 def _effect_str(ui, effect): |
336 '''Helper function for render_effects().''' | 339 '''Helper function for render_effects().''' |
337 | 340 |
338 bg = False | 341 bg = False |
339 if effect.endswith('_background'): | 342 if effect.endswith(b'_background'): |
340 bg = True | 343 bg = True |
341 effect = effect[:-11] | 344 effect = effect[:-11] |
342 try: | 345 try: |
343 attr, val, termcode = ui._terminfoparams[effect] | 346 attr, val, termcode = ui._terminfoparams[effect] |
344 except KeyError: | 347 except KeyError: |
345 return '' | 348 return b'' |
346 if attr: | 349 if attr: |
347 if termcode: | 350 if termcode: |
348 return termcode | 351 return termcode |
349 else: | 352 else: |
350 return curses.tigetstr(pycompat.sysstr(val)) | 353 return curses.tigetstr(pycompat.sysstr(val)) |
367 parts = [] | 370 parts = [] |
368 for t in text.split(stop): | 371 for t in text.split(stop): |
369 if not t: | 372 if not t: |
370 continue | 373 continue |
371 parts.extend([start, t, stop]) | 374 parts.extend([start, t, stop]) |
372 return ''.join(parts) | 375 return b''.join(parts) |
373 | 376 |
374 | 377 |
375 def _render_effects(ui, text, effects): | 378 def _render_effects(ui, text, effects): |
376 'Wrap text in commands to turn on each effect.' | 379 b'Wrap text in commands to turn on each effect.' |
377 if not text: | 380 if not text: |
378 return text | 381 return text |
379 if ui._terminfoparams: | 382 if ui._terminfoparams: |
380 start = ''.join( | 383 start = b''.join( |
381 _effect_str(ui, effect) for effect in ['none'] + effects.split() | 384 _effect_str(ui, effect) for effect in [b'none'] + effects.split() |
382 ) | 385 ) |
383 stop = _effect_str(ui, 'none') | 386 stop = _effect_str(ui, b'none') |
384 else: | 387 else: |
385 activeeffects = _activeeffects(ui) | 388 activeeffects = _activeeffects(ui) |
386 start = [ | 389 start = [ |
387 pycompat.bytestr(activeeffects[e]) | 390 pycompat.bytestr(activeeffects[e]) |
388 for e in ['none'] + effects.split() | 391 for e in [b'none'] + effects.split() |
389 ] | 392 ] |
390 start = '\033[' + ';'.join(start) + 'm' | 393 start = b'\033[' + b';'.join(start) + b'm' |
391 stop = '\033[' + pycompat.bytestr(activeeffects['none']) + 'm' | 394 stop = b'\033[' + pycompat.bytestr(activeeffects[b'none']) + b'm' |
392 return _mergeeffects(text, start, stop) | 395 return _mergeeffects(text, start, stop) |
393 | 396 |
394 | 397 |
395 _ansieffectre = re.compile(br'\x1b\[[0-9;]*m') | 398 _ansieffectre = re.compile(br'\x1b\[[0-9;]*m') |
396 | 399 |
397 | 400 |
398 def stripeffects(text): | 401 def stripeffects(text): |
399 """Strip ANSI control codes which could be inserted by colorlabel()""" | 402 """Strip ANSI control codes which could be inserted by colorlabel()""" |
400 return _ansieffectre.sub('', text) | 403 return _ansieffectre.sub(b'', text) |
401 | 404 |
402 | 405 |
403 def colorlabel(ui, msg, label): | 406 def colorlabel(ui, msg, label): |
404 """add color control code according to the mode""" | 407 """add color control code according to the mode""" |
405 if ui._colormode == 'debug': | 408 if ui._colormode == b'debug': |
406 if label and msg: | 409 if label and msg: |
407 if msg.endswith('\n'): | 410 if msg.endswith(b'\n'): |
408 msg = "[%s|%s]\n" % (label, msg[:-1]) | 411 msg = b"[%s|%s]\n" % (label, msg[:-1]) |
409 else: | 412 else: |
410 msg = "[%s|%s]" % (label, msg) | 413 msg = b"[%s|%s]" % (label, msg) |
411 elif ui._colormode is not None: | 414 elif ui._colormode is not None: |
412 effects = [] | 415 effects = [] |
413 for l in label.split(): | 416 for l in label.split(): |
414 s = ui._styles.get(l, '') | 417 s = ui._styles.get(l, b'') |
415 if s: | 418 if s: |
416 effects.append(s) | 419 effects.append(s) |
417 elif valideffect(ui, l): | 420 elif valideffect(ui, l): |
418 effects.append(l) | 421 effects.append(l) |
419 effects = ' '.join(effects) | 422 effects = b' '.join(effects) |
420 if effects: | 423 if effects: |
421 msg = '\n'.join( | 424 msg = b'\n'.join( |
422 [_render_effects(ui, line, effects) for line in msg.split('\n')] | 425 [ |
426 _render_effects(ui, line, effects) | |
427 for line in msg.split(b'\n') | |
428 ] | |
423 ) | 429 ) |
424 return msg | 430 return msg |
425 | 431 |
426 | 432 |
427 w32effects = None | 433 w32effects = None |
470 _COMMON_LVB_REVERSE_VIDEO = 0x4000 | 476 _COMMON_LVB_REVERSE_VIDEO = 0x4000 |
471 _COMMON_LVB_UNDERSCORE = 0x8000 | 477 _COMMON_LVB_UNDERSCORE = 0x8000 |
472 | 478 |
473 # http://msdn.microsoft.com/en-us/library/ms682088%28VS.85%29.aspx | 479 # http://msdn.microsoft.com/en-us/library/ms682088%28VS.85%29.aspx |
474 w32effects = { | 480 w32effects = { |
475 'none': -1, | 481 b'none': -1, |
476 'black': 0, | 482 b'black': 0, |
477 'red': _FOREGROUND_RED, | 483 b'red': _FOREGROUND_RED, |
478 'green': _FOREGROUND_GREEN, | 484 b'green': _FOREGROUND_GREEN, |
479 'yellow': _FOREGROUND_RED | _FOREGROUND_GREEN, | 485 b'yellow': _FOREGROUND_RED | _FOREGROUND_GREEN, |
480 'blue': _FOREGROUND_BLUE, | 486 b'blue': _FOREGROUND_BLUE, |
481 'magenta': _FOREGROUND_BLUE | _FOREGROUND_RED, | 487 b'magenta': _FOREGROUND_BLUE | _FOREGROUND_RED, |
482 'cyan': _FOREGROUND_BLUE | _FOREGROUND_GREEN, | 488 b'cyan': _FOREGROUND_BLUE | _FOREGROUND_GREEN, |
483 'white': _FOREGROUND_RED | _FOREGROUND_GREEN | _FOREGROUND_BLUE, | 489 b'white': _FOREGROUND_RED | _FOREGROUND_GREEN | _FOREGROUND_BLUE, |
484 'bold': _FOREGROUND_INTENSITY, | 490 b'bold': _FOREGROUND_INTENSITY, |
485 'black_background': 0x100, # unused value > 0x0f | 491 b'black_background': 0x100, # unused value > 0x0f |
486 'red_background': _BACKGROUND_RED, | 492 b'red_background': _BACKGROUND_RED, |
487 'green_background': _BACKGROUND_GREEN, | 493 b'green_background': _BACKGROUND_GREEN, |
488 'yellow_background': _BACKGROUND_RED | _BACKGROUND_GREEN, | 494 b'yellow_background': _BACKGROUND_RED | _BACKGROUND_GREEN, |
489 'blue_background': _BACKGROUND_BLUE, | 495 b'blue_background': _BACKGROUND_BLUE, |
490 'purple_background': _BACKGROUND_BLUE | _BACKGROUND_RED, | 496 b'purple_background': _BACKGROUND_BLUE | _BACKGROUND_RED, |
491 'cyan_background': _BACKGROUND_BLUE | _BACKGROUND_GREEN, | 497 b'cyan_background': _BACKGROUND_BLUE | _BACKGROUND_GREEN, |
492 'white_background': ( | 498 b'white_background': ( |
493 _BACKGROUND_RED | _BACKGROUND_GREEN | _BACKGROUND_BLUE | 499 _BACKGROUND_RED | _BACKGROUND_GREEN | _BACKGROUND_BLUE |
494 ), | 500 ), |
495 'bold_background': _BACKGROUND_INTENSITY, | 501 b'bold_background': _BACKGROUND_INTENSITY, |
496 'underline': _COMMON_LVB_UNDERSCORE, # double-byte charsets only | 502 b'underline': _COMMON_LVB_UNDERSCORE, # double-byte charsets only |
497 'inverse': _COMMON_LVB_REVERSE_VIDEO, # double-byte charsets only | 503 b'inverse': _COMMON_LVB_REVERSE_VIDEO, # double-byte charsets only |
498 } | 504 } |
499 | 505 |
500 passthrough = { | 506 passthrough = { |
501 _FOREGROUND_INTENSITY, | 507 _FOREGROUND_INTENSITY, |
502 _BACKGROUND_INTENSITY, | 508 _BACKGROUND_INTENSITY, |
520 ansire = re.compile( | 526 ansire = re.compile( |
521 br'\033\[([^m]*)m([^\033]*)(.*)', re.MULTILINE | re.DOTALL | 527 br'\033\[([^m]*)m([^\033]*)(.*)', re.MULTILINE | re.DOTALL |
522 ) | 528 ) |
523 | 529 |
524 def win32print(ui, writefunc, text, **opts): | 530 def win32print(ui, writefunc, text, **opts): |
525 label = opts.get(r'label', '') | 531 label = opts.get(r'label', b'') |
526 attr = origattr | 532 attr = origattr |
527 | 533 |
528 def mapcolor(val, attr): | 534 def mapcolor(val, attr): |
529 if val == -1: | 535 if val == -1: |
530 return origattr | 536 return origattr |
535 else: | 541 else: |
536 return (val & 0x07) | (attr & 0xF8) | 542 return (val & 0x07) | (attr & 0xF8) |
537 | 543 |
538 # determine console attributes based on labels | 544 # determine console attributes based on labels |
539 for l in label.split(): | 545 for l in label.split(): |
540 style = ui._styles.get(l, '') | 546 style = ui._styles.get(l, b'') |
541 for effect in style.split(): | 547 for effect in style.split(): |
542 try: | 548 try: |
543 attr = mapcolor(w32effects[effect], attr) | 549 attr = mapcolor(w32effects[effect], attr) |
544 except KeyError: | 550 except KeyError: |
545 # w32effects could not have certain attributes so we skip | 551 # w32effects could not have certain attributes so we skip |