Mercurial > hg
comparison hgext/color.py @ 30968:0d2a58a04080
color: move '_terminfo_params' into the core 'color' module
On step closer to have color in core.
author | Pierre-Yves David <pierre-yves.david@ens-lyon.org> |
---|---|
date | Thu, 22 Dec 2016 02:23:23 +0100 |
parents | 20990991d384 |
children | ddc80d1777a6 |
comparison
equal
deleted
inserted
replaced
30967:20990991d384 | 30968:0d2a58a04080 |
---|---|
161 | 161 |
162 If ``pagermode`` is not defined, the ``mode`` will be used. | 162 If ``pagermode`` is not defined, the ``mode`` will be used. |
163 ''' | 163 ''' |
164 | 164 |
165 from __future__ import absolute_import | 165 from __future__ import absolute_import |
166 | |
167 try: | |
168 import curses | |
169 curses.COLOR_BLACK # force import | |
170 except ImportError: | |
171 curses = None | |
166 | 172 |
167 from mercurial.i18n import _ | 173 from mercurial.i18n import _ |
168 from mercurial import ( | 174 from mercurial import ( |
169 cmdutil, | 175 cmdutil, |
170 color, | 176 color, |
188 | 194 |
189 def _terminfosetup(ui, mode): | 195 def _terminfosetup(ui, mode): |
190 '''Initialize terminfo data and the terminal if we're in terminfo mode.''' | 196 '''Initialize terminfo data and the terminal if we're in terminfo mode.''' |
191 | 197 |
192 # If we failed to load curses, we go ahead and return. | 198 # If we failed to load curses, we go ahead and return. |
193 if not _terminfo_params: | 199 if not color._terminfo_params: |
194 return | 200 return |
195 # Otherwise, see what the config file says. | 201 # Otherwise, see what the config file says. |
196 if mode not in ('auto', 'terminfo'): | 202 if mode not in ('auto', 'terminfo'): |
197 return | 203 return |
198 | 204 |
199 _terminfo_params.update((key[6:], (False, int(val), '')) | 205 color._terminfo_params.update((key[6:], (False, int(val), '')) |
200 for key, val in ui.configitems('color') | 206 for key, val in ui.configitems('color') |
201 if key.startswith('color.')) | 207 if key.startswith('color.')) |
202 _terminfo_params.update((key[9:], (True, '', val.replace('\\E', '\x1b'))) | 208 color._terminfo_params.update((key[9:], |
209 (True, '', val.replace('\\E', '\x1b'))) | |
203 for key, val in ui.configitems('color') | 210 for key, val in ui.configitems('color') |
204 if key.startswith('terminfo.')) | 211 if key.startswith('terminfo.')) |
205 | 212 |
206 try: | 213 try: |
207 curses.setupterm() | 214 curses.setupterm() |
208 except curses.error as e: | 215 except curses.error as e: |
209 _terminfo_params.clear() | 216 color._terminfo_params.clear() |
210 return | 217 return |
211 | 218 |
212 for key, (b, e, c) in _terminfo_params.items(): | 219 for key, (b, e, c) in color._terminfo_params.items(): |
213 if not b: | 220 if not b: |
214 continue | 221 continue |
215 if not c and not curses.tigetstr(e): | 222 if not c and not curses.tigetstr(e): |
216 # Most terminals don't support dim, invis, etc, so don't be | 223 # Most terminals don't support dim, invis, etc, so don't be |
217 # noisy and use ui.debug(). | 224 # noisy and use ui.debug(). |
218 ui.debug("no terminfo entry for %s\n" % e) | 225 ui.debug("no terminfo entry for %s\n" % e) |
219 del _terminfo_params[key] | 226 del color._terminfo_params[key] |
220 if not curses.tigetstr('setaf') or not curses.tigetstr('setab'): | 227 if not curses.tigetstr('setaf') or not curses.tigetstr('setab'): |
221 # Only warn about missing terminfo entries if we explicitly asked for | 228 # Only warn about missing terminfo entries if we explicitly asked for |
222 # terminfo mode. | 229 # terminfo mode. |
223 if mode == "terminfo": | 230 if mode == "terminfo": |
224 ui.warn(_("no terminfo entry for setab/setaf: reverting to " | 231 ui.warn(_("no terminfo entry for setab/setaf: reverting to " |
225 "ECMA-48 color\n")) | 232 "ECMA-48 color\n")) |
226 _terminfo_params.clear() | 233 color._terminfo_params.clear() |
227 | 234 |
228 def _modesetup(ui, coloropt): | 235 def _modesetup(ui, coloropt): |
229 if coloropt == 'debug': | 236 if coloropt == 'debug': |
230 return 'debug' | 237 return 'debug' |
231 | 238 |
268 # a formatted terminal | 275 # a formatted terminal |
269 if mode == realmode and ui.formatted(): | 276 if mode == realmode and ui.formatted(): |
270 ui.warn(_('warning: failed to set color mode to %s\n') % mode) | 277 ui.warn(_('warning: failed to set color mode to %s\n') % mode) |
271 | 278 |
272 if realmode == 'win32': | 279 if realmode == 'win32': |
273 _terminfo_params.clear() | 280 color._terminfo_params.clear() |
274 if not w32effects: | 281 if not w32effects: |
275 modewarn() | 282 modewarn() |
276 return None | 283 return None |
277 color._effects.update(w32effects) | 284 color._effects.update(w32effects) |
278 elif realmode == 'ansi': | 285 elif realmode == 'ansi': |
279 _terminfo_params.clear() | 286 color._terminfo_params.clear() |
280 elif realmode == 'terminfo': | 287 elif realmode == 'terminfo': |
281 _terminfosetup(ui, mode) | 288 _terminfosetup(ui, mode) |
282 if not _terminfo_params: | 289 if not color._terminfo_params: |
283 ## FIXME Shouldn't we return None in this case too? | 290 ## FIXME Shouldn't we return None in this case too? |
284 modewarn() | 291 modewarn() |
285 realmode = 'ansi' | 292 realmode = 'ansi' |
286 else: | 293 else: |
287 return None | 294 return None |
288 | 295 |
289 if always or (auto and formatted): | 296 if always or (auto and formatted): |
290 return realmode | 297 return realmode |
291 return None | 298 return None |
292 | 299 |
293 try: | |
294 import curses | |
295 # Mapping from effect name to terminfo attribute name (or raw code) or | |
296 # color number. This will also force-load the curses module. | |
297 _terminfo_params = {'none': (True, 'sgr0', ''), | |
298 'standout': (True, 'smso', ''), | |
299 'underline': (True, 'smul', ''), | |
300 'reverse': (True, 'rev', ''), | |
301 'inverse': (True, 'rev', ''), | |
302 'blink': (True, 'blink', ''), | |
303 'dim': (True, 'dim', ''), | |
304 'bold': (True, 'bold', ''), | |
305 'invisible': (True, 'invis', ''), | |
306 'italic': (True, 'sitm', ''), | |
307 'black': (False, curses.COLOR_BLACK, ''), | |
308 'red': (False, curses.COLOR_RED, ''), | |
309 'green': (False, curses.COLOR_GREEN, ''), | |
310 'yellow': (False, curses.COLOR_YELLOW, ''), | |
311 'blue': (False, curses.COLOR_BLUE, ''), | |
312 'magenta': (False, curses.COLOR_MAGENTA, ''), | |
313 'cyan': (False, curses.COLOR_CYAN, ''), | |
314 'white': (False, curses.COLOR_WHITE, '')} | |
315 except ImportError: | |
316 _terminfo_params = {} | |
317 | |
318 def _effect_str(effect): | 300 def _effect_str(effect): |
319 '''Helper function for render_effects().''' | 301 '''Helper function for render_effects().''' |
320 | 302 |
321 bg = False | 303 bg = False |
322 if effect.endswith('_background'): | 304 if effect.endswith('_background'): |
323 bg = True | 305 bg = True |
324 effect = effect[:-11] | 306 effect = effect[:-11] |
325 try: | 307 try: |
326 attr, val, termcode = _terminfo_params[effect] | 308 attr, val, termcode = color._terminfo_params[effect] |
327 except KeyError: | 309 except KeyError: |
328 return '' | 310 return '' |
329 if attr: | 311 if attr: |
330 if termcode: | 312 if termcode: |
331 return termcode | 313 return termcode |
338 | 320 |
339 def render_effects(text, effects): | 321 def render_effects(text, effects): |
340 'Wrap text in commands to turn on each effect.' | 322 'Wrap text in commands to turn on each effect.' |
341 if not text: | 323 if not text: |
342 return text | 324 return text |
343 if not _terminfo_params: | 325 if not color._terminfo_params: |
344 start = [str(color._effects[e]) for e in ['none'] + effects.split()] | 326 start = [str(color._effects[e]) for e in ['none'] + effects.split()] |
345 start = '\033[' + ';'.join(start) + 'm' | 327 start = '\033[' + ';'.join(start) + 'm' |
346 stop = '\033[' + str(color._effects['none']) + 'm' | 328 stop = '\033[' + str(color._effects['none']) + 'm' |
347 else: | 329 else: |
348 start = ''.join(_effect_str(effect) | 330 start = ''.join(_effect_str(effect) |
351 return ''.join([start, text, stop]) | 333 return ''.join([start, text, stop]) |
352 | 334 |
353 def valideffect(effect): | 335 def valideffect(effect): |
354 'Determine if the effect is valid or not.' | 336 'Determine if the effect is valid or not.' |
355 good = False | 337 good = False |
356 if not _terminfo_params and effect in color._effects: | 338 if not color._terminfo_params and effect in color._effects: |
357 good = True | 339 good = True |
358 elif effect in _terminfo_params or effect[:-11] in _terminfo_params: | 340 elif (effect in color._terminfo_params |
341 or effect[:-11] in color._terminfo_params): | |
359 good = True | 342 good = True |
360 return good | 343 return good |
361 | 344 |
362 def configstyles(ui): | 345 def configstyles(ui): |
363 for status, cfgeffects in ui.configitems('color'): | 346 for status, cfgeffects in ui.configitems('color'): |
481 oldstyle = color._styles.copy() | 464 oldstyle = color._styles.copy() |
482 try: | 465 try: |
483 color._styles.clear() | 466 color._styles.clear() |
484 for effect in color._effects.keys(): | 467 for effect in color._effects.keys(): |
485 color._styles[effect] = effect | 468 color._styles[effect] = effect |
486 if _terminfo_params: | 469 if color._terminfo_params: |
487 for k, v in ui.configitems('color'): | 470 for k, v in ui.configitems('color'): |
488 if k.startswith('color.'): | 471 if k.startswith('color.'): |
489 color._styles[k] = k[6:] | 472 color._styles[k] = k[6:] |
490 elif k.startswith('terminfo.'): | 473 elif k.startswith('terminfo.'): |
491 color._styles[k] = k[9:] | 474 color._styles[k] = k[9:] |