6 from Delegator
import Delegator
9 #$ event <<toggle-auto-coloring>>
10 #$ win <Control-slash>
11 #$ unix <Control-slash>
17 return "(?P<%s>" % name
+ string
.join(list, "|") + ")"
20 kw
= r
"\b" + any("KEYWORD", keyword
.kwlist
) + r
"\b"
21 comment
= any("COMMENT", [r
"#[^\n]*"])
22 sqstring
= r
"(\b[rR])?'[^'\\\n]*(\\.[^'\\\n]*)*'?"
23 dqstring
= r
'(\b[rR])?"[^"\\\n]*(\\.[^"\\\n]*)*"?'
24 sq3string
= r
"(\b[rR])?'''[^'\\]*((\\.|'(?!''))[^'\\]*)*(''')?"
25 dq3string
= r
'(\b[rR])?"""[^"\\]*((\\.|"(?!""))[^"\\]*)*(""")?'
26 string
= any("STRING", [sq3string
, dq3string
, sqstring
, dqstring
])
27 return kw
+ "|" + comment
+ "|" + string
+ "|" + any("SYNC", [r
"\n"])
29 prog
= re
.compile(make_pat(), re
.S
)
30 idprog
= re
.compile(r
"\s+(\w+)", re
.S
)
32 class ColorDelegator(Delegator
):
35 Delegator
.__init
__(self
)
39 def setdelegate(self
, delegate
):
40 if self
.delegate
is not None:
41 self
.unbind("<<toggle-auto-coloring>>")
42 Delegator
.setdelegate(self
, delegate
)
43 if delegate
is not None:
45 self
.bind("<<toggle-auto-coloring>>", self
.toggle_colorize_event
)
46 self
.notify_range("1.0", "end")
48 def config_colors(self
):
49 for tag
, cnf
in self
.tagdefs
.items():
51 apply(self
.tag_configure
, (tag
,), cnf
)
54 cprefs
= IdlePrefs
.ColorPrefs()
57 "COMMENT": {"foreground": cprefs
.CComment
[0],
58 "background": cprefs
.CComment
[1]},
59 "KEYWORD": {"foreground": cprefs
.CKeyword
[0],
60 "background": cprefs
.CKeyword
[1]},
61 "STRING": {"foreground": cprefs
.CString
[0],
62 "background": cprefs
.CString
[1]},
63 "DEFINITION": {"foreground": cprefs
.CDefinition
[0],
64 "background": cprefs
.CDefinition
[1]},
66 "SYNC": {"background": cprefs
.CSync
[0],
67 "background": cprefs
.CSync
[1]},
68 "TODO": {"background": cprefs
.CTodo
[0],
69 "background": cprefs
.CTodo
[1]},
71 "BREAK": {"background": cprefs
.CBreak
[0],
72 "background": cprefs
.CBreak
[1]},
74 # The following is used by ReplaceDialog:
75 "hit": {"foreground": cprefs
.CHit
[0],
76 "background": cprefs
.CHit
[1]},
79 def insert(self
, index
, chars
, tags
=None):
80 index
= self
.index(index
)
81 self
.delegate
.insert(index
, chars
, tags
)
82 self
.notify_range(index
, index
+ "+%dc" % len(chars
))
84 def delete(self
, index1
, index2
=None):
85 index1
= self
.index(index1
)
86 self
.delegate
.delete(index1
, index2
)
87 self
.notify_range(index1
)
93 def notify_range(self
, index1
, index2
=None):
94 self
.tag_add("TODO", index1
, index2
)
96 if __debug__
: print "colorizing already scheduled"
99 self
.stop_colorizing
= 1
100 if __debug__
: print "stop colorizing"
101 if self
.allow_colorizing
:
102 if __debug__
: print "schedule colorizing"
103 self
.after_id
= self
.after(1, self
.recolorize
)
105 close_when_done
= None # Window to be closed when done colorizing
107 def close(self
, close_when_done
=None):
109 after_id
= self
.after_id
111 if __debug__
: print "cancel scheduled recolorizer"
112 self
.after_cancel(after_id
)
113 self
.allow_colorizing
= 0
114 self
.stop_colorizing
= 1
116 if not self
.colorizing
:
117 close_when_done
.destroy()
119 self
.close_when_done
= close_when_done
121 def toggle_colorize_event(self
, event
):
123 after_id
= self
.after_id
125 if __debug__
: print "cancel scheduled recolorizer"
126 self
.after_cancel(after_id
)
127 if self
.allow_colorizing
and self
.colorizing
:
128 if __debug__
: print "stop colorizing"
129 self
.stop_colorizing
= 1
130 self
.allow_colorizing
= not self
.allow_colorizing
131 if self
.allow_colorizing
and not self
.colorizing
:
132 self
.after_id
= self
.after(1, self
.recolorize
)
134 print "auto colorizing turned", self
.allow_colorizing
and "on" or "off"
137 def recolorize(self
):
139 if not self
.delegate
:
140 if __debug__
: print "no delegate"
142 if not self
.allow_colorizing
:
143 if __debug__
: print "auto colorizing is off"
146 if __debug__
: print "already colorizing"
149 self
.stop_colorizing
= 0
151 if __debug__
: print "colorizing..."
153 self
.recolorize_main()
155 if __debug__
: print "%.3f seconds" % (t1
-t0
)
158 if self
.allow_colorizing
and self
.tag_nextrange("TODO", "1.0"):
159 if __debug__
: print "reschedule colorizing"
160 self
.after_id
= self
.after(1, self
.recolorize
)
161 if self
.close_when_done
:
162 top
= self
.close_when_done
163 self
.close_when_done
= None
166 def recolorize_main(self
):
169 item
= self
.tag_nextrange("TODO", next
)
173 self
.tag_remove("SYNC", head
, tail
)
174 item
= self
.tag_prevrange("SYNC", head
)
186 next
= self
.index(mark
+ "+%d lines linestart" %
188 lines_to_get
= min(lines_to_get
* 2, 100)
189 ok
= "SYNC" in self
.tag_names(next
+ "-1c")
190 line
= self
.get(mark
, next
)
191 ##print head, "get", mark, next, "->", `line`
194 for tag
in self
.tagdefs
.keys():
195 self
.tag_remove(tag
, mark
, next
)
197 m
= self
.prog
.search(chars
)
199 for key
, value
in m
.groupdict().items():
205 if value
in ("def", "class"):
206 m1
= self
.idprog
.match(chars
, b
)
209 self
.tag_add("DEFINITION",
212 m
= self
.prog
.search(chars
, m
.end())
213 if "SYNC" in self
.tag_names(next
+ "-1c"):
219 # We're in an inconsistent state, and the call to
220 # update may tell us to stop. It may also change
221 # the correct value for "next" (since this is a
222 # line.col string, not a true mark). So leave a
223 # crumb telling the next invocation to resume here
224 # in case update tells us to leave.
225 self
.tag_add("TODO", next
)
227 if self
.stop_colorizing
:
228 if __debug__
: print "colorizing stopped"
233 from Percolator
import Percolator
235 root
.wm_protocol("WM_DELETE_WINDOW", root
.quit
)
236 text
= Text(background
="white")
237 text
.pack(expand
=1, fill
="both")
244 if __name__
== "__main__":