mercurial/color.py
changeset 31113 268caf97c38f
parent 31112 7f056fdbe37e
child 31114 1613c55ad3d6
equal deleted inserted replaced
31112:7f056fdbe37e 31113:268caf97c38f
    17 
    17 
    18 try:
    18 try:
    19     import curses
    19     import curses
    20     # Mapping from effect name to terminfo attribute name (or raw code) or
    20     # Mapping from effect name to terminfo attribute name (or raw code) or
    21     # color number.  This will also force-load the curses module.
    21     # color number.  This will also force-load the curses module.
    22     _terminfo_params = {
    22     _baseterminfoparams = {
    23         'none': (True, 'sgr0', ''),
    23         'none': (True, 'sgr0', ''),
    24         'standout': (True, 'smso', ''),
    24         'standout': (True, 'smso', ''),
    25         'underline': (True, 'smul', ''),
    25         'underline': (True, 'smul', ''),
    26         'reverse': (True, 'rev', ''),
    26         'reverse': (True, 'rev', ''),
    27         'inverse': (True, 'rev', ''),
    27         'inverse': (True, 'rev', ''),
    39         'cyan': (False, curses.COLOR_CYAN, ''),
    39         'cyan': (False, curses.COLOR_CYAN, ''),
    40         'white': (False, curses.COLOR_WHITE, ''),
    40         'white': (False, curses.COLOR_WHITE, ''),
    41     }
    41     }
    42 except ImportError:
    42 except ImportError:
    43     curses = None
    43     curses = None
    44     _terminfo_params = {}
    44     _baseterminfoparams = {}
    45 
    45 
    46 # allow the extensions to change the default
    46 # allow the extensions to change the default
    47 _enabledbydefault = False
    47 _enabledbydefault = False
    48 
    48 
    49 # start and stop parameters for effects
    49 # start and stop parameters for effects
   138     if curses is None:
   138     if curses is None:
   139         return
   139         return
   140     # Otherwise, see what the config file says.
   140     # Otherwise, see what the config file says.
   141     if mode not in ('auto', 'terminfo'):
   141     if mode not in ('auto', 'terminfo'):
   142         return
   142         return
       
   143     ui._terminfoparams.update(_baseterminfoparams)
   143 
   144 
   144     for key, val in ui.configitems('color'):
   145     for key, val in ui.configitems('color'):
   145         if key.startswith('color.'):
   146         if key.startswith('color.'):
   146             newval = (False, int(val), '')
   147             newval = (False, int(val), '')
   147             _terminfo_params[key[6:]] = newval
   148             ui._terminfoparams[key[6:]] = newval
   148         elif key.startswith('terminfo.'):
   149         elif key.startswith('terminfo.'):
   149             newval = (True, '', val.replace('\\E', '\x1b'))
   150             newval = (True, '', val.replace('\\E', '\x1b'))
   150             _terminfo_params[key[9:]] = newval
   151             ui._terminfoparams[key[9:]] = newval
   151     try:
   152     try:
   152         curses.setupterm()
   153         curses.setupterm()
   153     except curses.error as e:
   154     except curses.error as e:
   154         _terminfo_params.clear()
   155         ui._terminfoparams.clear()
   155         return
   156         return
   156 
   157 
   157     for key, (b, e, c) in _terminfo_params.items():
   158     for key, (b, e, c) in ui._terminfoparams.items():
   158         if not b:
   159         if not b:
   159             continue
   160             continue
   160         if not c and not curses.tigetstr(e):
   161         if not c and not curses.tigetstr(e):
   161             # Most terminals don't support dim, invis, etc, so don't be
   162             # Most terminals don't support dim, invis, etc, so don't be
   162             # noisy and use ui.debug().
   163             # noisy and use ui.debug().
   163             ui.debug("no terminfo entry for %s\n" % e)
   164             ui.debug("no terminfo entry for %s\n" % e)
   164             del _terminfo_params[key]
   165             del ui._terminfoparams[key]
   165     if not curses.tigetstr('setaf') or not curses.tigetstr('setab'):
   166     if not curses.tigetstr('setaf') or not curses.tigetstr('setab'):
   166         # Only warn about missing terminfo entries if we explicitly asked for
   167         # Only warn about missing terminfo entries if we explicitly asked for
   167         # terminfo mode.
   168         # terminfo mode.
   168         if mode == "terminfo":
   169         if mode == "terminfo":
   169             ui.warn(_("no terminfo entry for setab/setaf: reverting to "
   170             ui.warn(_("no terminfo entry for setab/setaf: reverting to "
   170               "ECMA-48 color\n"))
   171               "ECMA-48 color\n"))
   171         _terminfo_params.clear()
   172         ui._terminfoparams.clear()
   172 
   173 
   173 def setup(ui):
   174 def setup(ui):
   174     """configure color on a ui
   175     """configure color on a ui
   175 
   176 
   176     That function both set the colormode for the ui object and read
   177     That function both set the colormode for the ui object and read
   230         # a formatted terminal
   231         # a formatted terminal
   231         if mode == realmode and ui.formatted():
   232         if mode == realmode and ui.formatted():
   232             ui.warn(_('warning: failed to set color mode to %s\n') % mode)
   233             ui.warn(_('warning: failed to set color mode to %s\n') % mode)
   233 
   234 
   234     if realmode == 'win32':
   235     if realmode == 'win32':
   235         _terminfo_params.clear()
   236         ui._terminfoparams.clear()
   236         if not w32effects:
   237         if not w32effects:
   237             modewarn()
   238             modewarn()
   238             return None
   239             return None
   239         _effects.update(w32effects)
   240         _effects.update(w32effects)
   240     elif realmode == 'ansi':
   241     elif realmode == 'ansi':
   241         _terminfo_params.clear()
   242         ui._terminfoparams.clear()
   242     elif realmode == 'terminfo':
   243     elif realmode == 'terminfo':
   243         _terminfosetup(ui, mode)
   244         _terminfosetup(ui, mode)
   244         if not _terminfo_params:
   245         if not ui._terminfoparams:
   245             ## FIXME Shouldn't we return None in this case too?
   246             ## FIXME Shouldn't we return None in this case too?
   246             modewarn()
   247             modewarn()
   247             realmode = 'ansi'
   248             realmode = 'ansi'
   248     else:
   249     else:
   249         return None
   250         return None
   268                             % (e, status))
   269                             % (e, status))
   269             _styles[status] = ' '.join(good)
   270             _styles[status] = ' '.join(good)
   270 
   271 
   271 def valideffect(ui, effect):
   272 def valideffect(ui, effect):
   272     'Determine if the effect is valid or not.'
   273     'Determine if the effect is valid or not.'
   273     return ((not _terminfo_params and effect in _effects)
   274     return ((not ui._terminfoparams and effect in _effects)
   274              or (effect in _terminfo_params
   275              or (effect in ui._terminfoparams
   275                  or effect[:-11] in _terminfo_params))
   276                  or effect[:-11] in ui._terminfoparams))
   276 
   277 
   277 def _effect_str(ui, effect):
   278 def _effect_str(ui, effect):
   278     '''Helper function for render_effects().'''
   279     '''Helper function for render_effects().'''
   279 
   280 
   280     bg = False
   281     bg = False
   281     if effect.endswith('_background'):
   282     if effect.endswith('_background'):
   282         bg = True
   283         bg = True
   283         effect = effect[:-11]
   284         effect = effect[:-11]
   284     try:
   285     try:
   285         attr, val, termcode = _terminfo_params[effect]
   286         attr, val, termcode = ui._terminfoparams[effect]
   286     except KeyError:
   287     except KeyError:
   287         return ''
   288         return ''
   288     if attr:
   289     if attr:
   289         if termcode:
   290         if termcode:
   290             return termcode
   291             return termcode
   297 
   298 
   298 def _render_effects(ui, text, effects):
   299 def _render_effects(ui, text, effects):
   299     'Wrap text in commands to turn on each effect.'
   300     'Wrap text in commands to turn on each effect.'
   300     if not text:
   301     if not text:
   301         return text
   302         return text
   302     if _terminfo_params:
   303     if ui._terminfoparams:
   303         start = ''.join(_effect_str(ui, effect)
   304         start = ''.join(_effect_str(ui, effect)
   304                         for effect in ['none'] + effects.split())
   305                         for effect in ['none'] + effects.split())
   305         stop = _effect_str(ui, 'none')
   306         stop = _effect_str(ui, 'none')
   306     else:
   307     else:
   307         start = [str(_effects[e]) for e in ['none'] + effects.split()]
   308         start = [str(_effects[e]) for e in ['none'] + effects.split()]