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