Mercurial > hg
comparison mercurial/color.py @ 43076:2372284d9457
formatting: blacken the codebase
This is using my patch to black
(https://github.com/psf/black/pull/826) so we don't un-wrap collection
literals.
Done with:
hg files 'set:**.py - mercurial/thirdparty/** - "contrib/python-zstandard/**"' | xargs black -S
# skip-blame mass-reformatting only
# no-check-commit reformats foo_bar functions
Differential Revision: https://phab.mercurial-scm.org/D6971
author | Augie Fackler <augie@google.com> |
---|---|
date | Sun, 06 Oct 2019 09:45:02 -0400 |
parents | a91615b71679 |
children | 687b865b95ad |
comparison
equal
deleted
inserted
replaced
43075:57875cf423c9 | 43076:2372284d9457 |
---|---|
14 from . import ( | 14 from . import ( |
15 encoding, | 15 encoding, |
16 pycompat, | 16 pycompat, |
17 ) | 17 ) |
18 | 18 |
19 from .utils import ( | 19 from .utils import stringutil |
20 stringutil, | |
21 ) | |
22 | 20 |
23 try: | 21 try: |
24 import curses | 22 import curses |
23 | |
25 # 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 |
26 # color number. This will also force-load the curses module. | 25 # color number. This will also force-load the curses module. |
27 _baseterminfoparams = { | 26 _baseterminfoparams = { |
28 'none': (True, 'sgr0', ''), | 27 'none': (True, 'sgr0', ''), |
29 'standout': (True, 'smso', ''), | 28 'standout': (True, 'smso', ''), |
70 'yellow_background': 43, | 69 'yellow_background': 43, |
71 'blue_background': 44, | 70 'blue_background': 44, |
72 'purple_background': 45, | 71 'purple_background': 45, |
73 'cyan_background': 46, | 72 'cyan_background': 46, |
74 'white_background': 47, | 73 'white_background': 47, |
75 } | 74 } |
76 | 75 |
77 _defaultstyles = { | 76 _defaultstyles = { |
78 'grep.match': 'red bold', | 77 'grep.match': 'red bold', |
79 'grep.linenumber': 'green', | 78 'grep.linenumber': 'green', |
80 'grep.rev': 'blue', | 79 'grep.rev': 'blue', |
145 'status.unknown': 'magenta bold underline', | 144 'status.unknown': 'magenta bold underline', |
146 'tags.normal': 'green', | 145 'tags.normal': 'green', |
147 'tags.local': 'black bold', | 146 'tags.local': 'black bold', |
148 } | 147 } |
149 | 148 |
149 | |
150 def loadcolortable(ui, extname, colortable): | 150 def loadcolortable(ui, extname, colortable): |
151 _defaultstyles.update(colortable) | 151 _defaultstyles.update(colortable) |
152 | |
152 | 153 |
153 def _terminfosetup(ui, mode, formatted): | 154 def _terminfosetup(ui, mode, formatted): |
154 '''Initialize terminfo data and the terminal if we're in terminfo mode.''' | 155 '''Initialize terminfo data and the terminal if we're in terminfo mode.''' |
155 | 156 |
156 # If we failed to load curses, we go ahead and return. | 157 # If we failed to load curses, we go ahead and return. |
184 del ui._terminfoparams[key] | 185 del ui._terminfoparams[key] |
185 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'): |
186 # Only warn about missing terminfo entries if we explicitly asked for | 187 # Only warn about missing terminfo entries if we explicitly asked for |
187 # terminfo mode and we're in a formatted terminal. | 188 # terminfo mode and we're in a formatted terminal. |
188 if mode == "terminfo" and formatted: | 189 if mode == "terminfo" and formatted: |
189 ui.warn(_("no terminfo entry for setab/setaf: reverting to " | 190 ui.warn( |
190 "ECMA-48 color\n")) | 191 _( |
192 "no terminfo entry for setab/setaf: reverting to " | |
193 "ECMA-48 color\n" | |
194 ) | |
195 ) | |
191 ui._terminfoparams.clear() | 196 ui._terminfoparams.clear() |
197 | |
192 | 198 |
193 def setup(ui): | 199 def setup(ui): |
194 """configure color on a ui | 200 """configure color on a ui |
195 | 201 |
196 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 |
198 mode = _modesetup(ui) | 204 mode = _modesetup(ui) |
199 ui._colormode = mode | 205 ui._colormode = mode |
200 if mode and mode != 'debug': | 206 if mode and mode != 'debug': |
201 configstyles(ui) | 207 configstyles(ui) |
202 | 208 |
209 | |
203 def _modesetup(ui): | 210 def _modesetup(ui): |
204 if ui.plain('color'): | 211 if ui.plain('color'): |
205 return None | 212 return None |
206 config = ui.config('ui', 'color') | 213 config = ui.config('ui', 'color') |
207 if config == 'debug': | 214 if config == 'debug': |
208 return 'debug' | 215 return 'debug' |
209 | 216 |
210 auto = (config == 'auto') | 217 auto = config == 'auto' |
211 always = False | 218 always = False |
212 if not auto and stringutil.parsebool(config): | 219 if not auto and stringutil.parsebool(config): |
213 # 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, |
214 # 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. |
215 if ui.configsource('ui', 'color') == '--color' or config == 'always': | 222 if ui.configsource('ui', 'color') == '--color' or config == 'always': |
218 auto = True | 225 auto = True |
219 | 226 |
220 if not always and not auto: | 227 if not always and not auto: |
221 return None | 228 return None |
222 | 229 |
223 formatted = (always or (encoding.environ.get('TERM') != 'dumb' | 230 formatted = always or ( |
224 and ui.formatted())) | 231 encoding.environ.get('TERM') != 'dumb' and ui.formatted() |
232 ) | |
225 | 233 |
226 mode = ui.config('color', 'mode') | 234 mode = ui.config('color', 'mode') |
227 | 235 |
228 # If pager is active, color.pagermode overrides color.mode. | 236 # If pager is active, color.pagermode overrides color.mode. |
229 if getattr(ui, 'pageractive', False): | 237 if getattr(ui, 'pageractive', False): |
283 | 291 |
284 if always or (auto and formatted): | 292 if always or (auto and formatted): |
285 return realmode | 293 return realmode |
286 return None | 294 return None |
287 | 295 |
296 | |
288 def configstyles(ui): | 297 def configstyles(ui): |
289 ui._styles.update(_defaultstyles) | 298 ui._styles.update(_defaultstyles) |
290 for status, cfgeffects in ui.configitems('color'): | 299 for status, cfgeffects in ui.configitems('color'): |
291 if '.' not in status or status.startswith(('color.', 'terminfo.')): | 300 if '.' not in status or status.startswith(('color.', 'terminfo.')): |
292 continue | 301 continue |
295 good = [] | 304 good = [] |
296 for e in cfgeffects: | 305 for e in cfgeffects: |
297 if valideffect(ui, e): | 306 if valideffect(ui, e): |
298 good.append(e) | 307 good.append(e) |
299 else: | 308 else: |
300 ui.warn(_("ignoring unknown color/effect %s " | 309 ui.warn( |
301 "(configured in color.%s)\n") | 310 _( |
302 % (stringutil.pprint(e), status)) | 311 "ignoring unknown color/effect %s " |
312 "(configured in color.%s)\n" | |
313 ) | |
314 % (stringutil.pprint(e), status) | |
315 ) | |
303 ui._styles[status] = ' '.join(good) | 316 ui._styles[status] = ' '.join(good) |
317 | |
304 | 318 |
305 def _activeeffects(ui): | 319 def _activeeffects(ui): |
306 '''Return the effects map for the color mode set on the ui.''' | 320 '''Return the effects map for the color mode set on the ui.''' |
307 if ui._colormode == 'win32': | 321 if ui._colormode == 'win32': |
308 return w32effects | 322 return w32effects |
309 elif ui._colormode is not None: | 323 elif ui._colormode is not None: |
310 return _effects | 324 return _effects |
311 return {} | 325 return {} |
312 | 326 |
327 | |
313 def valideffect(ui, effect): | 328 def valideffect(ui, effect): |
314 'Determine if the effect is valid or not.' | 329 'Determine if the effect is valid or not.' |
315 return ((not ui._terminfoparams and effect in _activeeffects(ui)) | 330 return (not ui._terminfoparams and effect in _activeeffects(ui)) or ( |
316 or (effect in ui._terminfoparams | 331 effect in ui._terminfoparams or effect[:-11] in ui._terminfoparams |
317 or effect[:-11] in ui._terminfoparams)) | 332 ) |
333 | |
318 | 334 |
319 def _effect_str(ui, effect): | 335 def _effect_str(ui, effect): |
320 '''Helper function for render_effects().''' | 336 '''Helper function for render_effects().''' |
321 | 337 |
322 bg = False | 338 bg = False |
335 elif bg: | 351 elif bg: |
336 return curses.tparm(curses.tigetstr(r'setab'), val) | 352 return curses.tparm(curses.tigetstr(r'setab'), val) |
337 else: | 353 else: |
338 return curses.tparm(curses.tigetstr(r'setaf'), val) | 354 return curses.tparm(curses.tigetstr(r'setaf'), val) |
339 | 355 |
356 | |
340 def _mergeeffects(text, start, stop): | 357 def _mergeeffects(text, start, stop): |
341 """Insert start sequence at every occurrence of stop sequence | 358 """Insert start sequence at every occurrence of stop sequence |
342 | 359 |
343 >>> s = _mergeeffects(b'cyan', b'[C]', b'|') | 360 >>> s = _mergeeffects(b'cyan', b'[C]', b'|') |
344 >>> s = _mergeeffects(s + b'yellow', b'[Y]', b'|') | 361 >>> s = _mergeeffects(s + b'yellow', b'[Y]', b'|') |
352 if not t: | 369 if not t: |
353 continue | 370 continue |
354 parts.extend([start, t, stop]) | 371 parts.extend([start, t, stop]) |
355 return ''.join(parts) | 372 return ''.join(parts) |
356 | 373 |
374 | |
357 def _render_effects(ui, text, effects): | 375 def _render_effects(ui, text, effects): |
358 'Wrap text in commands to turn on each effect.' | 376 'Wrap text in commands to turn on each effect.' |
359 if not text: | 377 if not text: |
360 return text | 378 return text |
361 if ui._terminfoparams: | 379 if ui._terminfoparams: |
362 start = ''.join(_effect_str(ui, effect) | 380 start = ''.join( |
363 for effect in ['none'] + effects.split()) | 381 _effect_str(ui, effect) for effect in ['none'] + effects.split() |
382 ) | |
364 stop = _effect_str(ui, 'none') | 383 stop = _effect_str(ui, 'none') |
365 else: | 384 else: |
366 activeeffects = _activeeffects(ui) | 385 activeeffects = _activeeffects(ui) |
367 start = [pycompat.bytestr(activeeffects[e]) | 386 start = [ |
368 for e in ['none'] + effects.split()] | 387 pycompat.bytestr(activeeffects[e]) |
388 for e in ['none'] + effects.split() | |
389 ] | |
369 start = '\033[' + ';'.join(start) + 'm' | 390 start = '\033[' + ';'.join(start) + 'm' |
370 stop = '\033[' + pycompat.bytestr(activeeffects['none']) + 'm' | 391 stop = '\033[' + pycompat.bytestr(activeeffects['none']) + 'm' |
371 return _mergeeffects(text, start, stop) | 392 return _mergeeffects(text, start, stop) |
372 | 393 |
394 | |
373 _ansieffectre = re.compile(br'\x1b\[[0-9;]*m') | 395 _ansieffectre = re.compile(br'\x1b\[[0-9;]*m') |
396 | |
374 | 397 |
375 def stripeffects(text): | 398 def stripeffects(text): |
376 """Strip ANSI control codes which could be inserted by colorlabel()""" | 399 """Strip ANSI control codes which could be inserted by colorlabel()""" |
377 return _ansieffectre.sub('', text) | 400 return _ansieffectre.sub('', text) |
401 | |
378 | 402 |
379 def colorlabel(ui, msg, label): | 403 def colorlabel(ui, msg, label): |
380 """add color control code according to the mode""" | 404 """add color control code according to the mode""" |
381 if ui._colormode == 'debug': | 405 if ui._colormode == 'debug': |
382 if label and msg: | 406 if label and msg: |
392 effects.append(s) | 416 effects.append(s) |
393 elif valideffect(ui, l): | 417 elif valideffect(ui, l): |
394 effects.append(l) | 418 effects.append(l) |
395 effects = ' '.join(effects) | 419 effects = ' '.join(effects) |
396 if effects: | 420 if effects: |
397 msg = '\n'.join([_render_effects(ui, line, effects) | 421 msg = '\n'.join( |
398 for line in msg.split('\n')]) | 422 [_render_effects(ui, line, effects) for line in msg.split('\n')] |
423 ) | |
399 return msg | 424 return msg |
425 | |
400 | 426 |
401 w32effects = None | 427 w32effects = None |
402 if pycompat.iswindows: | 428 if pycompat.iswindows: |
403 import ctypes | 429 import ctypes |
404 | 430 |
407 _WORD = ctypes.c_ushort | 433 _WORD = ctypes.c_ushort |
408 | 434 |
409 _INVALID_HANDLE_VALUE = -1 | 435 _INVALID_HANDLE_VALUE = -1 |
410 | 436 |
411 class _COORD(ctypes.Structure): | 437 class _COORD(ctypes.Structure): |
412 _fields_ = [(r'X', ctypes.c_short), | 438 _fields_ = [(r'X', ctypes.c_short), (r'Y', ctypes.c_short)] |
413 (r'Y', ctypes.c_short)] | |
414 | 439 |
415 class _SMALL_RECT(ctypes.Structure): | 440 class _SMALL_RECT(ctypes.Structure): |
416 _fields_ = [(r'Left', ctypes.c_short), | 441 _fields_ = [ |
417 (r'Top', ctypes.c_short), | 442 (r'Left', ctypes.c_short), |
418 (r'Right', ctypes.c_short), | 443 (r'Top', ctypes.c_short), |
419 (r'Bottom', ctypes.c_short)] | 444 (r'Right', ctypes.c_short), |
445 (r'Bottom', ctypes.c_short), | |
446 ] | |
420 | 447 |
421 class _CONSOLE_SCREEN_BUFFER_INFO(ctypes.Structure): | 448 class _CONSOLE_SCREEN_BUFFER_INFO(ctypes.Structure): |
422 _fields_ = [(r'dwSize', _COORD), | 449 _fields_ = [ |
423 (r'dwCursorPosition', _COORD), | 450 (r'dwSize', _COORD), |
424 (r'wAttributes', _WORD), | 451 (r'dwCursorPosition', _COORD), |
425 (r'srWindow', _SMALL_RECT), | 452 (r'wAttributes', _WORD), |
426 (r'dwMaximumWindowSize', _COORD)] | 453 (r'srWindow', _SMALL_RECT), |
427 | 454 (r'dwMaximumWindowSize', _COORD), |
428 _STD_OUTPUT_HANDLE = 0xfffffff5 # (DWORD)-11 | 455 ] |
429 _STD_ERROR_HANDLE = 0xfffffff4 # (DWORD)-12 | 456 |
457 _STD_OUTPUT_HANDLE = 0xFFFFFFF5 # (DWORD)-11 | |
458 _STD_ERROR_HANDLE = 0xFFFFFFF4 # (DWORD)-12 | |
430 | 459 |
431 _FOREGROUND_BLUE = 0x0001 | 460 _FOREGROUND_BLUE = 0x0001 |
432 _FOREGROUND_GREEN = 0x0002 | 461 _FOREGROUND_GREEN = 0x0002 |
433 _FOREGROUND_RED = 0x0004 | 462 _FOREGROUND_RED = 0x0004 |
434 _FOREGROUND_INTENSITY = 0x0008 | 463 _FOREGROUND_INTENSITY = 0x0008 |
451 'blue': _FOREGROUND_BLUE, | 480 'blue': _FOREGROUND_BLUE, |
452 'magenta': _FOREGROUND_BLUE | _FOREGROUND_RED, | 481 'magenta': _FOREGROUND_BLUE | _FOREGROUND_RED, |
453 'cyan': _FOREGROUND_BLUE | _FOREGROUND_GREEN, | 482 'cyan': _FOREGROUND_BLUE | _FOREGROUND_GREEN, |
454 'white': _FOREGROUND_RED | _FOREGROUND_GREEN | _FOREGROUND_BLUE, | 483 'white': _FOREGROUND_RED | _FOREGROUND_GREEN | _FOREGROUND_BLUE, |
455 'bold': _FOREGROUND_INTENSITY, | 484 'bold': _FOREGROUND_INTENSITY, |
456 'black_background': 0x100, # unused value > 0x0f | 485 'black_background': 0x100, # unused value > 0x0f |
457 'red_background': _BACKGROUND_RED, | 486 'red_background': _BACKGROUND_RED, |
458 'green_background': _BACKGROUND_GREEN, | 487 'green_background': _BACKGROUND_GREEN, |
459 'yellow_background': _BACKGROUND_RED | _BACKGROUND_GREEN, | 488 'yellow_background': _BACKGROUND_RED | _BACKGROUND_GREEN, |
460 'blue_background': _BACKGROUND_BLUE, | 489 'blue_background': _BACKGROUND_BLUE, |
461 'purple_background': _BACKGROUND_BLUE | _BACKGROUND_RED, | 490 'purple_background': _BACKGROUND_BLUE | _BACKGROUND_RED, |
462 'cyan_background': _BACKGROUND_BLUE | _BACKGROUND_GREEN, | 491 'cyan_background': _BACKGROUND_BLUE | _BACKGROUND_GREEN, |
463 'white_background': (_BACKGROUND_RED | _BACKGROUND_GREEN | | 492 'white_background': ( |
464 _BACKGROUND_BLUE), | 493 _BACKGROUND_RED | _BACKGROUND_GREEN | _BACKGROUND_BLUE |
494 ), | |
465 'bold_background': _BACKGROUND_INTENSITY, | 495 'bold_background': _BACKGROUND_INTENSITY, |
466 'underline': _COMMON_LVB_UNDERSCORE, # double-byte charsets only | 496 'underline': _COMMON_LVB_UNDERSCORE, # double-byte charsets only |
467 'inverse': _COMMON_LVB_REVERSE_VIDEO, # double-byte charsets only | 497 'inverse': _COMMON_LVB_REVERSE_VIDEO, # double-byte charsets only |
468 } | 498 } |
469 | 499 |
470 passthrough = {_FOREGROUND_INTENSITY, | 500 passthrough = { |
471 _BACKGROUND_INTENSITY, | 501 _FOREGROUND_INTENSITY, |
472 _COMMON_LVB_UNDERSCORE, | 502 _BACKGROUND_INTENSITY, |
473 _COMMON_LVB_REVERSE_VIDEO} | 503 _COMMON_LVB_UNDERSCORE, |
504 _COMMON_LVB_REVERSE_VIDEO, | |
505 } | |
474 | 506 |
475 stdout = _kernel32.GetStdHandle( | 507 stdout = _kernel32.GetStdHandle( |
476 _STD_OUTPUT_HANDLE) # don't close the handle returned | 508 _STD_OUTPUT_HANDLE |
509 ) # don't close the handle returned | |
477 if stdout is None or stdout == _INVALID_HANDLE_VALUE: | 510 if stdout is None or stdout == _INVALID_HANDLE_VALUE: |
478 w32effects = None | 511 w32effects = None |
479 else: | 512 else: |
480 csbi = _CONSOLE_SCREEN_BUFFER_INFO() | 513 csbi = _CONSOLE_SCREEN_BUFFER_INFO() |
481 if not _kernel32.GetConsoleScreenBufferInfo( | 514 if not _kernel32.GetConsoleScreenBufferInfo(stdout, ctypes.byref(csbi)): |
482 stdout, ctypes.byref(csbi)): | |
483 # stdout may not support GetConsoleScreenBufferInfo() | 515 # stdout may not support GetConsoleScreenBufferInfo() |
484 # when called from subprocess or redirected | 516 # when called from subprocess or redirected |
485 w32effects = None | 517 w32effects = None |
486 else: | 518 else: |
487 origattr = csbi.wAttributes | 519 origattr = csbi.wAttributes |
488 ansire = re.compile(br'\033\[([^m]*)m([^\033]*)(.*)', | 520 ansire = re.compile( |
489 re.MULTILINE | re.DOTALL) | 521 br'\033\[([^m]*)m([^\033]*)(.*)', re.MULTILINE | re.DOTALL |
522 ) | |
490 | 523 |
491 def win32print(ui, writefunc, text, **opts): | 524 def win32print(ui, writefunc, text, **opts): |
492 label = opts.get(r'label', '') | 525 label = opts.get(r'label', '') |
493 attr = origattr | 526 attr = origattr |
494 | 527 |
495 def mapcolor(val, attr): | 528 def mapcolor(val, attr): |
496 if val == -1: | 529 if val == -1: |
497 return origattr | 530 return origattr |
498 elif val in passthrough: | 531 elif val in passthrough: |
499 return attr | val | 532 return attr | val |
500 elif val > 0x0f: | 533 elif val > 0x0F: |
501 return (val & 0x70) | (attr & 0x8f) | 534 return (val & 0x70) | (attr & 0x8F) |
502 else: | 535 else: |
503 return (val & 0x07) | (attr & 0xf8) | 536 return (val & 0x07) | (attr & 0xF8) |
504 | 537 |
505 # determine console attributes based on labels | 538 # determine console attributes based on labels |
506 for l in label.split(): | 539 for l in label.split(): |
507 style = ui._styles.get(l, '') | 540 style = ui._styles.get(l, '') |
508 for effect in style.split(): | 541 for effect in style.split(): |