1#!/usr/bin/env python3 2 3"""Basic regular expression demonstration facility (Perl style syntax).""" 4 5from tkinter import * 6import re 7 8class ReDemo: 9 10 def __init__(self, master): 11 self.master = master 12 13 self.promptdisplay = Label(self.master, anchor=W, 14 text="Enter a Perl-style regular expression:") 15 self.promptdisplay.pack(side=TOP, fill=X) 16 17 self.regexdisplay = Entry(self.master) 18 self.regexdisplay.pack(fill=X) 19 self.regexdisplay.focus_set() 20 21 self.addoptions() 22 23 self.statusdisplay = Label(self.master, text="", anchor=W) 24 self.statusdisplay.pack(side=TOP, fill=X) 25 26 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) 30 31 self.showframe = Frame(master) 32 self.showframe.pack(fill=X, anchor=W) 33 34 self.showvar = StringVar(master) 35 self.showvar.set("first") 36 37 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) 43 44 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) 50 51 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") 54 55 self.grouplabel = Label(self.master, text="Groups:", anchor=W) 56 self.grouplabel.pack(fill=X) 57 58 self.grouplist = Listbox(self.master) 59 self.grouplist.pack(expand=1, fill=BOTH) 60 61 self.regexdisplay.bind('<Key>', self.recompile) 62 self.stringdisplay.bind('<Key>', self.reevaluate) 63 64 self.compiled = None 65 self.recompile() 66 67 btags = self.regexdisplay.bindtags() 68 self.regexdisplay.bindtags(btags[1:] + btags[:1]) 69 70 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) 109 except re.error as msg: 110 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)): 151 g = "%2d: %r" % (i, groups[i]) 152 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="") 162 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() 174