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__":