2007-03-06 10:05:38 -05:00
|
|
|
import curses
|
|
|
|
|
2009-06-10 16:07:03 -04:00
|
|
|
colors = {}
|
|
|
|
_colors = []
|
|
|
|
_pairs = {}
|
|
|
|
index = 1
|
|
|
|
attributes = {
|
|
|
|
'bold': curses.A_BOLD,
|
|
|
|
'reverse': curses.A_REVERSE,
|
|
|
|
'normal': curses.A_NORMAL,
|
|
|
|
'underline': curses.A_UNDERLINE,
|
|
|
|
'dim': curses.A_DIM,
|
|
|
|
'standout': curses.A_STANDOUT,
|
|
|
|
}
|
|
|
|
|
2009-07-23 16:26:59 -04:00
|
|
|
inited = False
|
2007-03-06 10:05:38 -05:00
|
|
|
default_color = True
|
|
|
|
|
2009-06-10 16:07:03 -04:00
|
|
|
ascii_map = {
|
|
|
|
'*': 'bold',
|
|
|
|
}
|
|
|
|
rev_ascii_map = {
|
|
|
|
'bold': '*',
|
|
|
|
}
|
2007-03-06 10:05:38 -05:00
|
|
|
|
2009-07-23 16:26:59 -04:00
|
|
|
# add a particular color
|
2009-06-10 16:07:03 -04:00
|
|
|
def add_color(name, value, abbrev):
|
|
|
|
colors[name] = value
|
|
|
|
ascii_map[abbrev] = name
|
|
|
|
rev_ascii_map[name] = abbrev
|
2007-03-06 10:05:38 -05:00
|
|
|
|
2009-07-23 16:26:59 -04:00
|
|
|
# assign every RGB triple (0-5) to one of six basic colors (red, yellow, green,
|
|
|
|
# cyan, blue, magenta) based on some semi-arbitrary rules i came up with.
|
2009-06-10 23:41:53 -04:00
|
|
|
def iter256():
|
2009-11-12 00:01:05 -05:00
|
|
|
for r in xrange(0, 6):
|
|
|
|
for g in xrange(0, 6):
|
|
|
|
for b in xrange(0, 6):
|
2009-08-20 00:29:04 -04:00
|
|
|
#if r >= 3 and g >= 3 and b >= 3: name = 'white'
|
|
|
|
#elif r >= g and g > b: name = 'yellow'
|
2009-06-10 23:41:53 -04:00
|
|
|
if r >= g and g > b: name = 'yellow'
|
|
|
|
elif r >= b and b - g > 1: name = 'magenta'
|
|
|
|
|
|
|
|
elif b >= g and g - r > 2: name = 'cyan'
|
|
|
|
elif b >= r and r > g: name = 'magenta'
|
|
|
|
|
|
|
|
elif g >= r and r - b > 2: name = 'yellow'
|
|
|
|
elif g >= b and b - r > 1: name = 'cyan'
|
|
|
|
|
|
|
|
elif r > b and r > g: name = 'red'
|
|
|
|
elif g > b and g > r: name = 'green'
|
|
|
|
elif b > r and b > g: name = 'blue'
|
|
|
|
|
|
|
|
else: continue
|
|
|
|
|
|
|
|
yield (name, r, g, b)
|
|
|
|
raise StopIteration
|
|
|
|
|
2009-07-23 16:26:59 -04:00
|
|
|
# if we can support 256 colors, create all of the color names and map them to
|
|
|
|
# the correct RGB value.
|
2009-06-10 16:07:03 -04:00
|
|
|
def color256(name, fallback, abbrev, r, g, b):
|
|
|
|
name2 = '%s%d%d%d' % (name, r, g, b)
|
|
|
|
abbrev2 = '%s%d%d%d' % (abbrev, r, g, b)
|
|
|
|
if curses.COLORS == 256:
|
|
|
|
value = 16 + r * 36 + g * 6 + b
|
2009-06-10 17:55:33 -04:00
|
|
|
if curses.can_change_color():
|
2009-07-23 16:26:59 -04:00
|
|
|
curses.init_color(value, r * 200, g * 200, b* 200)
|
2007-03-06 10:05:38 -05:00
|
|
|
else:
|
2009-06-10 16:07:03 -04:00
|
|
|
value = fallback
|
|
|
|
add_color(name2, value, abbrev2)
|
2007-03-06 10:05:38 -05:00
|
|
|
|
2009-06-10 16:07:03 -04:00
|
|
|
def init():
|
|
|
|
global _pairs, inited
|
2009-07-23 16:26:59 -04:00
|
|
|
if inited: return
|
|
|
|
inited = True
|
2007-03-06 10:05:38 -05:00
|
|
|
|
2009-07-23 16:26:59 -04:00
|
|
|
# create the basic 8 colors of curses
|
2009-06-10 16:07:03 -04:00
|
|
|
add_color('cyan', curses.COLOR_CYAN, 'c')
|
|
|
|
add_color('blue', curses.COLOR_BLUE, 'b')
|
|
|
|
add_color('green', curses.COLOR_GREEN, 'g')
|
|
|
|
add_color('red', curses.COLOR_RED, 'r')
|
|
|
|
add_color('yellow', curses.COLOR_YELLOW, 'y')
|
|
|
|
add_color('magenta', curses.COLOR_MAGENTA, 'm')
|
|
|
|
add_color('black', curses.COLOR_BLACK, 'B')
|
|
|
|
add_color('white', curses.COLOR_WHITE, 'w')
|
|
|
|
|
2009-07-23 16:26:59 -04:00
|
|
|
# initialize the "default" color if possible
|
2009-06-10 17:55:33 -04:00
|
|
|
if default_color:
|
|
|
|
colors['default'] = -1
|
|
|
|
ascii_map['d'] = 'default'
|
|
|
|
rev_ascii_map['default'] = 'd'
|
|
|
|
|
2009-07-23 16:26:59 -04:00
|
|
|
# add in hex aliases to 256 colors; used by color-data buffers
|
2009-11-12 00:01:05 -05:00
|
|
|
for i in xrange(0, 256):
|
2009-06-10 16:07:03 -04:00
|
|
|
name = 'f%02x' % i
|
|
|
|
abbrev = 'f%02x' % i
|
|
|
|
add_color(name, i, abbrev)
|
|
|
|
|
2009-07-23 16:26:59 -04:00
|
|
|
# create the 24 flavors of grey in 256 colors
|
2009-11-12 00:01:05 -05:00
|
|
|
for i in xrange(0, 24):
|
2009-06-10 17:55:33 -04:00
|
|
|
name2 = 'grey%d' % i
|
|
|
|
abbrev2 = 'G%d' % i
|
|
|
|
if curses.COLORS == 256:
|
|
|
|
value = 232 + i
|
|
|
|
if curses.can_change_color():
|
2009-07-23 16:26:59 -04:00
|
|
|
curses.init_color(value, i * 41, i * 41, i * 41)
|
2009-06-10 17:55:33 -04:00
|
|
|
else:
|
|
|
|
value = curses.COLOR_WHITE
|
|
|
|
add_color(name2, value, abbrev2)
|
2007-03-06 10:05:38 -05:00
|
|
|
|
2009-07-23 16:26:59 -04:00
|
|
|
# create 256 colors
|
2009-06-10 23:41:53 -04:00
|
|
|
for name, r, g, b in iter256():
|
|
|
|
color256(name, colors[name], rev_ascii_map[name], r, g, b)
|
2009-06-10 16:07:03 -04:00
|
|
|
|
|
|
|
def build(fg, bg, *attr):
|
|
|
|
v = curses.A_NORMAL | pairs(fg, bg)
|
2007-03-06 10:05:38 -05:00
|
|
|
for x in attr:
|
|
|
|
if type(x) == type(''):
|
|
|
|
x = attributes[x]
|
|
|
|
v = v | x
|
|
|
|
return v
|
2009-06-10 16:07:03 -04:00
|
|
|
|
|
|
|
def pairs(fg, bg):
|
|
|
|
if not curses.has_colors():
|
|
|
|
return curses.color_pair(0)
|
|
|
|
|
|
|
|
global index
|
|
|
|
fgi = colors.get(fg, colors['white'])
|
|
|
|
bgi = colors.get(bg, colors['black'])
|
|
|
|
key = (fgi, bgi)
|
|
|
|
if key not in _pairs:
|
|
|
|
assert index < curses.COLOR_PAIRS, "too many colors"
|
|
|
|
assert type(fgi) == type(0), "illegal fgi: %r" % fgi
|
|
|
|
assert type(bgi) == type(0), "illegal bgi: %r" % bgi
|
2009-06-10 17:55:33 -04:00
|
|
|
try:
|
|
|
|
curses.init_pair(index, fgi, bgi)
|
|
|
|
except:
|
|
|
|
raise Exception('failed to init %d,%d,%d' % (index, fgi, bgi))
|
2009-06-10 16:07:03 -04:00
|
|
|
_pairs[key] = curses.color_pair(index)
|
|
|
|
_colors.append(key)
|
|
|
|
index = len(_colors) + 1
|
|
|
|
return _pairs[key]
|