-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathansicolortext.py
151 lines (139 loc) · 4.64 KB
/
ansicolortext.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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# author: stefaan.himpe@gmail.com
# license: MIT
from Tkinter import *
import re
from idlelib.WidgetRedirector import WidgetRedirector
class AnsiColorText(Text):
"""
class to convert text with ansi color codes to
text with tkinter color tags
for now we ignore all but the simplest color directives
see http://www.termsys.demon.co.uk/vtansi.htm for a list of
other directives
it has not been thoroughly tested, but it works well enough for demonstration purposes
"""
foreground_colors = {
'bright' : {
'30' : 'Black',
'31' : 'Red',
'32' : 'Green',
'33' : 'Brown',
'34' : 'Blue',
'35' : 'Purple',
'36' : 'Cyan',
'37' : 'White'
},
'dim' : {
'30' : 'DarkGray',
'31' : 'LightRed',
'32' : 'LightGreen',
'33' : 'Yellow',
'34' : 'LightBlue',
'35' : 'Magenta',
'36' : 'Pink',
'37' : 'White'
}
}
background_colors= {
'bright' : {
'40' : 'Black',
'41' : 'Red',
'42' : 'Green',
'43' : 'Brown',
'44' : 'Blue',
'45' : 'Purple',
'46' : 'Cyan',
'47' : 'White'
},
'dim' : {
'40' : 'DarkGray',
'41' : 'LightRed',
'42' : 'LightGreen',
'43' : 'Yellow',
'44' : 'LightBlue',
'45' : 'Magenta',
'46' : 'Pink',
'47' : 'White'
}
}
# define some regexes which will come in handy in filtering
# out the ansi color codes
color_pat = re.compile('\x01?\x1b\[([\d+;]*?)m\x02?')
inner_color_pat = re.compile("^(\d+;?)+$")
def __init__(self, parent):
"""
initialize our specialized tkinter Text widget
"""
Text.__init__(self, parent)
self.redirector = WidgetRedirector(self)
self.insert = self.redirector.register("insert", lambda *args, **kw: "break")
self.delete = self.redirector.register("delete", lambda *args, **kw: "break")
self.known_tags = set([])
# register a default color tag
self.register_tag("30", "Black", "White")
self.reset_to_default_attribs()
def reset_to_default_attribs(self):
self.tag = '30'
self.bright = 'bright'
self.foregroundcolor = 'Black'
self.backgroundcolor = 'White'
def colored_write(self, txt, color):
self.tag = str(30+color)
txt += '\n'
self.color_set(self.tag)
self.insert(END,txt,self.tag)
def register_tag(self, txt, foreground, background):
"""
register a tag with name txt and with given
foreground and background color
"""
self.tag_config(txt, foreground=foreground, background=background)
self.known_tags.add(txt)
def color_set(self, tag):
if tag not in self.known_tags:
# if tag not yet registered,
# extract the foreground and background color
# and ignore the other things
parts = tag.split(";")
for part in parts:
if part in AnsiColorText.foreground_colors[self.bright]:
self.foregroundcolor = AnsiColorText.foreground_colors[self.bright][part]
elif part in AnsiColorText.background_colors[self.bright]:
self.backgroundcolor = AnsiColorText.background_colors[self.bright][part]
else:
for ch in part:
if ch == '0' :
# reset all attributes
self.reset_to_default_attribs()
if ch == '1' :
# define bright colors
self.bright = 'bright'
if ch == '2' :
# define dim colors
self.bright = 'dim'
self.register_tag(tag,
foreground=self.foregroundcolor,
background=self.backgroundcolor)
# remember that we switched to this tag
self.tag = tag
def write(self, text, is_editable=False):
"""
add text to the text widget
"""
# first split the text at color codes, stripping stuff like the <ESC>
# and \[ characters and keeping only the inner "0;23"-like codes
segments = AnsiColorText.color_pat.split(text)
if segments:
for text in segments:
# a segment can be regular text, or it can be a color pattern
if AnsiColorText.inner_color_pat.match(text):
# if it's a color pattern, check if we already have
# registered a tag for it
color_set(text)
elif text == '':
# reset tag to black
self.tag = '30' # black
else:
# no color pattern, insert text with the currently selected
# tag
self.insert(END,text,self.tag)