Home | History | Annotate | Download | only in idlelib
      1 from __future__ import print_function
      2 import os
      3 import fnmatch
      4 import re  # for htest
      5 import sys
      6 from Tkinter import StringVar, BooleanVar, Checkbutton  # for GrepDialog
      7 from Tkinter import Tk, Text, Button, SEL, END  # for htest
      8 from idlelib import SearchEngine
      9 from idlelib.SearchDialogBase import SearchDialogBase
     10 # Importing OutputWindow fails due to import loop
     11 # EditorWindow -> GrepDialop -> OutputWindow -> EditorWindow
     12 
     13 def grep(text, io=None, flist=None):
     14     root = text._root()
     15     engine = SearchEngine.get(root)
     16     if not hasattr(engine, "_grepdialog"):
     17         engine._grepdialog = GrepDialog(root, engine, flist)
     18     dialog = engine._grepdialog
     19     searchphrase = text.get("sel.first", "sel.last")
     20     dialog.open(text, searchphrase, io)
     21 
     22 class GrepDialog(SearchDialogBase):
     23 
     24     title = "Find in Files Dialog"
     25     icon = "Grep"
     26     needwrapbutton = 0
     27 
     28     def __init__(self, root, engine, flist):
     29         SearchDialogBase.__init__(self, root, engine)
     30         self.flist = flist
     31         self.globvar = StringVar(root)
     32         self.recvar = BooleanVar(root)
     33 
     34     def open(self, text, searchphrase, io=None):
     35         SearchDialogBase.open(self, text, searchphrase)
     36         if io:
     37             path = io.filename or ""
     38         else:
     39             path = ""
     40         dir, base = os.path.split(path)
     41         head, tail = os.path.splitext(base)
     42         if not tail:
     43             tail = ".py"
     44         self.globvar.set(os.path.join(dir, "*" + tail))
     45 
     46     def create_entries(self):
     47         SearchDialogBase.create_entries(self)
     48         self.globent = self.make_entry("In files:", self.globvar)[0]
     49 
     50     def create_other_buttons(self):
     51         f = self.make_frame()[0]
     52 
     53         btn = Checkbutton(f, anchor="w",
     54                 variable=self.recvar,
     55                 text="Recurse down subdirectories")
     56         btn.pack(side="top", fill="both")
     57         btn.select()
     58 
     59     def create_command_buttons(self):
     60         SearchDialogBase.create_command_buttons(self)
     61         self.make_button("Search Files", self.default_command, 1)
     62 
     63     def default_command(self, event=None):
     64         prog = self.engine.getprog()
     65         if not prog:
     66             return
     67         path = self.globvar.get()
     68         if not path:
     69             self.top.bell()
     70             return
     71         from idlelib.OutputWindow import OutputWindow  # leave here!
     72         save = sys.stdout
     73         try:
     74             sys.stdout = OutputWindow(self.flist)
     75             self.grep_it(prog, path)
     76         finally:
     77             sys.stdout = save
     78 
     79     def grep_it(self, prog, path):
     80         dir, base = os.path.split(path)
     81         list = self.findfiles(dir, base, self.recvar.get())
     82         list.sort()
     83         self.close()
     84         pat = self.engine.getpat()
     85         print("Searching %r in %s ..." % (pat, path))
     86         hits = 0
     87         try:
     88             for fn in list:
     89                 try:
     90                     with open(fn) as f:
     91                         for lineno, line in enumerate(f, 1):
     92                             if line[-1:] == '\n':
     93                                 line = line[:-1]
     94                             if prog.search(line):
     95                                 sys.stdout.write("%s: %s: %s\n" %
     96                                                  (fn, lineno, line))
     97                                 hits += 1
     98                 except IOError as msg:
     99                     print(msg)
    100             print(("Hits found: %s\n"
    101                   "(Hint: right-click to open locations.)"
    102                   % hits) if hits else "No hits.")
    103         except AttributeError:
    104             # Tk window has been closed, OutputWindow.text = None,
    105             # so in OW.write, OW.text.insert fails.
    106             pass
    107 
    108     def findfiles(self, dir, base, rec):
    109         try:
    110             names = os.listdir(dir or os.curdir)
    111         except os.error as msg:
    112             print(msg)
    113             return []
    114         list = []
    115         subdirs = []
    116         for name in names:
    117             fn = os.path.join(dir, name)
    118             if os.path.isdir(fn):
    119                 subdirs.append(fn)
    120             else:
    121                 if fnmatch.fnmatch(name, base):
    122                     list.append(fn)
    123         if rec:
    124             for subdir in subdirs:
    125                 list.extend(self.findfiles(subdir, base, rec))
    126         return list
    127 
    128     def close(self, event=None):
    129         if self.top:
    130             self.top.grab_release()
    131             self.top.withdraw()
    132 
    133 
    134 def _grep_dialog(parent):  # htest #
    135     from idlelib.PyShell import PyShellFileList
    136     root = Tk()
    137     root.title("Test GrepDialog")
    138     width, height, x, y = list(map(int, re.split('[x+]', parent.geometry())))
    139     root.geometry("+%d+%d"%(x, y + 150))
    140 
    141     flist = PyShellFileList(root)
    142     text = Text(root, height=5)
    143     text.pack()
    144 
    145     def show_grep_dialog():
    146         text.tag_add(SEL, "1.0", END)
    147         grep(text, flist=flist)
    148         text.tag_remove(SEL, "1.0", END)
    149 
    150     button = Button(root, text="Show GrepDialog", command=show_grep_dialog)
    151     button.pack()
    152     root.mainloop()
    153 
    154 if __name__ == "__main__":
    155     import unittest
    156     unittest.main('idlelib.idle_test.test_grep', verbosity=2, exit=False)
    157 
    158     from idlelib.idle_test.htest import run
    159     run(_grep_dialog)
    160