summaryrefslogtreecommitdiffstats
path: root/Tools/idle/ColorDelegator.py
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>1998-10-10 18:48:31 (GMT)
committerGuido van Rossum <guido@python.org>1998-10-10 18:48:31 (GMT)
commit3b4ca0ddad8d1e224f71e89f4c7fbc8de5c6edc4 (patch)
tree1a66ed7c7eec87f31d61a2a083096e5cad89a39c /Tools/idle/ColorDelegator.py
parentdc1adabcb86ee0813c9bae2d5cc59be5cad1ff31 (diff)
downloadcpython-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.py203
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()