comparison hgext/color.py @ 30173:f34a8cff51d9

color: allow for user-configurable terminfo codes for effects If the entry in the terminfo database for your terminal is missing some attributes, it should be possible to create them on the fly without resorting to just making them a color. This change allows you to have [color] terminfo.<effect> = <code> where <effect> might be something like "dim" or "bold", and <code> is the escape sequence that would otherwise have come from a call to tigetstr(). If an escape character is needed, use "\E". Any such settings will override attributes that are present in the terminfo database.
author Danek Duvall <danek.duvall@oracle.com>
date Thu, 13 Oct 2016 11:48:17 -0700
parents 31a6d5e14508
children 5d777fe4615d
comparison
equal deleted inserted replaced
30172:90a6c18a7c1d 30173:f34a8cff51d9
194 return 194 return
195 # Otherwise, see what the config file says. 195 # Otherwise, see what the config file says.
196 if mode not in ('auto', 'terminfo'): 196 if mode not in ('auto', 'terminfo'):
197 return 197 return
198 198
199 _terminfo_params.update((key[6:], (False, int(val))) 199 _terminfo_params.update((key[6:], (False, int(val), ''))
200 for key, val in ui.configitems('color') 200 for key, val in ui.configitems('color')
201 if key.startswith('color.')) 201 if key.startswith('color.'))
202 _terminfo_params.update((key[9:], (True, '', val.replace('\\E', '\x1b')))
203 for key, val in ui.configitems('color')
204 if key.startswith('terminfo.'))
202 205
203 try: 206 try:
204 curses.setupterm() 207 curses.setupterm()
205 except curses.error as e: 208 except curses.error as e:
206 _terminfo_params = {} 209 _terminfo_params = {}
207 return 210 return
208 211
209 for key, (b, e) in _terminfo_params.items(): 212 for key, (b, e, c) in _terminfo_params.items():
210 if not b: 213 if not b:
211 continue 214 continue
212 if not curses.tigetstr(e): 215 if not c and not curses.tigetstr(e):
213 # Most terminals don't support dim, invis, etc, so don't be 216 # Most terminals don't support dim, invis, etc, so don't be
214 # noisy and use ui.debug(). 217 # noisy and use ui.debug().
215 ui.debug("no terminfo entry for %s\n" % e) 218 ui.debug("no terminfo entry for %s\n" % e)
216 del _terminfo_params[key] 219 del _terminfo_params[key]
217 if not curses.tigetstr('setaf') or not curses.tigetstr('setab'): 220 if not curses.tigetstr('setaf') or not curses.tigetstr('setab'):
288 return realmode 291 return realmode
289 return None 292 return None
290 293
291 try: 294 try:
292 import curses 295 import curses
293 # Mapping from effect name to terminfo attribute name or color number. 296 # Mapping from effect name to terminfo attribute name (or raw code) or
294 # This will also force-load the curses module. 297 # color number. This will also force-load the curses module.
295 _terminfo_params = {'none': (True, 'sgr0'), 298 _terminfo_params = {'none': (True, 'sgr0', ''),
296 'standout': (True, 'smso'), 299 'standout': (True, 'smso', ''),
297 'underline': (True, 'smul'), 300 'underline': (True, 'smul', ''),
298 'reverse': (True, 'rev'), 301 'reverse': (True, 'rev', ''),
299 'inverse': (True, 'rev'), 302 'inverse': (True, 'rev', ''),
300 'blink': (True, 'blink'), 303 'blink': (True, 'blink', ''),
301 'dim': (True, 'dim'), 304 'dim': (True, 'dim', ''),
302 'bold': (True, 'bold'), 305 'bold': (True, 'bold', ''),
303 'invisible': (True, 'invis'), 306 'invisible': (True, 'invis', ''),
304 'italic': (True, 'sitm'), 307 'italic': (True, 'sitm', ''),
305 'black': (False, curses.COLOR_BLACK), 308 'black': (False, curses.COLOR_BLACK, ''),
306 'red': (False, curses.COLOR_RED), 309 'red': (False, curses.COLOR_RED, ''),
307 'green': (False, curses.COLOR_GREEN), 310 'green': (False, curses.COLOR_GREEN, ''),
308 'yellow': (False, curses.COLOR_YELLOW), 311 'yellow': (False, curses.COLOR_YELLOW, ''),
309 'blue': (False, curses.COLOR_BLUE), 312 'blue': (False, curses.COLOR_BLUE, ''),
310 'magenta': (False, curses.COLOR_MAGENTA), 313 'magenta': (False, curses.COLOR_MAGENTA, ''),
311 'cyan': (False, curses.COLOR_CYAN), 314 'cyan': (False, curses.COLOR_CYAN, ''),
312 'white': (False, curses.COLOR_WHITE)} 315 'white': (False, curses.COLOR_WHITE, '')}
313 except ImportError: 316 except ImportError:
314 _terminfo_params = {} 317 _terminfo_params = {}
315 318
316 _styles = {'grep.match': 'red bold', 319 _styles = {'grep.match': 'red bold',
317 'grep.linenumber': 'green', 320 'grep.linenumber': 'green',
373 376
374 bg = False 377 bg = False
375 if effect.endswith('_background'): 378 if effect.endswith('_background'):
376 bg = True 379 bg = True
377 effect = effect[:-11] 380 effect = effect[:-11]
378 attr, val = _terminfo_params[effect] 381 attr, val, termcode = _terminfo_params[effect]
379 if attr: 382 if attr:
380 return curses.tigetstr(val) 383 if termcode:
384 return termcode
385 else:
386 return curses.tigetstr(val)
381 elif bg: 387 elif bg:
382 return curses.tparm(curses.tigetstr('setab'), val) 388 return curses.tparm(curses.tigetstr('setab'), val)
383 else: 389 else:
384 return curses.tparm(curses.tigetstr('setaf'), val) 390 return curses.tparm(curses.tigetstr('setaf'), val)
385 391
410 good = True 416 good = True
411 return good 417 return good
412 418
413 def configstyles(ui): 419 def configstyles(ui):
414 for status, cfgeffects in ui.configitems('color'): 420 for status, cfgeffects in ui.configitems('color'):
415 if '.' not in status or status.startswith('color.'): 421 if '.' not in status or status.startswith(('color.', 'terminfo.')):
416 continue 422 continue
417 cfgeffects = ui.configlist('color', status) 423 cfgeffects = ui.configlist('color', status)
418 if cfgeffects: 424 if cfgeffects:
419 good = [] 425 good = []
420 for e in cfgeffects: 426 for e in cfgeffects: