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