Show More
@@ -263,7 +263,7 b' def _modesetup(ui, coloropt):' | |||
|
263 | 263 | # gibberish, we error on the side of selecting "win32". However, if |
|
264 | 264 | # w32effects is not defined, we almost certainly don't support |
|
265 | 265 | # "win32", so don't even try. |
|
266 | if (term and 'xterm' in term) or not w32effects: | |
|
266 | if (term and 'xterm' in term) or not color.w32effects: | |
|
267 | 267 | realmode = 'ansi' |
|
268 | 268 | else: |
|
269 | 269 | realmode = 'win32' |
@@ -278,10 +278,10 b' def _modesetup(ui, coloropt):' | |||
|
278 | 278 | |
|
279 | 279 | if realmode == 'win32': |
|
280 | 280 | color._terminfo_params.clear() |
|
281 | if not w32effects: | |
|
281 | if not color.w32effects: | |
|
282 | 282 | modewarn() |
|
283 | 283 | return None |
|
284 | color._effects.update(w32effects) | |
|
284 | color._effects.update(color.w32effects) | |
|
285 | 285 | elif realmode == 'ansi': |
|
286 | 286 | color._terminfo_params.clear() |
|
287 | 287 | elif realmode == 'terminfo': |
@@ -311,7 +311,7 b' class colorui(uimod.ui):' | |||
|
311 | 311 | self._buffers[-1].extend(args) |
|
312 | 312 | elif self._colormode == 'win32': |
|
313 | 313 | for a in args: |
|
314 | win32print(a, super(colorui, self).write, **opts) | |
|
314 | color.win32print(a, super(colorui, self).write, **opts) | |
|
315 | 315 | else: |
|
316 | 316 | return super(colorui, self).write( |
|
317 | 317 | *[self.label(a, label) for a in args], **opts) |
@@ -325,7 +325,7 b' class colorui(uimod.ui):' | |||
|
325 | 325 | return self.write(*args, **opts) |
|
326 | 326 | if self._colormode == 'win32': |
|
327 | 327 | for a in args: |
|
328 | win32print(a, super(colorui, self).write_err, **opts) | |
|
328 | color.win32print(a, super(colorui, self).write_err, **opts) | |
|
329 | 329 | else: |
|
330 | 330 | return super(colorui, self).write_err( |
|
331 | 331 | *[self.label(a, label) for a in args], **opts) |
@@ -432,138 +432,3 b' def _debugdisplaystyle(ui):' | |||
|
432 | 432 | ui.write(' ' * (max(0, width - len(label)))) |
|
433 | 433 | ui.write(', '.join(ui.label(e, e) for e in effects.split())) |
|
434 | 434 | ui.write('\n') |
|
435 | ||
|
436 | if pycompat.osname != 'nt': | |
|
437 | w32effects = None | |
|
438 | else: | |
|
439 | import ctypes | |
|
440 | import re | |
|
441 | ||
|
442 | _kernel32 = ctypes.windll.kernel32 | |
|
443 | ||
|
444 | _WORD = ctypes.c_ushort | |
|
445 | ||
|
446 | _INVALID_HANDLE_VALUE = -1 | |
|
447 | ||
|
448 | class _COORD(ctypes.Structure): | |
|
449 | _fields_ = [('X', ctypes.c_short), | |
|
450 | ('Y', ctypes.c_short)] | |
|
451 | ||
|
452 | class _SMALL_RECT(ctypes.Structure): | |
|
453 | _fields_ = [('Left', ctypes.c_short), | |
|
454 | ('Top', ctypes.c_short), | |
|
455 | ('Right', ctypes.c_short), | |
|
456 | ('Bottom', ctypes.c_short)] | |
|
457 | ||
|
458 | class _CONSOLE_SCREEN_BUFFER_INFO(ctypes.Structure): | |
|
459 | _fields_ = [('dwSize', _COORD), | |
|
460 | ('dwCursorPosition', _COORD), | |
|
461 | ('wAttributes', _WORD), | |
|
462 | ('srWindow', _SMALL_RECT), | |
|
463 | ('dwMaximumWindowSize', _COORD)] | |
|
464 | ||
|
465 | _STD_OUTPUT_HANDLE = 0xfffffff5 # (DWORD)-11 | |
|
466 | _STD_ERROR_HANDLE = 0xfffffff4 # (DWORD)-12 | |
|
467 | ||
|
468 | _FOREGROUND_BLUE = 0x0001 | |
|
469 | _FOREGROUND_GREEN = 0x0002 | |
|
470 | _FOREGROUND_RED = 0x0004 | |
|
471 | _FOREGROUND_INTENSITY = 0x0008 | |
|
472 | ||
|
473 | _BACKGROUND_BLUE = 0x0010 | |
|
474 | _BACKGROUND_GREEN = 0x0020 | |
|
475 | _BACKGROUND_RED = 0x0040 | |
|
476 | _BACKGROUND_INTENSITY = 0x0080 | |
|
477 | ||
|
478 | _COMMON_LVB_REVERSE_VIDEO = 0x4000 | |
|
479 | _COMMON_LVB_UNDERSCORE = 0x8000 | |
|
480 | ||
|
481 | # http://msdn.microsoft.com/en-us/library/ms682088%28VS.85%29.aspx | |
|
482 | w32effects = { | |
|
483 | 'none': -1, | |
|
484 | 'black': 0, | |
|
485 | 'red': _FOREGROUND_RED, | |
|
486 | 'green': _FOREGROUND_GREEN, | |
|
487 | 'yellow': _FOREGROUND_RED | _FOREGROUND_GREEN, | |
|
488 | 'blue': _FOREGROUND_BLUE, | |
|
489 | 'magenta': _FOREGROUND_BLUE | _FOREGROUND_RED, | |
|
490 | 'cyan': _FOREGROUND_BLUE | _FOREGROUND_GREEN, | |
|
491 | 'white': _FOREGROUND_RED | _FOREGROUND_GREEN | _FOREGROUND_BLUE, | |
|
492 | 'bold': _FOREGROUND_INTENSITY, | |
|
493 | 'black_background': 0x100, # unused value > 0x0f | |
|
494 | 'red_background': _BACKGROUND_RED, | |
|
495 | 'green_background': _BACKGROUND_GREEN, | |
|
496 | 'yellow_background': _BACKGROUND_RED | _BACKGROUND_GREEN, | |
|
497 | 'blue_background': _BACKGROUND_BLUE, | |
|
498 | 'purple_background': _BACKGROUND_BLUE | _BACKGROUND_RED, | |
|
499 | 'cyan_background': _BACKGROUND_BLUE | _BACKGROUND_GREEN, | |
|
500 | 'white_background': (_BACKGROUND_RED | _BACKGROUND_GREEN | | |
|
501 | _BACKGROUND_BLUE), | |
|
502 | 'bold_background': _BACKGROUND_INTENSITY, | |
|
503 | 'underline': _COMMON_LVB_UNDERSCORE, # double-byte charsets only | |
|
504 | 'inverse': _COMMON_LVB_REVERSE_VIDEO, # double-byte charsets only | |
|
505 | } | |
|
506 | ||
|
507 | passthrough = set([_FOREGROUND_INTENSITY, | |
|
508 | _BACKGROUND_INTENSITY, | |
|
509 | _COMMON_LVB_UNDERSCORE, | |
|
510 | _COMMON_LVB_REVERSE_VIDEO]) | |
|
511 | ||
|
512 | stdout = _kernel32.GetStdHandle( | |
|
513 | _STD_OUTPUT_HANDLE) # don't close the handle returned | |
|
514 | if stdout is None or stdout == _INVALID_HANDLE_VALUE: | |
|
515 | w32effects = None | |
|
516 | else: | |
|
517 | csbi = _CONSOLE_SCREEN_BUFFER_INFO() | |
|
518 | if not _kernel32.GetConsoleScreenBufferInfo( | |
|
519 | stdout, ctypes.byref(csbi)): | |
|
520 | # stdout may not support GetConsoleScreenBufferInfo() | |
|
521 | # when called from subprocess or redirected | |
|
522 | w32effects = None | |
|
523 | else: | |
|
524 | origattr = csbi.wAttributes | |
|
525 | ansire = re.compile('\033\[([^m]*)m([^\033]*)(.*)', | |
|
526 | re.MULTILINE | re.DOTALL) | |
|
527 | ||
|
528 | def win32print(text, orig, **opts): | |
|
529 | label = opts.get('label', '') | |
|
530 | attr = origattr | |
|
531 | ||
|
532 | def mapcolor(val, attr): | |
|
533 | if val == -1: | |
|
534 | return origattr | |
|
535 | elif val in passthrough: | |
|
536 | return attr | val | |
|
537 | elif val > 0x0f: | |
|
538 | return (val & 0x70) | (attr & 0x8f) | |
|
539 | else: | |
|
540 | return (val & 0x07) | (attr & 0xf8) | |
|
541 | ||
|
542 | # determine console attributes based on labels | |
|
543 | for l in label.split(): | |
|
544 | style = color._styles.get(l, '') | |
|
545 | for effect in style.split(): | |
|
546 | try: | |
|
547 | attr = mapcolor(w32effects[effect], attr) | |
|
548 | except KeyError: | |
|
549 | # w32effects could not have certain attributes so we skip | |
|
550 | # them if not found | |
|
551 | pass | |
|
552 | # hack to ensure regexp finds data | |
|
553 | if not text.startswith('\033['): | |
|
554 | text = '\033[m' + text | |
|
555 | ||
|
556 | # Look for ANSI-like codes embedded in text | |
|
557 | m = re.match(ansire, text) | |
|
558 | ||
|
559 | try: | |
|
560 | while m: | |
|
561 | for sattr in m.group(1).split(';'): | |
|
562 | if sattr: | |
|
563 | attr = mapcolor(int(sattr), attr) | |
|
564 | _kernel32.SetConsoleTextAttribute(stdout, attr) | |
|
565 | orig(m.group(2), **opts) | |
|
566 | m = re.match(ansire, m.group(3)) | |
|
567 | finally: | |
|
568 | # Explicitly reset original attributes | |
|
569 | _kernel32.SetConsoleTextAttribute(stdout, origattr) |
@@ -9,6 +9,8 b' from __future__ import absolute_import' | |||
|
9 | 9 | |
|
10 | 10 | from .i18n import _ |
|
11 | 11 | |
|
12 | from . import pycompat | |
|
13 | ||
|
12 | 14 | try: |
|
13 | 15 | import curses |
|
14 | 16 | # Mapping from effect name to terminfo attribute name (or raw code) or |
@@ -172,3 +174,137 b' def _render_effects(text, effects):' | |||
|
172 | 174 | for effect in ['none'] + effects.split()) |
|
173 | 175 | stop = _effect_str('none') |
|
174 | 176 | return ''.join([start, text, stop]) |
|
177 | ||
|
178 | w32effects = None | |
|
179 | if pycompat.osname == 'nt': | |
|
180 | import ctypes | |
|
181 | import re | |
|
182 | ||
|
183 | _kernel32 = ctypes.windll.kernel32 | |
|
184 | ||
|
185 | _WORD = ctypes.c_ushort | |
|
186 | ||
|
187 | _INVALID_HANDLE_VALUE = -1 | |
|
188 | ||
|
189 | class _COORD(ctypes.Structure): | |
|
190 | _fields_ = [('X', ctypes.c_short), | |
|
191 | ('Y', ctypes.c_short)] | |
|
192 | ||
|
193 | class _SMALL_RECT(ctypes.Structure): | |
|
194 | _fields_ = [('Left', ctypes.c_short), | |
|
195 | ('Top', ctypes.c_short), | |
|
196 | ('Right', ctypes.c_short), | |
|
197 | ('Bottom', ctypes.c_short)] | |
|
198 | ||
|
199 | class _CONSOLE_SCREEN_BUFFER_INFO(ctypes.Structure): | |
|
200 | _fields_ = [('dwSize', _COORD), | |
|
201 | ('dwCursorPosition', _COORD), | |
|
202 | ('wAttributes', _WORD), | |
|
203 | ('srWindow', _SMALL_RECT), | |
|
204 | ('dwMaximumWindowSize', _COORD)] | |
|
205 | ||
|
206 | _STD_OUTPUT_HANDLE = 0xfffffff5 # (DWORD)-11 | |
|
207 | _STD_ERROR_HANDLE = 0xfffffff4 # (DWORD)-12 | |
|
208 | ||
|
209 | _FOREGROUND_BLUE = 0x0001 | |
|
210 | _FOREGROUND_GREEN = 0x0002 | |
|
211 | _FOREGROUND_RED = 0x0004 | |
|
212 | _FOREGROUND_INTENSITY = 0x0008 | |
|
213 | ||
|
214 | _BACKGROUND_BLUE = 0x0010 | |
|
215 | _BACKGROUND_GREEN = 0x0020 | |
|
216 | _BACKGROUND_RED = 0x0040 | |
|
217 | _BACKGROUND_INTENSITY = 0x0080 | |
|
218 | ||
|
219 | _COMMON_LVB_REVERSE_VIDEO = 0x4000 | |
|
220 | _COMMON_LVB_UNDERSCORE = 0x8000 | |
|
221 | ||
|
222 | # http://msdn.microsoft.com/en-us/library/ms682088%28VS.85%29.aspx | |
|
223 | w32effects = { | |
|
224 | 'none': -1, | |
|
225 | 'black': 0, | |
|
226 | 'red': _FOREGROUND_RED, | |
|
227 | 'green': _FOREGROUND_GREEN, | |
|
228 | 'yellow': _FOREGROUND_RED | _FOREGROUND_GREEN, | |
|
229 | 'blue': _FOREGROUND_BLUE, | |
|
230 | 'magenta': _FOREGROUND_BLUE | _FOREGROUND_RED, | |
|
231 | 'cyan': _FOREGROUND_BLUE | _FOREGROUND_GREEN, | |
|
232 | 'white': _FOREGROUND_RED | _FOREGROUND_GREEN | _FOREGROUND_BLUE, | |
|
233 | 'bold': _FOREGROUND_INTENSITY, | |
|
234 | 'black_background': 0x100, # unused value > 0x0f | |
|
235 | 'red_background': _BACKGROUND_RED, | |
|
236 | 'green_background': _BACKGROUND_GREEN, | |
|
237 | 'yellow_background': _BACKGROUND_RED | _BACKGROUND_GREEN, | |
|
238 | 'blue_background': _BACKGROUND_BLUE, | |
|
239 | 'purple_background': _BACKGROUND_BLUE | _BACKGROUND_RED, | |
|
240 | 'cyan_background': _BACKGROUND_BLUE | _BACKGROUND_GREEN, | |
|
241 | 'white_background': (_BACKGROUND_RED | _BACKGROUND_GREEN | | |
|
242 | _BACKGROUND_BLUE), | |
|
243 | 'bold_background': _BACKGROUND_INTENSITY, | |
|
244 | 'underline': _COMMON_LVB_UNDERSCORE, # double-byte charsets only | |
|
245 | 'inverse': _COMMON_LVB_REVERSE_VIDEO, # double-byte charsets only | |
|
246 | } | |
|
247 | ||
|
248 | passthrough = set([_FOREGROUND_INTENSITY, | |
|
249 | _BACKGROUND_INTENSITY, | |
|
250 | _COMMON_LVB_UNDERSCORE, | |
|
251 | _COMMON_LVB_REVERSE_VIDEO]) | |
|
252 | ||
|
253 | stdout = _kernel32.GetStdHandle( | |
|
254 | _STD_OUTPUT_HANDLE) # don't close the handle returned | |
|
255 | if stdout is None or stdout == _INVALID_HANDLE_VALUE: | |
|
256 | w32effects = None | |
|
257 | else: | |
|
258 | csbi = _CONSOLE_SCREEN_BUFFER_INFO() | |
|
259 | if not _kernel32.GetConsoleScreenBufferInfo( | |
|
260 | stdout, ctypes.byref(csbi)): | |
|
261 | # stdout may not support GetConsoleScreenBufferInfo() | |
|
262 | # when called from subprocess or redirected | |
|
263 | w32effects = None | |
|
264 | else: | |
|
265 | origattr = csbi.wAttributes | |
|
266 | ansire = re.compile('\033\[([^m]*)m([^\033]*)(.*)', | |
|
267 | re.MULTILINE | re.DOTALL) | |
|
268 | ||
|
269 | def win32print(text, orig, **opts): | |
|
270 | label = opts.get('label', '') | |
|
271 | attr = origattr | |
|
272 | ||
|
273 | def mapcolor(val, attr): | |
|
274 | if val == -1: | |
|
275 | return origattr | |
|
276 | elif val in passthrough: | |
|
277 | return attr | val | |
|
278 | elif val > 0x0f: | |
|
279 | return (val & 0x70) | (attr & 0x8f) | |
|
280 | else: | |
|
281 | return (val & 0x07) | (attr & 0xf8) | |
|
282 | ||
|
283 | # determine console attributes based on labels | |
|
284 | for l in label.split(): | |
|
285 | style = _styles.get(l, '') | |
|
286 | for effect in style.split(): | |
|
287 | try: | |
|
288 | attr = mapcolor(w32effects[effect], attr) | |
|
289 | except KeyError: | |
|
290 | # w32effects could not have certain attributes so we skip | |
|
291 | # them if not found | |
|
292 | pass | |
|
293 | # hack to ensure regexp finds data | |
|
294 | if not text.startswith('\033['): | |
|
295 | text = '\033[m' + text | |
|
296 | ||
|
297 | # Look for ANSI-like codes embedded in text | |
|
298 | m = re.match(ansire, text) | |
|
299 | ||
|
300 | try: | |
|
301 | while m: | |
|
302 | for sattr in m.group(1).split(';'): | |
|
303 | if sattr: | |
|
304 | attr = mapcolor(int(sattr), attr) | |
|
305 | _kernel32.SetConsoleTextAttribute(stdout, attr) | |
|
306 | orig(m.group(2), **opts) | |
|
307 | m = re.match(ansire, m.group(3)) | |
|
308 | finally: | |
|
309 | # Explicitly reset original attributes | |
|
310 | _kernel32.SetConsoleTextAttribute(stdout, origattr) |
General Comments 0
You need to be logged in to leave comments.
Login now