blob: b10b03021d035fe8da777d9d9d7c685cc0014b0f [file] [log] [blame]
Ned Deily3c6661a2012-08-18 12:21:17 -07001#!/usr/bin/env python3
2
Guido van Rossum70280b82000-10-06 17:37:12 +00003"""Basic regular expression demostration facility (Perl style syntax)."""
4
Benjamin Peterson903a65d2009-11-09 00:42:58 +00005from tkinter import *
Guido van Rossum70280b82000-10-06 17:37:12 +00006import re
7
8class ReDemo:
Guido van Rossum70280b82000-10-06 17:37:12 +00009
Tim Peters70c43782001-01-17 08:48:39 +000010 def __init__(self, master):
11 self.master = master
Guido van Rossum70280b82000-10-06 17:37:12 +000012
Tim Peters70c43782001-01-17 08:48:39 +000013 self.promptdisplay = Label(self.master, anchor=W,
14 text="Enter a Perl-style regular expression:")
15 self.promptdisplay.pack(side=TOP, fill=X)
Guido van Rossum70280b82000-10-06 17:37:12 +000016
Tim Peters70c43782001-01-17 08:48:39 +000017 self.regexdisplay = Entry(self.master)
18 self.regexdisplay.pack(fill=X)
19 self.regexdisplay.focus_set()
Guido van Rossum70280b82000-10-06 17:37:12 +000020
Tim Peters70c43782001-01-17 08:48:39 +000021 self.addoptions()
Guido van Rossum70280b82000-10-06 17:37:12 +000022
Tim Peters70c43782001-01-17 08:48:39 +000023 self.statusdisplay = Label(self.master, text="", anchor=W)
24 self.statusdisplay.pack(side=TOP, fill=X)
Guido van Rossum70280b82000-10-06 17:37:12 +000025
Tim Peters70c43782001-01-17 08:48:39 +000026 self.labeldisplay = Label(self.master, anchor=W,
27 text="Enter a string to search:")
28 self.labeldisplay.pack(fill=X)
29 self.labeldisplay.pack(fill=X)
Guido van Rossum70280b82000-10-06 17:37:12 +000030
Tim Peters70c43782001-01-17 08:48:39 +000031 self.showframe = Frame(master)
32 self.showframe.pack(fill=X, anchor=W)
Guido van Rossum70280b82000-10-06 17:37:12 +000033
Tim Peters70c43782001-01-17 08:48:39 +000034 self.showvar = StringVar(master)
35 self.showvar.set("first")
Guido van Rossum70280b82000-10-06 17:37:12 +000036
Tim Peters70c43782001-01-17 08:48:39 +000037 self.showfirstradio = Radiobutton(self.showframe,
38 text="Highlight first match",
39 variable=self.showvar,
40 value="first",
41 command=self.recompile)
42 self.showfirstradio.pack(side=LEFT)
Guido van Rossum70280b82000-10-06 17:37:12 +000043
Tim Peters70c43782001-01-17 08:48:39 +000044 self.showallradio = Radiobutton(self.showframe,
45 text="Highlight all matches",
46 variable=self.showvar,
47 value="all",
48 command=self.recompile)
49 self.showallradio.pack(side=LEFT)
Guido van Rossum70280b82000-10-06 17:37:12 +000050
Tim Peters70c43782001-01-17 08:48:39 +000051 self.stringdisplay = Text(self.master, width=60, height=4)
52 self.stringdisplay.pack(fill=BOTH, expand=1)
53 self.stringdisplay.tag_configure("hit", background="yellow")
Guido van Rossum70280b82000-10-06 17:37:12 +000054
Tim Peters70c43782001-01-17 08:48:39 +000055 self.grouplabel = Label(self.master, text="Groups:", anchor=W)
56 self.grouplabel.pack(fill=X)
Guido van Rossum70280b82000-10-06 17:37:12 +000057
Tim Peters70c43782001-01-17 08:48:39 +000058 self.grouplist = Listbox(self.master)
59 self.grouplist.pack(expand=1, fill=BOTH)
Guido van Rossum70280b82000-10-06 17:37:12 +000060
Tim Peters70c43782001-01-17 08:48:39 +000061 self.regexdisplay.bind('<Key>', self.recompile)
62 self.stringdisplay.bind('<Key>', self.reevaluate)
Guido van Rossum70280b82000-10-06 17:37:12 +000063
Tim Peters70c43782001-01-17 08:48:39 +000064 self.compiled = None
65 self.recompile()
Guido van Rossum70280b82000-10-06 17:37:12 +000066
Tim Peters70c43782001-01-17 08:48:39 +000067 btags = self.regexdisplay.bindtags()
68 self.regexdisplay.bindtags(btags[1:] + btags[:1])
Guido van Rossum70280b82000-10-06 17:37:12 +000069
Tim Peters70c43782001-01-17 08:48:39 +000070 btags = self.stringdisplay.bindtags()
71 self.stringdisplay.bindtags(btags[1:] + btags[:1])
72
73 def addoptions(self):
74 self.frames = []
75 self.boxes = []
76 self.vars = []
77 for name in ('IGNORECASE',
78 'LOCALE',
79 'MULTILINE',
80 'DOTALL',
81 'VERBOSE'):
82 if len(self.boxes) % 3 == 0:
83 frame = Frame(self.master)
84 frame.pack(fill=X)
85 self.frames.append(frame)
86 val = getattr(re, name)
87 var = IntVar()
88 box = Checkbutton(frame,
89 variable=var, text=name,
90 offvalue=0, onvalue=val,
91 command=self.recompile)
92 box.pack(side=LEFT)
93 self.boxes.append(box)
94 self.vars.append(var)
95
96 def getflags(self):
97 flags = 0
98 for var in self.vars:
99 flags = flags | var.get()
100 flags = flags
101 return flags
102
103 def recompile(self, event=None):
104 try:
105 self.compiled = re.compile(self.regexdisplay.get(),
106 self.getflags())
107 bg = self.promptdisplay['background']
108 self.statusdisplay.config(text="", background=bg)
Guido van Rossumb940e112007-01-10 16:19:56 +0000109 except re.error as msg:
Tim Peters70c43782001-01-17 08:48:39 +0000110 self.compiled = None
111 self.statusdisplay.config(
112 text="re.error: %s" % str(msg),
113 background="red")
114 self.reevaluate()
115
116 def reevaluate(self, event=None):
117 try:
118 self.stringdisplay.tag_remove("hit", "1.0", END)
119 except TclError:
120 pass
121 try:
122 self.stringdisplay.tag_remove("hit0", "1.0", END)
123 except TclError:
124 pass
125 self.grouplist.delete(0, END)
126 if not self.compiled:
127 return
128 self.stringdisplay.tag_configure("hit", background="yellow")
129 self.stringdisplay.tag_configure("hit0", background="orange")
130 text = self.stringdisplay.get("1.0", END)
131 last = 0
132 nmatches = 0
133 while last <= len(text):
134 m = self.compiled.search(text, last)
135 if m is None:
136 break
137 first, last = m.span()
138 if last == first:
139 last = first+1
140 tag = "hit0"
141 else:
142 tag = "hit"
143 pfirst = "1.0 + %d chars" % first
144 plast = "1.0 + %d chars" % last
145 self.stringdisplay.tag_add(tag, pfirst, plast)
146 if nmatches == 0:
147 self.stringdisplay.yview_pickplace(pfirst)
148 groups = list(m.groups())
149 groups.insert(0, m.group())
150 for i in range(len(groups)):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000151 g = "%2d: %r" % (i, groups[i])
Tim Peters70c43782001-01-17 08:48:39 +0000152 self.grouplist.insert(END, g)
153 nmatches = nmatches + 1
154 if self.showvar.get() == "first":
155 break
156
157 if nmatches == 0:
158 self.statusdisplay.config(text="(no match)",
159 background="yellow")
160 else:
161 self.statusdisplay.config(text="")
Guido van Rossum70280b82000-10-06 17:37:12 +0000162
163
164# Main function, run when invoked as a stand-alone Python program.
165
166def main():
167 root = Tk()
168 demo = ReDemo(root)
169 root.protocol('WM_DELETE_WINDOW', root.quit)
170 root.mainloop()
171
172if __name__ == '__main__':
173 main()