-
Notifications
You must be signed in to change notification settings - Fork 0
/
urwidpygments.py
114 lines (93 loc) · 3.84 KB
/
urwidpygments.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
"""Provides a pygments formatter for use with urwid."""
from pygments.formatter import Formatter
import urwid
colors16 = ['default',
'black', 'dark red', 'dark green', 'brown', 'dark blue',
'dark magenta', 'dark cyan', 'light gray', 'dark gray',
'light red', 'light green', 'yellow', 'light blue',
'light magenta', 'light cyan', 'white']
class UrwidFormatter(Formatter):
"""Formatter that returns [(text,attrspec), ...],
where text is a piece of text, and attrspec is an urwid.AttrSpec"""
def __init__(self, **options):
"""Extra arguments:
usebold: if false, bold will be ignored and always off
default: True
usebg: if false, background color will always be 'default'
default: True
colors: number of colors to use (16, 88, or 256)
default: 256"""
self.usebold = options.get('usebold',True)
self.usebg = options.get('usebg', True)
colors = options.get('colors', 256)
self.style_attrs = {}
Formatter.__init__(self, **options)
@property
def style(self):
return self._style
@style.setter
def style(self, newstyle):
self._style = newstyle
self._setup_styles()
@staticmethod
def _distance(col1, col2):
r1, g1, b1 = col1
r2, g2, b2 = col2
rd = r1 - r2
gd = g1 - g2
bd = b1 - b2
return rd*rd + gd*gd + bd*bd
@classmethod
def findclosest(cls, colstr, colors=256):
"""Takes a hex string and finds the nearest color to it.
Returns a string urwid will recognize."""
rgb = int(colstr, 16)
r = (rgb >> 16) & 0xff
g = (rgb >> 8) & 0xff
b = rgb & 0xff
dist = 257 * 257 * 3
bestcol = urwid.AttrSpec('h0','default')
for i in range(colors):
curcol = urwid.AttrSpec('h%d' % i,'default', colors=colors)
currgb = curcol.get_rgb_values()[:3]
curdist = cls._distance((r,g,b), currgb)
if curdist < dist:
dist = curdist
bestcol = curcol
return bestcol.foreground
def findclosestattr(self, fgcolstr=None, bgcolstr=None, othersettings='', colors = 256):
"""Takes two hex colstring (e.g. 'ff00dd') and returns the
nearest urwid style."""
fg = bg = 'default'
if fgcolstr:
fg = self.findclosest(fgcolstr, colors)
if bgcolstr:
bg = self.findclosest(bgcolstr, colors)
if othersettings:
fg = fg + ',' + othersettings
return urwid.AttrSpec(fg, bg, colors)
def _setup_styles(self, colors = 256):
"""Fills self.style_attrs with urwid.AttrSpec attributes
corresponding to the closest equivalents to the given style."""
for ttype, ndef in self.style:
fgcolstr = bgcolstr = None
othersettings = ''
if ndef['color']:
fgcolstr = ndef['color']
if self.usebg and ndef['bgcolor']:
bgcolstr = ndef['bgcolor']
if self.usebold and ndef['bold']:
othersettings = 'bold'
self.style_attrs[str(ttype)] = self.findclosestattr(
fgcolstr, bgcolstr, othersettings, colors)
def formatgenerator(self, tokensource):
"""Takes a token source, and generates
(tokenstring, urwid.AttrSpec) pairs"""
for (ttype, tstring) in tokensource:
while str(ttype) not in self.style_attrs:
ttype = ttype[:-1]
attr = self.style_attrs[str(ttype)]
yield attr, tstring
def format(self, tokensource, outfile):
for (attr, tstring) in self.formatgenerator(tokensource):
outfile.write(attr, tstring)