from charseq import charseq class colorchr(str): def __new__(cls, c, color): if isinstance(c, (int, long)): c = chr(c) self = str.__new__(cls, c) if len(self) != 1: raise ValueError, "colorchr() argument must be a character" self.color = color return self def __repr__(self): return '<%s %r>' % (self.color, str(self)) class colorunichr(unicode): def __new__(cls, c, color): if isinstance(c, (int, long)): c = unichr(c) self = unicode.__new__(cls, c) if len(self) != 1: raise ValueError, "colorchr() argument must be a character" self.color = color return self def __repr__(self): return '<%s %r>' % (self.color, unicode(self)) def _color(c, color): if isinstance(c, unicode): return colorunichr(c, color) else: return colorchr(c, color) def color(s, color): return charseq.fromlist([_color(c, color) for c in s]) def ansi(s): result = [] currentcolor = None for c in s: color = getattr(c, 'color', None) if color != currentcolor: result.append('\x1b[%dm' % ansi_color_map[color]) currentcolor = color result.append(c) if currentcolor is not None: result.append('\x1b[0m') return ''.join(result) ansi_color_map = { 'black' : 30, 'red' : 31, 'green' : 32, 'yellow' : 33, 'blue' : 34, 'purple' : 35, 'cyan' : 36, 'white' : 37, None : 39, } if __name__ == '__main__': s = color(' hello ', 'red') + color(' world ', 'green')