~malept/ubuntu/lucid/python2.6/dev-dependency-fix

« back to all changes in this revision

Viewing changes to Lib/idlelib/ColorDelegator.py

  • Committer: Bazaar Package Importer
  • Author(s): Matthias Klose
  • Date: 2009-02-13 12:51:00 UTC
  • Revision ID: james.westby@ubuntu.com-20090213125100-uufgcb9yeqzujpqw
Tags: upstream-2.6.1
ImportĀ upstreamĀ versionĀ 2.6.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
import time
 
2
import re
 
3
import keyword
 
4
import __builtin__
 
5
from Tkinter import *
 
6
from Delegator import Delegator
 
7
from configHandler import idleConf
 
8
 
 
9
DEBUG = False
 
10
 
 
11
def any(name, alternates):
 
12
    "Return a named group pattern matching list of alternates."
 
13
    return "(?P<%s>" % name + "|".join(alternates) + ")"
 
14
 
 
15
def make_pat():
 
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"])
 
30
 
 
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")
 
34
 
 
35
class ColorDelegator(Delegator):
 
36
 
 
37
    def __init__(self):
 
38
        Delegator.__init__(self)
 
39
        self.prog = prog
 
40
        self.idprog = idprog
 
41
        self.asprog = asprog
 
42
        self.LoadTagDefs()
 
43
 
 
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:
 
49
            self.config_colors()
 
50
            self.bind("<<toggle-auto-coloring>>", self.toggle_colorize_event)
 
51
            self.notify_range("1.0", "end")
 
52
 
 
53
    def config_colors(self):
 
54
        for tag, cnf in self.tagdefs.items():
 
55
            if cnf:
 
56
                self.tag_configure(tag, **cnf)
 
57
        self.tag_raise('sel')
 
58
 
 
59
    def LoadTagDefs(self):
 
60
        theme = idleConf.GetOption('main','Theme','name')
 
61
        self.tagdefs = {
 
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"),
 
73
            }
 
74
 
 
75
        if DEBUG: print 'tagdefs',self.tagdefs
 
76
 
 
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))
 
81
 
 
82
    def delete(self, index1, index2=None):
 
83
        index1 = self.index(index1)
 
84
        self.delegate.delete(index1, index2)
 
85
        self.notify_range(index1)
 
86
 
 
87
    after_id = None
 
88
    allow_colorizing = True
 
89
    colorizing = False
 
90
 
 
91
    def notify_range(self, index1, index2=None):
 
92
        self.tag_add("TODO", index1, index2)
 
93
        if self.after_id:
 
94
            if DEBUG: print "colorizing already scheduled"
 
95
            return
 
96
        if self.colorizing:
 
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)
 
102
 
 
103
    close_when_done = None # Window to be closed when done colorizing
 
104
 
 
105
    def close(self, close_when_done=None):
 
106
        if self.after_id:
 
107
            after_id = self.after_id
 
108
            self.after_id = None
 
109
            if DEBUG: print "cancel scheduled recolorizer"
 
110
            self.after_cancel(after_id)
 
111
        self.allow_colorizing = False
 
112
        self.stop_colorizing = True
 
113
        if close_when_done:
 
114
            if not self.colorizing:
 
115
                close_when_done.destroy()
 
116
            else:
 
117
                self.close_when_done = close_when_done
 
118
 
 
119
    def toggle_colorize_event(self, event):
 
120
        if self.after_id:
 
121
            after_id = self.after_id
 
122
            self.after_id = None
 
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)
 
131
        if DEBUG:
 
132
            print "auto colorizing turned",\
 
133
                  self.allow_colorizing and "on" or "off"
 
134
        return "break"
 
135
 
 
136
    def recolorize(self):
 
137
        self.after_id = None
 
138
        if not self.delegate:
 
139
            if DEBUG: print "no delegate"
 
140
            return
 
141
        if not self.allow_colorizing:
 
142
            if DEBUG: print "auto colorizing is off"
 
143
            return
 
144
        if self.colorizing:
 
145
            if DEBUG: print "already colorizing"
 
146
            return
 
147
        try:
 
148
            self.stop_colorizing = False
 
149
            self.colorizing = True
 
150
            if DEBUG: print "colorizing..."
 
151
            t0 = time.clock()
 
152
            self.recolorize_main()
 
153
            t1 = time.clock()
 
154
            if DEBUG: print "%.3f seconds" % (t1-t0)
 
155
        finally:
 
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
 
163
            top.destroy()
 
164
 
 
165
    def recolorize_main(self):
 
166
        next = "1.0"
 
167
        while True:
 
168
            item = self.tag_nextrange("TODO", next)
 
169
            if not item:
 
170
                break
 
171
            head, tail = item
 
172
            self.tag_remove("SYNC", head, tail)
 
173
            item = self.tag_prevrange("SYNC", head)
 
174
            if item:
 
175
                head = item[1]
 
176
            else:
 
177
                head = "1.0"
 
178
 
 
179
            chars = ""
 
180
            next = head
 
181
            lines_to_get = 1
 
182
            ok = False
 
183
            while not ok:
 
184
                mark = next
 
185
                next = self.index(mark + "+%d lines linestart" %
 
186
                                         lines_to_get)
 
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)
 
191
                if not line:
 
192
                    return
 
193
                for tag in self.tagdefs.keys():
 
194
                    self.tag_remove(tag, mark, next)
 
195
                chars = chars + line
 
196
                m = self.prog.search(chars)
 
197
                while m:
 
198
                    for key, value in m.groupdict().items():
 
199
                        if value:
 
200
                            a, b = m.span(key)
 
201
                            self.tag_add(key,
 
202
                                         head + "+%dc" % a,
 
203
                                         head + "+%dc" % b)
 
204
                            if value in ("def", "class"):
 
205
                                m1 = self.idprog.match(chars, b)
 
206
                                if m1:
 
207
                                    a, b = m1.span(1)
 
208
                                    self.tag_add("DEFINITION",
 
209
                                                 head + "+%dc" % a,
 
210
                                                 head + "+%dc" % b)
 
211
                            elif value == "import":
 
212
                                # color all the "as" words on same line, except
 
213
                                # if in a comment; cheap approximation to the
 
214
                                # truth
 
215
                                if '#' in chars:
 
216
                                    endpos = chars.index('#')
 
217
                                else:
 
218
                                    endpos = len(chars)
 
219
                                while True:
 
220
                                    m1 = self.asprog.match(chars, b, endpos)
 
221
                                    if not m1:
 
222
                                        break
 
223
                                    a, b = m1.span(1)
 
224
                                    self.tag_add("KEYWORD",
 
225
                                                 head + "+%dc" % a,
 
226
                                                 head + "+%dc" % b)
 
227
                    m = self.prog.search(chars, m.end())
 
228
                if "SYNC" in self.tag_names(next + "-1c"):
 
229
                    head = next
 
230
                    chars = ""
 
231
                else:
 
232
                    ok = False
 
233
                if not ok:
 
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)
 
241
                self.update()
 
242
                if self.stop_colorizing:
 
243
                    if DEBUG: print "colorizing stopped"
 
244
                    return
 
245
 
 
246
    def removecolors(self):
 
247
        for tag in self.tagdefs.keys():
 
248
            self.tag_remove(tag, "1.0", "end")
 
249
 
 
250
def main():
 
251
    from Percolator import Percolator
 
252
    root = Tk()
 
253
    root.wm_protocol("WM_DELETE_WINDOW", root.quit)
 
254
    text = Text(background="white")
 
255
    text.pack(expand=1, fill="both")
 
256
    text.focus_set()
 
257
    p = Percolator(text)
 
258
    d = ColorDelegator()
 
259
    p.insertfilter(d)
 
260
    root.mainloop()
 
261
 
 
262
if __name__ == "__main__":
 
263
    main()