6
from Delegator import Delegator
7
from configHandler import idleConf
11
def any(name, alternates):
12
"Return a named group pattern matching list of alternates."
13
return "(?P<%s>" % name + "|".join(alternates) + ")"
16
kw = r"\b" + any("KEYWORD", keyword.kwlist) + r"\b"
17
builtinlist = [str(name) for name in dir(__builtin__)
18
if not name.startswith('_')]
19
# self.file = file("file") :
20
# 1st 'file' colorized normal, 2nd as builtin, 3rd as string
21
builtin = r"([^.'\"\\#]\b|^)" + any("BUILTIN", builtinlist) + r"\b"
22
comment = any("COMMENT", [r"#[^\n]*"])
23
sqstring = r"(\b[rRuU])?'[^'\\\n]*(\\.[^'\\\n]*)*'?"
24
dqstring = r'(\b[rRuU])?"[^"\\\n]*(\\.[^"\\\n]*)*"?'
25
sq3string = r"(\b[rRuU])?'''[^'\\]*((\\.|'(?!''))[^'\\]*)*(''')?"
26
dq3string = r'(\b[rRuU])?"""[^"\\]*((\\.|"(?!""))[^"\\]*)*(""")?'
27
string = any("STRING", [sq3string, dq3string, sqstring, dqstring])
28
return kw + "|" + builtin + "|" + comment + "|" + string +\
29
"|" + any("SYNC", [r"\n"])
31
prog = re.compile(make_pat(), re.S)
32
idprog = re.compile(r"\s+(\w+)", re.S)
33
asprog = re.compile(r".*?\b(as)\b")
35
class ColorDelegator(Delegator):
38
Delegator.__init__(self)
44
def setdelegate(self, delegate):
45
if self.delegate is not None:
46
self.unbind("<<toggle-auto-coloring>>")
47
Delegator.setdelegate(self, delegate)
48
if delegate is not None:
50
self.bind("<<toggle-auto-coloring>>", self.toggle_colorize_event)
51
self.notify_range("1.0", "end")
53
def config_colors(self):
54
for tag, cnf in self.tagdefs.items():
56
self.tag_configure(tag, **cnf)
59
def LoadTagDefs(self):
60
theme = idleConf.GetOption('main','Theme','name')
62
"COMMENT": idleConf.GetHighlight(theme, "comment"),
63
"KEYWORD": idleConf.GetHighlight(theme, "keyword"),
64
"BUILTIN": idleConf.GetHighlight(theme, "builtin"),
65
"STRING": idleConf.GetHighlight(theme, "string"),
66
"DEFINITION": idleConf.GetHighlight(theme, "definition"),
67
"SYNC": {'background':None,'foreground':None},
68
"TODO": {'background':None,'foreground':None},
69
"BREAK": idleConf.GetHighlight(theme, "break"),
70
"ERROR": idleConf.GetHighlight(theme, "error"),
71
# The following is used by ReplaceDialog:
72
"hit": idleConf.GetHighlight(theme, "hit"),
75
if DEBUG: print 'tagdefs',self.tagdefs
77
def insert(self, index, chars, tags=None):
78
index = self.index(index)
79
self.delegate.insert(index, chars, tags)
80
self.notify_range(index, index + "+%dc" % len(chars))
82
def delete(self, index1, index2=None):
83
index1 = self.index(index1)
84
self.delegate.delete(index1, index2)
85
self.notify_range(index1)
88
allow_colorizing = True
91
def notify_range(self, index1, index2=None):
92
self.tag_add("TODO", index1, index2)
94
if DEBUG: print "colorizing already scheduled"
97
self.stop_colorizing = True
98
if DEBUG: print "stop colorizing"
99
if self.allow_colorizing:
100
if DEBUG: print "schedule colorizing"
101
self.after_id = self.after(1, self.recolorize)
103
close_when_done = None # Window to be closed when done colorizing
105
def close(self, close_when_done=None):
107
after_id = self.after_id
109
if DEBUG: print "cancel scheduled recolorizer"
110
self.after_cancel(after_id)
111
self.allow_colorizing = False
112
self.stop_colorizing = True
114
if not self.colorizing:
115
close_when_done.destroy()
117
self.close_when_done = close_when_done
119
def toggle_colorize_event(self, event):
121
after_id = self.after_id
123
if DEBUG: print "cancel scheduled recolorizer"
124
self.after_cancel(after_id)
125
if self.allow_colorizing and self.colorizing:
126
if DEBUG: print "stop colorizing"
127
self.stop_colorizing = True
128
self.allow_colorizing = not self.allow_colorizing
129
if self.allow_colorizing and not self.colorizing:
130
self.after_id = self.after(1, self.recolorize)
132
print "auto colorizing turned",\
133
self.allow_colorizing and "on" or "off"
136
def recolorize(self):
138
if not self.delegate:
139
if DEBUG: print "no delegate"
141
if not self.allow_colorizing:
142
if DEBUG: print "auto colorizing is off"
145
if DEBUG: print "already colorizing"
148
self.stop_colorizing = False
149
self.colorizing = True
150
if DEBUG: print "colorizing..."
152
self.recolorize_main()
154
if DEBUG: print "%.3f seconds" % (t1-t0)
156
self.colorizing = False
157
if self.allow_colorizing and self.tag_nextrange("TODO", "1.0"):
158
if DEBUG: print "reschedule colorizing"
159
self.after_id = self.after(1, self.recolorize)
160
if self.close_when_done:
161
top = self.close_when_done
162
self.close_when_done = None
165
def recolorize_main(self):
168
item = self.tag_nextrange("TODO", next)
172
self.tag_remove("SYNC", head, tail)
173
item = self.tag_prevrange("SYNC", head)
185
next = self.index(mark + "+%d lines linestart" %
187
lines_to_get = min(lines_to_get * 2, 100)
188
ok = "SYNC" in self.tag_names(next + "-1c")
189
line = self.get(mark, next)
190
##print head, "get", mark, next, "->", repr(line)
193
for tag in self.tagdefs.keys():
194
self.tag_remove(tag, mark, next)
196
m = self.prog.search(chars)
198
for key, value in m.groupdict().items():
204
if value in ("def", "class"):
205
m1 = self.idprog.match(chars, b)
208
self.tag_add("DEFINITION",
211
elif value == "import":
212
# color all the "as" words on same line, except
213
# if in a comment; cheap approximation to the
216
endpos = chars.index('#')
220
m1 = self.asprog.match(chars, b, endpos)
224
self.tag_add("KEYWORD",
227
m = self.prog.search(chars, m.end())
228
if "SYNC" in self.tag_names(next + "-1c"):
234
# We're in an inconsistent state, and the call to
235
# update may tell us to stop. It may also change
236
# the correct value for "next" (since this is a
237
# line.col string, not a true mark). So leave a
238
# crumb telling the next invocation to resume here
239
# in case update tells us to leave.
240
self.tag_add("TODO", next)
242
if self.stop_colorizing:
243
if DEBUG: print "colorizing stopped"
246
def removecolors(self):
247
for tag in self.tagdefs.keys():
248
self.tag_remove(tag, "1.0", "end")
251
from Percolator import Percolator
253
root.wm_protocol("WM_DELETE_WINDOW", root.quit)
254
text = Text(background="white")
255
text.pack(expand=1, fill="both")
262
if __name__ == "__main__":