diff options
author | Guido van Rossum <guido@python.org> | 1998-10-10 18:48:31 (GMT) |
---|---|---|
committer | Guido van Rossum <guido@python.org> | 1998-10-10 18:48:31 (GMT) |
commit | 3b4ca0ddad8d1e224f71e89f4c7fbc8de5c6edc4 (patch) | |
tree | 1a66ed7c7eec87f31d61a2a083096e5cad89a39c /Tools/idle/ColorDelegator.py | |
parent | dc1adabcb86ee0813c9bae2d5cc59be5cad1ff31 (diff) | |
download | cpython-3b4ca0ddad8d1e224f71e89f4c7fbc8de5c6edc4.zip cpython-3b4ca0ddad8d1e224f71e89f4c7fbc8de5c6edc4.tar.gz cpython-3b4ca0ddad8d1e224f71e89f4c7fbc8de5c6edc4.tar.bz2 |
Initial checking of Tk-based Python IDE.
Features: text editor with syntax coloring and undo;
subclassed into interactive Python shell which adds history.
Diffstat (limited to 'Tools/idle/ColorDelegator.py')
-rw-r--r-- | Tools/idle/ColorDelegator.py | 203 |
1 files changed, 203 insertions, 0 deletions
diff --git a/Tools/idle/ColorDelegator.py b/Tools/idle/ColorDelegator.py new file mode 100644 index 0000000..0cbf2fb --- /dev/null +++ b/Tools/idle/ColorDelegator.py @@ -0,0 +1,203 @@ +import time +import string +import re +import keyword +from Tkinter import * +from Delegator import Delegator + +__debug__ = 0 + + +def any(name, list): + return "(?P<%s>" % name + string.join(list, "|") + ")" + +def make_pat(): + kw = r"\b" + any("KEYWORD", keyword.kwlist) + r"\b" + comment = any("COMMENT", [r"#[^\n]*"]) + sqstring = r"(\b[rR])?'([^'\\\n]|\\.)*'?" + dqstring = r'(\b[rR])?"([^"\\\n]|\\.)*"?' + sq3string = r"(\b[rR])?'''([^'\\]|\\.|'(?!''))*(''')?" + dq3string = r'(\b[rR])?"""([^"\\]|\\.|"(?!""))*(""")?' + string = any("STRING", [sq3string, dq3string, sqstring, dqstring]) + return kw + "|" + comment + "|" + string + "|" + any("SYNC", [r"\n"]) + +prog = re.compile(make_pat(), re.S) +idprog = re.compile(r"\s+(\w+)", re.S) + +class ColorDelegator(Delegator): + + def __init__(self): + Delegator.__init__(self) + self.prog = prog + self.idprog = idprog + + def setdelegate(self, delegate): + if self.delegate is not None: + self.unbind("<<toggle-auto-coloring>>") + Delegator.setdelegate(self, delegate) + if delegate is not None: + self.config_colors() + self.bind("<<toggle-auto-coloring>>", self.toggle_colorize_event) + self.notify_range("1.0", "end") + + def config_colors(self): + for tag, cnf in self.tagdefs.items(): + if cnf: + apply(self.tag_configure, (tag,), cnf) + + tagdefs = { + "COMMENT": {"foreground": "#dd0000"}, + "KEYWORD": {"foreground": "#ff7700"}, + "STRING": {"foreground": "#00aa00"}, + "DEFINITION": {"foreground": "#0000ff"}, + + "SYNC": {}, #{"background": "#ffff00"}, + "TODO": {}, #{"background": "#cccccc"}, + } + + def insert(self, index, chars, tags=None): + index = self.index(index) + self.delegate.insert(index, chars, tags) + self.notify_range(index, index + "+%dc" % len(chars)) + + def delete(self, index1, index2=None): + index1 = self.index(index1) + self.delegate.delete(index1, index2) + self.notify_range(index1) + + after_id = None + allow_colorizing = 1 + colorizing = 0 + + def notify_range(self, index1, index2=None): + self.tag_add("TODO", index1, index2) + if self.after_id: + if __debug__: print "colorizing already scheduled" + return + if self.colorizing: + self.stop_colorizing = 1 + if __debug__: print "stop colorizing" + if self.allow_colorizing: + if __debug__: print "schedule colorizing" + self.after_id = self.after(1, self.recolorize) + + def close(self): + if self.after_id: + after_id = self.after_id + self.after_id = None + if __debug__: print "cancel scheduled recolorizer" + self.after_cancel(after_id) + self.allow_colorizing = 0 + self.stop_colorizing = 1 + + def toggle_colorize_event(self, event): + if self.after_id: + after_id = self.after_id + self.after_id = None + if __debug__: print "cancel scheduled recolorizer" + self.after_cancel(after_id) + if self.allow_colorizing and self.colorizing: + if __debug__: print "stop colorizing" + self.stop_colorizing = 1 + self.allow_colorizing = not self.allow_colorizing + if self.allow_colorizing and not self.colorizing: + self.after_id = self.after(1, self.recolorize) + if __debug__: + print "auto colorizing turned", self.allow_colorizing and "on" or "off" + return "break" + + def recolorize(self): + self.after_id = None + if not self.delegate: + if __debug__: print "no delegate" + return + if not self.allow_colorizing: + if __debug__: print "auto colorizing is off" + return + if self.colorizing: + if __debug__: print "already colorizing" + return + try: + self.stop_colorizing = 0 + self.colorizing = 1 + if __debug__: print "colorizing..." + t0 = time.clock() + self.recolorize_main() + t1 = time.clock() + if __debug__: print "%.3f seconds" % (t1-t0) + finally: + self.colorizing = 0 + if self.allow_colorizing and self.tag_nextrange("TODO", "1.0"): + if __debug__: print "reschedule colorizing" + self.after_id = self.after(1, self.recolorize) + + def recolorize_main(self): + next = "1.0" + was_ok = is_ok = 0 + while 1: + item = self.tag_nextrange("TODO", next) + if not item: + break + head, tail = item + self.tag_remove("SYNC", head, tail) + item = self.tag_prevrange("SYNC", head) + if item: + head = item[1] + else: + head = "1.0" + + chars = "" + mark = head + is_ok = was_ok = 0 + while not (was_ok and is_ok): + next = self.index(mark + " lineend +1c") + was_ok = "SYNC" in self.tag_names(next + "-1c") + line = self.get(mark, next) + ##print head, "get", mark, next, "->", `line` + if not line: + return + for tag in self.tagdefs.keys(): + self.tag_remove(tag, mark, next) + chars = chars + line + m = self.prog.search(chars) + while m: + i, j = m.span() + for key, value in m.groupdict().items(): + if value: + a, b = m.span(key) + self.tag_add(key, + head + "+%dc" % a, + head + "+%dc" % b) + if value in ("def", "class"): + m1 = self.idprog.match(chars, b) + if m1: + a, b = m1.span(1) + self.tag_add("DEFINITION", + head + "+%dc" % a, + head + "+%dc" % b) + m = self.prog.search(chars, j) + is_ok = "SYNC" in self.tag_names(next + "-1c") + mark = next + if is_ok: + head = mark + chars = "" + self.update() + if self.stop_colorizing: + if __debug__: print "colorizing stopped" + return + + +def main(): + from Percolator import Percolator + root = Tk() + root.wm_protocol("WM_DELETE_WINDOW", root.quit) + text = Text(background="white") + text.pack(expand=1, fill="both") + text.focus_set() + p = Percolator(text) + d = ColorDelegator() + p.insertfilter(d) + root.mainloop() + +if __name__ == "__main__": + main() |