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