• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python
2"""Basic regular expression demonstration facility (Perl style syntax)."""
3
4from Tkinter import *
5import re
6
7class ReDemo:
8
9    def __init__(self, master):
10        self.master = master
11
12        self.promptdisplay = Label(self.master, anchor=W,
13                text="Enter a Perl-style regular expression:")
14        self.promptdisplay.pack(side=TOP, fill=X)
15
16        self.regexdisplay = Entry(self.master)
17        self.regexdisplay.pack(fill=X)
18        self.regexdisplay.focus_set()
19
20        self.addoptions()
21
22        self.statusdisplay = Label(self.master, text="", anchor=W)
23        self.statusdisplay.pack(side=TOP, fill=X)
24
25        self.labeldisplay = Label(self.master, anchor=W,
26                text="Enter a string to search:")
27        self.labeldisplay.pack(fill=X)
28        self.labeldisplay.pack(fill=X)
29
30        self.showframe = Frame(master)
31        self.showframe.pack(fill=X, anchor=W)
32
33        self.showvar = StringVar(master)
34        self.showvar.set("first")
35
36        self.showfirstradio = Radiobutton(self.showframe,
37                                         text="Highlight first match",
38                                          variable=self.showvar,
39                                          value="first",
40                                          command=self.recompile)
41        self.showfirstradio.pack(side=LEFT)
42
43        self.showallradio = Radiobutton(self.showframe,
44                                        text="Highlight all matches",
45                                        variable=self.showvar,
46                                        value="all",
47                                        command=self.recompile)
48        self.showallradio.pack(side=LEFT)
49
50        self.stringdisplay = Text(self.master, width=60, height=4)
51        self.stringdisplay.pack(fill=BOTH, expand=1)
52        self.stringdisplay.tag_configure("hit", background="yellow")
53
54        self.grouplabel = Label(self.master, text="Groups:", anchor=W)
55        self.grouplabel.pack(fill=X)
56
57        self.grouplist = Listbox(self.master)
58        self.grouplist.pack(expand=1, fill=BOTH)
59
60        self.regexdisplay.bind('<Key>', self.recompile)
61        self.stringdisplay.bind('<Key>', self.reevaluate)
62
63        self.compiled = None
64        self.recompile()
65
66        btags = self.regexdisplay.bindtags()
67        self.regexdisplay.bindtags(btags[1:] + btags[:1])
68
69        btags = self.stringdisplay.bindtags()
70        self.stringdisplay.bindtags(btags[1:] + btags[:1])
71
72    def addoptions(self):
73        self.frames = []
74        self.boxes = []
75        self.vars = []
76        for name in ('IGNORECASE',
77                     'LOCALE',
78                     'MULTILINE',
79                     'DOTALL',
80                     'VERBOSE'):
81            if len(self.boxes) % 3 == 0:
82                frame = Frame(self.master)
83                frame.pack(fill=X)
84                self.frames.append(frame)
85            val = getattr(re, name)
86            var = IntVar()
87            box = Checkbutton(frame,
88                    variable=var, text=name,
89                    offvalue=0, onvalue=val,
90                    command=self.recompile)
91            box.pack(side=LEFT)
92            self.boxes.append(box)
93            self.vars.append(var)
94
95    def getflags(self):
96        flags = 0
97        for var in self.vars:
98            flags = flags | var.get()
99        flags = flags
100        return flags
101
102    def recompile(self, event=None):
103        try:
104            self.compiled = re.compile(self.regexdisplay.get(),
105                                       self.getflags())
106            bg = self.promptdisplay['background']
107            self.statusdisplay.config(text="", background=bg)
108        except re.error, msg:
109            self.compiled = None
110            self.statusdisplay.config(
111                    text="re.error: %s" % str(msg),
112                    background="red")
113        self.reevaluate()
114
115    def reevaluate(self, event=None):
116        try:
117            self.stringdisplay.tag_remove("hit", "1.0", END)
118        except TclError:
119            pass
120        try:
121            self.stringdisplay.tag_remove("hit0", "1.0", END)
122        except TclError:
123            pass
124        self.grouplist.delete(0, END)
125        if not self.compiled:
126            return
127        self.stringdisplay.tag_configure("hit", background="yellow")
128        self.stringdisplay.tag_configure("hit0", background="orange")
129        text = self.stringdisplay.get("1.0", END)
130        last = 0
131        nmatches = 0
132        while last <= len(text):
133            m = self.compiled.search(text, last)
134            if m is None:
135                break
136            first, last = m.span()
137            if last == first:
138                last = first+1
139                tag = "hit0"
140            else:
141                tag = "hit"
142            pfirst = "1.0 + %d chars" % first
143            plast = "1.0 + %d chars" % last
144            self.stringdisplay.tag_add(tag, pfirst, plast)
145            if nmatches == 0:
146                self.stringdisplay.yview_pickplace(pfirst)
147                groups = list(m.groups())
148                groups.insert(0, m.group())
149                for i in range(len(groups)):
150                    g = "%2d: %r" % (i, groups[i])
151                    self.grouplist.insert(END, g)
152            nmatches = nmatches + 1
153            if self.showvar.get() == "first":
154                break
155
156        if nmatches == 0:
157            self.statusdisplay.config(text="(no match)",
158                                      background="yellow")
159        else:
160            self.statusdisplay.config(text="")
161
162
163# Main function, run when invoked as a stand-alone Python program.
164
165def main():
166    root = Tk()
167    demo = ReDemo(root)
168    root.protocol('WM_DELETE_WINDOW', root.quit)
169    root.mainloop()
170
171if __name__ == '__main__':
172    main()
173