Home | History | Annotate | Download | only in idlelib
      1 import os
      2 import fnmatch
      3 import sys
      4 from Tkinter import *
      5 from idlelib import SearchEngine
      6 from idlelib.SearchDialogBase import SearchDialogBase
      7 
      8 def grep(text, io=None, flist=None):
      9     root = text._root()
     10     engine = SearchEngine.get(root)
     11     if not hasattr(engine, "_grepdialog"):
     12         engine._grepdialog = GrepDialog(root, engine, flist)
     13     dialog = engine._grepdialog
     14     searchphrase = text.get("sel.first", "sel.last")
     15     dialog.open(text, searchphrase, io)
     16 
     17 class GrepDialog(SearchDialogBase):
     18 
     19     title = "Find in Files Dialog"
     20     icon = "Grep"
     21     needwrapbutton = 0
     22 
     23     def __init__(self, root, engine, flist):
     24         SearchDialogBase.__init__(self, root, engine)
     25         self.flist = flist
     26         self.globvar = StringVar(root)
     27         self.recvar = BooleanVar(root)
     28 
     29     def open(self, text, searchphrase, io=None):
     30         SearchDialogBase.open(self, text, searchphrase)
     31         if io:
     32             path = io.filename or ""
     33         else:
     34             path = ""
     35         dir, base = os.path.split(path)
     36         head, tail = os.path.splitext(base)
     37         if not tail:
     38             tail = ".py"
     39         self.globvar.set(os.path.join(dir, "*" + tail))
     40 
     41     def create_entries(self):
     42         SearchDialogBase.create_entries(self)
     43         self.globent = self.make_entry("In files:", self.globvar)
     44 
     45     def create_other_buttons(self):
     46         f = self.make_frame()
     47 
     48         btn = Checkbutton(f, anchor="w",
     49                 variable=self.recvar,
     50                 text="Recurse down subdirectories")
     51         btn.pack(side="top", fill="both")
     52         btn.select()
     53 
     54     def create_command_buttons(self):
     55         SearchDialogBase.create_command_buttons(self)
     56         self.make_button("Search Files", self.default_command, 1)
     57 
     58     def default_command(self, event=None):
     59         prog = self.engine.getprog()
     60         if not prog:
     61             return
     62         path = self.globvar.get()
     63         if not path:
     64             self.top.bell()
     65             return
     66         from idlelib.OutputWindow import OutputWindow
     67         save = sys.stdout
     68         try:
     69             sys.stdout = OutputWindow(self.flist)
     70             self.grep_it(prog, path)
     71         finally:
     72             sys.stdout = save
     73 
     74     def grep_it(self, prog, path):
     75         dir, base = os.path.split(path)
     76         list = self.findfiles(dir, base, self.recvar.get())
     77         list.sort()
     78         self.close()
     79         pat = self.engine.getpat()
     80         print "Searching %r in %s ..." % (pat, path)
     81         hits = 0
     82         for fn in list:
     83             try:
     84                 f = open(fn)
     85             except IOError, msg:
     86                 print msg
     87                 continue
     88             lineno = 0
     89             while 1:
     90                 block = f.readlines(100000)
     91                 if not block:
     92                     break
     93                 for line in block:
     94                     lineno = lineno + 1
     95                     if line[-1:] == '\n':
     96                         line = line[:-1]
     97                     if prog.search(line):
     98                         sys.stdout.write("%s: %s: %s\n" % (fn, lineno, line))
     99                         hits = hits + 1
    100         if hits:
    101             if hits == 1:
    102                 s = ""
    103             else:
    104                 s = "s"
    105             print "Found", hits, "hit%s." % s
    106             print "(Hint: right-click to open locations.)"
    107         else:
    108             print "No hits."
    109 
    110     def findfiles(self, dir, base, rec):
    111         try:
    112             names = os.listdir(dir or os.curdir)
    113         except os.error, msg:
    114             print msg
    115             return []
    116         list = []
    117         subdirs = []
    118         for name in names:
    119             fn = os.path.join(dir, name)
    120             if os.path.isdir(fn):
    121                 subdirs.append(fn)
    122             else:
    123                 if fnmatch.fnmatch(name, base):
    124                     list.append(fn)
    125         if rec:
    126             for subdir in subdirs:
    127                 list.extend(self.findfiles(subdir, base, rec))
    128         return list
    129 
    130     def close(self, event=None):
    131         if self.top:
    132             self.top.grab_release()
    133             self.top.withdraw()
    134