Home | History | Annotate | Download | only in scripts
      1 #!/usr/bin/env python
      2 """Basic regular expression demonstration facility (Perl style syntax)."""
      3 
      4 from Tkinter import *
      5 import re
      6 
      7 class 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 
    165 def main():
    166     root = Tk()
    167     demo = ReDemo(root)
    168     root.protocol('WM_DELETE_WINDOW', root.quit)
    169     root.mainloop()
    170 
    171 if __name__ == '__main__':
    172     main()
    173