##// END OF EJS Templates
color: update docstring for debug option...
Jordi Gutiérrez Hermoso -
r22711:60ac52a2 default
parent child Browse files
Show More
@@ -1,629 +1,628
1 1 # color.py color output for the status and qseries commands
2 2 #
3 3 # Copyright (C) 2007 Kevin Christen <kevin.christen@gmail.com>
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 '''colorize output from some commands
9 9
10 10 This extension modifies the status and resolve commands to add color
11 11 to their output to reflect file status, the qseries command to add
12 12 color to reflect patch status (applied, unapplied, missing), and to
13 13 diff-related commands to highlight additions, removals, diff headers,
14 14 tabs, and trailing whitespace.
15 15
16 16 Other effects in addition to color, like bold and underlined text, are
17 17 also available. By default, the terminfo database is used to find the
18 18 terminal codes used to change color and effect. If terminfo is not
19 19 available, then effects are rendered with the ECMA-48 SGR control
20 20 function (aka ANSI escape codes).
21 21
22 22 Text receives color effects depending on the labels that it has. Many
23 23 default Mercurial commands emit labelled text. You can also define
24 24 your own labels in templates using the label function, see :hg:`help
25 25 templates`. A single portion of text may have more than one label. In
26 26 that case, effects given to the last label will override any other
27 27 effects. This includes the special "none" effect, which nullifies
28 28 other effects.
29 29
30 30 Labels are normally invisible. In order to see these labels and their
31 position in the text, use the global --color=debug option. In case of
32 multiple labels for the same text, the labels will be enclosed by
33 square brackets, e.g.
31 position in the text, use the global --color=debug option. The same
32 anchor text may be associated to multiple labels, e.g.
34 33
35 [log.changeset changeset.secret](changeset: 22611:6f0a53c8f587)
34 [log.changeset changeset.secret|changeset: 22611:6f0a53c8f587]
36 35
37 36 The following are the default effects for some default labels. Default
38 37 effects may be overridden from your configuration file::
39 38
40 39 [color]
41 40 status.modified = blue bold underline red_background
42 41 status.added = green bold
43 42 status.removed = red bold blue_background
44 43 status.deleted = cyan bold underline
45 44 status.unknown = magenta bold underline
46 45 status.ignored = black bold
47 46
48 47 # 'none' turns off all effects
49 48 status.clean = none
50 49 status.copied = none
51 50
52 51 qseries.applied = blue bold underline
53 52 qseries.unapplied = black bold
54 53 qseries.missing = red bold
55 54
56 55 diff.diffline = bold
57 56 diff.extended = cyan bold
58 57 diff.file_a = red bold
59 58 diff.file_b = green bold
60 59 diff.hunk = magenta
61 60 diff.deleted = red
62 61 diff.inserted = green
63 62 diff.changed = white
64 63 diff.tab =
65 64 diff.trailingwhitespace = bold red_background
66 65
67 66 # Blank so it inherits the style of the surrounding label
68 67 changeset.public =
69 68 changeset.draft =
70 69 changeset.secret =
71 70
72 71 resolve.unresolved = red bold
73 72 resolve.resolved = green bold
74 73
75 74 bookmarks.current = green
76 75
77 76 branches.active = none
78 77 branches.closed = black bold
79 78 branches.current = green
80 79 branches.inactive = none
81 80
82 81 tags.normal = green
83 82 tags.local = black bold
84 83
85 84 rebase.rebased = blue
86 85 rebase.remaining = red bold
87 86
88 87 shelve.age = cyan
89 88 shelve.newest = green bold
90 89 shelve.name = blue bold
91 90
92 91 histedit.remaining = red bold
93 92
94 93 The available effects in terminfo mode are 'blink', 'bold', 'dim',
95 94 'inverse', 'invisible', 'italic', 'standout', and 'underline'; in
96 95 ECMA-48 mode, the options are 'bold', 'inverse', 'italic', and
97 96 'underline'. How each is rendered depends on the terminal emulator.
98 97 Some may not be available for a given terminal type, and will be
99 98 silently ignored.
100 99
101 100 Note that on some systems, terminfo mode may cause problems when using
102 101 color with the pager extension and less -R. less with the -R option
103 102 will only display ECMA-48 color codes, and terminfo mode may sometimes
104 103 emit codes that less doesn't understand. You can work around this by
105 104 either using ansi mode (or auto mode), or by using less -r (which will
106 105 pass through all terminal control codes, not just color control
107 106 codes).
108 107
109 108 Because there are only eight standard colors, this module allows you
110 109 to define color names for other color slots which might be available
111 110 for your terminal type, assuming terminfo mode. For instance::
112 111
113 112 color.brightblue = 12
114 113 color.pink = 207
115 114 color.orange = 202
116 115
117 116 to set 'brightblue' to color slot 12 (useful for 16 color terminals
118 117 that have brighter colors defined in the upper eight) and, 'pink' and
119 118 'orange' to colors in 256-color xterm's default color cube. These
120 119 defined colors may then be used as any of the pre-defined eight,
121 120 including appending '_background' to set the background to that color.
122 121
123 122 By default, the color extension will use ANSI mode (or win32 mode on
124 123 Windows) if it detects a terminal. To override auto mode (to enable
125 124 terminfo mode, for example), set the following configuration option::
126 125
127 126 [color]
128 127 mode = terminfo
129 128
130 129 Any value other than 'ansi', 'win32', 'terminfo', or 'auto' will
131 130 disable color.
132 131 '''
133 132
134 133 import os
135 134
136 135 from mercurial import cmdutil, commands, dispatch, extensions, ui as uimod, util
137 136 from mercurial import templater, error
138 137 from mercurial.i18n import _
139 138
140 139 cmdtable = {}
141 140 command = cmdutil.command(cmdtable)
142 141 testedwith = 'internal'
143 142
144 143 # start and stop parameters for effects
145 144 _effects = {'none': 0, 'black': 30, 'red': 31, 'green': 32, 'yellow': 33,
146 145 'blue': 34, 'magenta': 35, 'cyan': 36, 'white': 37, 'bold': 1,
147 146 'italic': 3, 'underline': 4, 'inverse': 7,
148 147 'black_background': 40, 'red_background': 41,
149 148 'green_background': 42, 'yellow_background': 43,
150 149 'blue_background': 44, 'purple_background': 45,
151 150 'cyan_background': 46, 'white_background': 47}
152 151
153 152 def _terminfosetup(ui, mode):
154 153 '''Initialize terminfo data and the terminal if we're in terminfo mode.'''
155 154
156 155 global _terminfo_params
157 156 # If we failed to load curses, we go ahead and return.
158 157 if not _terminfo_params:
159 158 return
160 159 # Otherwise, see what the config file says.
161 160 if mode not in ('auto', 'terminfo'):
162 161 return
163 162
164 163 _terminfo_params.update((key[6:], (False, int(val)))
165 164 for key, val in ui.configitems('color')
166 165 if key.startswith('color.'))
167 166
168 167 try:
169 168 curses.setupterm()
170 169 except curses.error, e:
171 170 _terminfo_params = {}
172 171 return
173 172
174 173 for key, (b, e) in _terminfo_params.items():
175 174 if not b:
176 175 continue
177 176 if not curses.tigetstr(e):
178 177 # Most terminals don't support dim, invis, etc, so don't be
179 178 # noisy and use ui.debug().
180 179 ui.debug("no terminfo entry for %s\n" % e)
181 180 del _terminfo_params[key]
182 181 if not curses.tigetstr('setaf') or not curses.tigetstr('setab'):
183 182 # Only warn about missing terminfo entries if we explicitly asked for
184 183 # terminfo mode.
185 184 if mode == "terminfo":
186 185 ui.warn(_("no terminfo entry for setab/setaf: reverting to "
187 186 "ECMA-48 color\n"))
188 187 _terminfo_params = {}
189 188
190 189 def _modesetup(ui, coloropt):
191 190 global _terminfo_params
192 191
193 192 if coloropt == 'debug':
194 193 return 'debug'
195 194
196 195 auto = (coloropt == 'auto')
197 196 always = not auto and util.parsebool(coloropt)
198 197 if not always and not auto:
199 198 return None
200 199
201 200 formatted = always or (os.environ.get('TERM') != 'dumb' and ui.formatted())
202 201
203 202 mode = ui.config('color', 'mode', 'auto')
204 203 realmode = mode
205 204 if mode == 'auto':
206 205 if os.name == 'nt' and 'TERM' not in os.environ:
207 206 # looks line a cmd.exe console, use win32 API or nothing
208 207 realmode = 'win32'
209 208 else:
210 209 realmode = 'ansi'
211 210
212 211 if realmode == 'win32':
213 212 _terminfo_params = {}
214 213 if not w32effects:
215 214 if mode == 'win32':
216 215 # only warn if color.mode is explicitly set to win32
217 216 ui.warn(_('warning: failed to set color mode to %s\n') % mode)
218 217 return None
219 218 _effects.update(w32effects)
220 219 elif realmode == 'ansi':
221 220 _terminfo_params = {}
222 221 elif realmode == 'terminfo':
223 222 _terminfosetup(ui, mode)
224 223 if not _terminfo_params:
225 224 if mode == 'terminfo':
226 225 ## FIXME Shouldn't we return None in this case too?
227 226 # only warn if color.mode is explicitly set to win32
228 227 ui.warn(_('warning: failed to set color mode to %s\n') % mode)
229 228 realmode = 'ansi'
230 229 else:
231 230 return None
232 231
233 232 if always or (auto and formatted):
234 233 return realmode
235 234 return None
236 235
237 236 try:
238 237 import curses
239 238 # Mapping from effect name to terminfo attribute name or color number.
240 239 # This will also force-load the curses module.
241 240 _terminfo_params = {'none': (True, 'sgr0'),
242 241 'standout': (True, 'smso'),
243 242 'underline': (True, 'smul'),
244 243 'reverse': (True, 'rev'),
245 244 'inverse': (True, 'rev'),
246 245 'blink': (True, 'blink'),
247 246 'dim': (True, 'dim'),
248 247 'bold': (True, 'bold'),
249 248 'invisible': (True, 'invis'),
250 249 'italic': (True, 'sitm'),
251 250 'black': (False, curses.COLOR_BLACK),
252 251 'red': (False, curses.COLOR_RED),
253 252 'green': (False, curses.COLOR_GREEN),
254 253 'yellow': (False, curses.COLOR_YELLOW),
255 254 'blue': (False, curses.COLOR_BLUE),
256 255 'magenta': (False, curses.COLOR_MAGENTA),
257 256 'cyan': (False, curses.COLOR_CYAN),
258 257 'white': (False, curses.COLOR_WHITE)}
259 258 except ImportError:
260 259 _terminfo_params = {}
261 260
262 261 _styles = {'grep.match': 'red bold',
263 262 'grep.linenumber': 'green',
264 263 'grep.rev': 'green',
265 264 'grep.change': 'green',
266 265 'grep.sep': 'cyan',
267 266 'grep.filename': 'magenta',
268 267 'grep.user': 'magenta',
269 268 'grep.date': 'magenta',
270 269 'bookmarks.current': 'green',
271 270 'branches.active': 'none',
272 271 'branches.closed': 'black bold',
273 272 'branches.current': 'green',
274 273 'branches.inactive': 'none',
275 274 'diff.changed': 'white',
276 275 'diff.deleted': 'red',
277 276 'diff.diffline': 'bold',
278 277 'diff.extended': 'cyan bold',
279 278 'diff.file_a': 'red bold',
280 279 'diff.file_b': 'green bold',
281 280 'diff.hunk': 'magenta',
282 281 'diff.inserted': 'green',
283 282 'diff.tab': '',
284 283 'diff.trailingwhitespace': 'bold red_background',
285 284 'changeset.public' : '',
286 285 'changeset.draft' : '',
287 286 'changeset.secret' : '',
288 287 'diffstat.deleted': 'red',
289 288 'diffstat.inserted': 'green',
290 289 'histedit.remaining': 'red bold',
291 290 'ui.prompt': 'yellow',
292 291 'log.changeset': 'yellow',
293 292 'rebase.rebased': 'blue',
294 293 'rebase.remaining': 'red bold',
295 294 'resolve.resolved': 'green bold',
296 295 'resolve.unresolved': 'red bold',
297 296 'shelve.age': 'cyan',
298 297 'shelve.newest': 'green bold',
299 298 'shelve.name': 'blue bold',
300 299 'status.added': 'green bold',
301 300 'status.clean': 'none',
302 301 'status.copied': 'none',
303 302 'status.deleted': 'cyan bold underline',
304 303 'status.ignored': 'black bold',
305 304 'status.modified': 'blue bold',
306 305 'status.removed': 'red bold',
307 306 'status.unknown': 'magenta bold underline',
308 307 'tags.normal': 'green',
309 308 'tags.local': 'black bold'}
310 309
311 310
312 311 def _effect_str(effect):
313 312 '''Helper function for render_effects().'''
314 313
315 314 bg = False
316 315 if effect.endswith('_background'):
317 316 bg = True
318 317 effect = effect[:-11]
319 318 attr, val = _terminfo_params[effect]
320 319 if attr:
321 320 return curses.tigetstr(val)
322 321 elif bg:
323 322 return curses.tparm(curses.tigetstr('setab'), val)
324 323 else:
325 324 return curses.tparm(curses.tigetstr('setaf'), val)
326 325
327 326 def render_effects(text, effects):
328 327 'Wrap text in commands to turn on each effect.'
329 328 if not text:
330 329 return text
331 330 if not _terminfo_params:
332 331 start = [str(_effects[e]) for e in ['none'] + effects.split()]
333 332 start = '\033[' + ';'.join(start) + 'm'
334 333 stop = '\033[' + str(_effects['none']) + 'm'
335 334 else:
336 335 start = ''.join(_effect_str(effect)
337 336 for effect in ['none'] + effects.split())
338 337 stop = _effect_str('none')
339 338 return ''.join([start, text, stop])
340 339
341 340 def extstyles():
342 341 for name, ext in extensions.extensions():
343 342 _styles.update(getattr(ext, 'colortable', {}))
344 343
345 344 def valideffect(effect):
346 345 'Determine if the effect is valid or not.'
347 346 good = False
348 347 if not _terminfo_params and effect in _effects:
349 348 good = True
350 349 elif effect in _terminfo_params or effect[:-11] in _terminfo_params:
351 350 good = True
352 351 return good
353 352
354 353 def configstyles(ui):
355 354 for status, cfgeffects in ui.configitems('color'):
356 355 if '.' not in status or status.startswith('color.'):
357 356 continue
358 357 cfgeffects = ui.configlist('color', status)
359 358 if cfgeffects:
360 359 good = []
361 360 for e in cfgeffects:
362 361 if valideffect(e):
363 362 good.append(e)
364 363 else:
365 364 ui.warn(_("ignoring unknown color/effect %r "
366 365 "(configured in color.%s)\n")
367 366 % (e, status))
368 367 _styles[status] = ' '.join(good)
369 368
370 369 class colorui(uimod.ui):
371 370 def popbuffer(self, labeled=False):
372 371 if self._colormode is None:
373 372 return super(colorui, self).popbuffer(labeled)
374 373
375 374 self._bufferstates.pop()
376 375 if labeled:
377 376 return ''.join(self.label(a, label) for a, label
378 377 in self._buffers.pop())
379 378 return ''.join(a for a, label in self._buffers.pop())
380 379
381 380 _colormode = 'ansi'
382 381 def write(self, *args, **opts):
383 382 if self._colormode is None:
384 383 return super(colorui, self).write(*args, **opts)
385 384
386 385 label = opts.get('label', '')
387 386 if self._buffers:
388 387 self._buffers[-1].extend([(str(a), label) for a in args])
389 388 elif self._colormode == 'win32':
390 389 for a in args:
391 390 win32print(a, super(colorui, self).write, **opts)
392 391 else:
393 392 return super(colorui, self).write(
394 393 *[self.label(str(a), label) for a in args], **opts)
395 394
396 395 def write_err(self, *args, **opts):
397 396 if self._colormode is None:
398 397 return super(colorui, self).write_err(*args, **opts)
399 398
400 399 label = opts.get('label', '')
401 400 if self._bufferstates and self._bufferstates[-1]:
402 401 return self.write(*args, **opts)
403 402 if self._colormode == 'win32':
404 403 for a in args:
405 404 win32print(a, super(colorui, self).write_err, **opts)
406 405 else:
407 406 return super(colorui, self).write_err(
408 407 *[self.label(str(a), label) for a in args], **opts)
409 408
410 409 def showlabel(self, msg, label):
411 410 if label:
412 411 if msg and msg[-1] == '\n':
413 412 return "[%s|%s]\n" % (label, msg[:-1])
414 413 else:
415 414 return "[%s|%s]" % (label, msg)
416 415 else:
417 416 return msg
418 417
419 418 def label(self, msg, label):
420 419 if self._colormode is None:
421 420 return super(colorui, self).label(msg, label)
422 421
423 422 if self._colormode == 'debug':
424 423 return self.showlabel(msg, label)
425 424
426 425 effects = []
427 426 for l in label.split():
428 427 s = _styles.get(l, '')
429 428 if s:
430 429 effects.append(s)
431 430 elif valideffect(l):
432 431 effects.append(l)
433 432 effects = ' '.join(effects)
434 433 if effects:
435 434 return '\n'.join([render_effects(s, effects)
436 435 for s in msg.split('\n')])
437 436 return msg
438 437
439 438 def templatelabel(context, mapping, args):
440 439 if len(args) != 2:
441 440 # i18n: "label" is a keyword
442 441 raise error.ParseError(_("label expects two arguments"))
443 442
444 443 # add known effects to the mapping so symbols like 'red', 'bold',
445 444 # etc. don't need to be quoted
446 445 mapping.update(dict([(k, k) for k in _effects]))
447 446
448 447 thing = templater._evalifliteral(args[1], context, mapping)
449 448
450 449 # apparently, repo could be a string that is the favicon?
451 450 repo = mapping.get('repo', '')
452 451 if isinstance(repo, str):
453 452 return thing
454 453
455 454 label = templater._evalifliteral(args[0], context, mapping)
456 455
457 456 thing = templater.stringify(thing)
458 457 label = templater.stringify(label)
459 458
460 459 return repo.ui.label(thing, label)
461 460
462 461 def uisetup(ui):
463 462 if ui.plain():
464 463 return
465 464 if not isinstance(ui, colorui):
466 465 colorui.__bases__ = (ui.__class__,)
467 466 ui.__class__ = colorui
468 467 def colorcmd(orig, ui_, opts, cmd, cmdfunc):
469 468 mode = _modesetup(ui_, opts['color'])
470 469 colorui._colormode = mode
471 470 if mode and mode != 'debug':
472 471 extstyles()
473 472 configstyles(ui_)
474 473 return orig(ui_, opts, cmd, cmdfunc)
475 474 extensions.wrapfunction(dispatch, '_runcommand', colorcmd)
476 475 templater.funcs['label'] = templatelabel
477 476
478 477 def extsetup(ui):
479 478 commands.globalopts.append(
480 479 ('', 'color', 'auto',
481 480 # i18n: 'always', 'auto', 'never', and 'debug' are keywords
482 481 # and should not be translated
483 482 _("when to colorize (boolean, always, auto, never, or debug)"),
484 483 _('TYPE')))
485 484
486 485 @command('debugcolor', [], 'hg debugcolor')
487 486 def debugcolor(ui, repo, **opts):
488 487 global _styles
489 488 _styles = {}
490 489 for effect in _effects.keys():
491 490 _styles[effect] = effect
492 491 ui.write(('color mode: %s\n') % ui._colormode)
493 492 ui.write(_('available colors:\n'))
494 493 for label, colors in _styles.items():
495 494 ui.write(('%s\n') % colors, label=label)
496 495
497 496 if os.name != 'nt':
498 497 w32effects = None
499 498 else:
500 499 import re, ctypes
501 500
502 501 _kernel32 = ctypes.windll.kernel32
503 502
504 503 _WORD = ctypes.c_ushort
505 504
506 505 _INVALID_HANDLE_VALUE = -1
507 506
508 507 class _COORD(ctypes.Structure):
509 508 _fields_ = [('X', ctypes.c_short),
510 509 ('Y', ctypes.c_short)]
511 510
512 511 class _SMALL_RECT(ctypes.Structure):
513 512 _fields_ = [('Left', ctypes.c_short),
514 513 ('Top', ctypes.c_short),
515 514 ('Right', ctypes.c_short),
516 515 ('Bottom', ctypes.c_short)]
517 516
518 517 class _CONSOLE_SCREEN_BUFFER_INFO(ctypes.Structure):
519 518 _fields_ = [('dwSize', _COORD),
520 519 ('dwCursorPosition', _COORD),
521 520 ('wAttributes', _WORD),
522 521 ('srWindow', _SMALL_RECT),
523 522 ('dwMaximumWindowSize', _COORD)]
524 523
525 524 _STD_OUTPUT_HANDLE = 0xfffffff5L # (DWORD)-11
526 525 _STD_ERROR_HANDLE = 0xfffffff4L # (DWORD)-12
527 526
528 527 _FOREGROUND_BLUE = 0x0001
529 528 _FOREGROUND_GREEN = 0x0002
530 529 _FOREGROUND_RED = 0x0004
531 530 _FOREGROUND_INTENSITY = 0x0008
532 531
533 532 _BACKGROUND_BLUE = 0x0010
534 533 _BACKGROUND_GREEN = 0x0020
535 534 _BACKGROUND_RED = 0x0040
536 535 _BACKGROUND_INTENSITY = 0x0080
537 536
538 537 _COMMON_LVB_REVERSE_VIDEO = 0x4000
539 538 _COMMON_LVB_UNDERSCORE = 0x8000
540 539
541 540 # http://msdn.microsoft.com/en-us/library/ms682088%28VS.85%29.aspx
542 541 w32effects = {
543 542 'none': -1,
544 543 'black': 0,
545 544 'red': _FOREGROUND_RED,
546 545 'green': _FOREGROUND_GREEN,
547 546 'yellow': _FOREGROUND_RED | _FOREGROUND_GREEN,
548 547 'blue': _FOREGROUND_BLUE,
549 548 'magenta': _FOREGROUND_BLUE | _FOREGROUND_RED,
550 549 'cyan': _FOREGROUND_BLUE | _FOREGROUND_GREEN,
551 550 'white': _FOREGROUND_RED | _FOREGROUND_GREEN | _FOREGROUND_BLUE,
552 551 'bold': _FOREGROUND_INTENSITY,
553 552 'black_background': 0x100, # unused value > 0x0f
554 553 'red_background': _BACKGROUND_RED,
555 554 'green_background': _BACKGROUND_GREEN,
556 555 'yellow_background': _BACKGROUND_RED | _BACKGROUND_GREEN,
557 556 'blue_background': _BACKGROUND_BLUE,
558 557 'purple_background': _BACKGROUND_BLUE | _BACKGROUND_RED,
559 558 'cyan_background': _BACKGROUND_BLUE | _BACKGROUND_GREEN,
560 559 'white_background': (_BACKGROUND_RED | _BACKGROUND_GREEN |
561 560 _BACKGROUND_BLUE),
562 561 'bold_background': _BACKGROUND_INTENSITY,
563 562 'underline': _COMMON_LVB_UNDERSCORE, # double-byte charsets only
564 563 'inverse': _COMMON_LVB_REVERSE_VIDEO, # double-byte charsets only
565 564 }
566 565
567 566 passthrough = set([_FOREGROUND_INTENSITY,
568 567 _BACKGROUND_INTENSITY,
569 568 _COMMON_LVB_UNDERSCORE,
570 569 _COMMON_LVB_REVERSE_VIDEO])
571 570
572 571 stdout = _kernel32.GetStdHandle(
573 572 _STD_OUTPUT_HANDLE) # don't close the handle returned
574 573 if stdout is None or stdout == _INVALID_HANDLE_VALUE:
575 574 w32effects = None
576 575 else:
577 576 csbi = _CONSOLE_SCREEN_BUFFER_INFO()
578 577 if not _kernel32.GetConsoleScreenBufferInfo(
579 578 stdout, ctypes.byref(csbi)):
580 579 # stdout may not support GetConsoleScreenBufferInfo()
581 580 # when called from subprocess or redirected
582 581 w32effects = None
583 582 else:
584 583 origattr = csbi.wAttributes
585 584 ansire = re.compile('\033\[([^m]*)m([^\033]*)(.*)',
586 585 re.MULTILINE | re.DOTALL)
587 586
588 587 def win32print(text, orig, **opts):
589 588 label = opts.get('label', '')
590 589 attr = origattr
591 590
592 591 def mapcolor(val, attr):
593 592 if val == -1:
594 593 return origattr
595 594 elif val in passthrough:
596 595 return attr | val
597 596 elif val > 0x0f:
598 597 return (val & 0x70) | (attr & 0x8f)
599 598 else:
600 599 return (val & 0x07) | (attr & 0xf8)
601 600
602 601 # determine console attributes based on labels
603 602 for l in label.split():
604 603 style = _styles.get(l, '')
605 604 for effect in style.split():
606 605 try:
607 606 attr = mapcolor(w32effects[effect], attr)
608 607 except KeyError:
609 608 # w32effects could not have certain attributes so we skip
610 609 # them if not found
611 610 pass
612 611 # hack to ensure regexp finds data
613 612 if not text.startswith('\033['):
614 613 text = '\033[m' + text
615 614
616 615 # Look for ANSI-like codes embedded in text
617 616 m = re.match(ansire, text)
618 617
619 618 try:
620 619 while m:
621 620 for sattr in m.group(1).split(';'):
622 621 if sattr:
623 622 attr = mapcolor(int(sattr), attr)
624 623 _kernel32.SetConsoleTextAttribute(stdout, attr)
625 624 orig(m.group(2), **opts)
626 625 m = re.match(ansire, m.group(3))
627 626 finally:
628 627 # Explicitly reset original attributes
629 628 _kernel32.SetConsoleTextAttribute(stdout, origattr)
General Comments 0
You need to be logged in to leave comments. Login now