mirror of https://github.com/python/cpython
128 lines
3.7 KiB
Python
128 lines
3.7 KiB
Python
"""Basic regular expression demostration facility.
|
|
|
|
This displays a window with two type-in boxes. In the top box, you enter a
|
|
regular expression. In the bottom box, you enter a string. The first
|
|
match in the string of the regular expression is highlighted with a yellow
|
|
background (or red if the match is empty -- then the character at the match
|
|
is highlighted). The highlighting is continuously updated. At the bottom
|
|
are a number of checkboxes which control the regular expression syntax used
|
|
(see the regex_syntax module for descriptions). When there's no match, or
|
|
when the regular expression is syntactically incorrect, an error message is
|
|
displayed.
|
|
|
|
"""
|
|
|
|
from Tkinter import *
|
|
import regex
|
|
import regex_syntax
|
|
|
|
class RegexDemo:
|
|
|
|
def __init__(self, master):
|
|
self.master = master
|
|
self.topframe = Frame(self.master)
|
|
self.topframe.pack(fill=X)
|
|
self.promptdisplay = Label(self.topframe, text="Enter a regex:")
|
|
self.promptdisplay.pack(side=LEFT)
|
|
self.statusdisplay = Label(self.topframe, text="", anchor=W)
|
|
self.statusdisplay.pack(side=LEFT, fill=X)
|
|
self.regexdisplay = Entry(self.master)
|
|
self.regexdisplay.pack(fill=X)
|
|
self.regexdisplay.focus_set()
|
|
self.labeldisplay = Label(self.master, anchor=W,
|
|
text="Enter a string:")
|
|
self.labeldisplay.pack(fill=X)
|
|
self.labeldisplay.pack(fill=X)
|
|
self.stringdisplay = Text(self.master, width=60, height=4)
|
|
self.stringdisplay.pack(fill=BOTH, expand=1)
|
|
self.stringdisplay.tag_configure("hit", background="yellow")
|
|
self.addoptions()
|
|
self.regexdisplay.bind('<Key>', self.recompile)
|
|
self.stringdisplay.bind('<Key>', self.reevaluate)
|
|
self.compiled = None
|
|
self.recompile()
|
|
btags = self.regexdisplay.bindtags()
|
|
self.regexdisplay.bindtags(btags[1:] + btags[:1])
|
|
btags = self.stringdisplay.bindtags()
|
|
self.stringdisplay.bindtags(btags[1:] + btags[:1])
|
|
|
|
def addoptions(self):
|
|
self.frames = []
|
|
self.boxes = []
|
|
self.vars = []
|
|
for name in ( 'RE_NO_BK_PARENS',
|
|
'RE_NO_BK_VBAR',
|
|
'RE_BK_PLUS_QM',
|
|
'RE_TIGHT_VBAR',
|
|
'RE_NEWLINE_OR',
|
|
'RE_CONTEXT_INDEP_OPS'):
|
|
if len(self.boxes) % 3 == 0:
|
|
frame = Frame(self.master)
|
|
frame.pack(fill=X)
|
|
self.frames.append(frame)
|
|
val = getattr(regex_syntax, name)
|
|
var = IntVar()
|
|
box = Checkbutton(frame,
|
|
variable=var, text=name,
|
|
offvalue=0, onvalue=val,
|
|
command=self.newsyntax)
|
|
box.pack(side=LEFT)
|
|
self.boxes.append(box)
|
|
self.vars.append(var)
|
|
|
|
def newsyntax(self):
|
|
syntax = 0
|
|
for var in self.vars:
|
|
syntax = syntax | var.get()
|
|
regex.set_syntax(syntax)
|
|
self.recompile()
|
|
|
|
def recompile(self, event=None):
|
|
try:
|
|
self.compiled = regex.compile(self.regexdisplay.get())
|
|
self.statusdisplay.config(text="")
|
|
except regex.error, msg:
|
|
self.compiled = None
|
|
self.statusdisplay.config(text="regex.error: %s" % str(msg))
|
|
self.reevaluate()
|
|
|
|
def reevaluate(self, event=None):
|
|
try:
|
|
self.stringdisplay.tag_remove("hit", "1.0", END)
|
|
except TclError:
|
|
pass
|
|
if not self.compiled:
|
|
return
|
|
text = self.stringdisplay.get("1.0", END)
|
|
i = self.compiled.search(text)
|
|
if i < 0:
|
|
self.statusdisplay.config(text="(no match)")
|
|
else:
|
|
self.statusdisplay.config(text="")
|
|
regs = self.compiled.regs
|
|
first, last = regs[0]
|
|
if last == first:
|
|
last = first+1
|
|
self.stringdisplay.tag_configure("hit",
|
|
background="red")
|
|
else:
|
|
self.stringdisplay.tag_configure("hit",
|
|
background="yellow")
|
|
pfirst = "1.0 + %d chars" % first
|
|
plast = "1.0 + %d chars" % last
|
|
self.stringdisplay.tag_add("hit", pfirst, plast)
|
|
self.stringdisplay.yview_pickplace(pfirst)
|
|
|
|
|
|
|
|
# Main function, run when invoked as a stand-alone Python program.
|
|
|
|
def main():
|
|
root = Tk()
|
|
demo = RegexDemo(root)
|
|
root.protocol('WM_DELETE_WINDOW', root.quit)
|
|
root.mainloop()
|
|
|
|
if __name__ == '__main__':
|
|
main()
|