10a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoimport os
20a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoimport fnmatch
30a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoimport sys
40a8c90248264a8b26970b4473770bcc3df8515fJosh Gaofrom Tkinter import *
50a8c90248264a8b26970b4473770bcc3df8515fJosh Gaofrom idlelib import SearchEngine
60a8c90248264a8b26970b4473770bcc3df8515fJosh Gaofrom idlelib.SearchDialogBase import SearchDialogBase
70a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
80a8c90248264a8b26970b4473770bcc3df8515fJosh Gaodef grep(text, io=None, flist=None):
90a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    root = text._root()
100a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    engine = SearchEngine.get(root)
110a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    if not hasattr(engine, "_grepdialog"):
120a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        engine._grepdialog = GrepDialog(root, engine, flist)
130a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    dialog = engine._grepdialog
140a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    searchphrase = text.get("sel.first", "sel.last")
150a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    dialog.open(text, searchphrase, io)
160a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
170a8c90248264a8b26970b4473770bcc3df8515fJosh Gaoclass GrepDialog(SearchDialogBase):
180a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
190a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    title = "Find in Files Dialog"
200a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    icon = "Grep"
210a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    needwrapbutton = 0
220a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
230a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def __init__(self, root, engine, flist):
240a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        SearchDialogBase.__init__(self, root, engine)
250a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.flist = flist
260a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.globvar = StringVar(root)
270a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.recvar = BooleanVar(root)
280a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
290a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def open(self, text, searchphrase, io=None):
300a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        SearchDialogBase.open(self, text, searchphrase)
310a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if io:
320a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            path = io.filename or ""
330a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        else:
340a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            path = ""
350a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        dir, base = os.path.split(path)
360a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        head, tail = os.path.splitext(base)
370a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if not tail:
380a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            tail = ".py"
390a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.globvar.set(os.path.join(dir, "*" + tail))
400a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
410a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def create_entries(self):
420a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        SearchDialogBase.create_entries(self)
430a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.globent = self.make_entry("In files:", self.globvar)
440a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
450a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def create_other_buttons(self):
460a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        f = self.make_frame()
470a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
480a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        btn = Checkbutton(f, anchor="w",
490a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                variable=self.recvar,
500a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                text="Recurse down subdirectories")
510a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        btn.pack(side="top", fill="both")
520a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        btn.select()
530a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
540a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def create_command_buttons(self):
550a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        SearchDialogBase.create_command_buttons(self)
560a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.make_button("Search Files", self.default_command, 1)
570a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
580a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def default_command(self, event=None):
590a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        prog = self.engine.getprog()
600a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if not prog:
610a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            return
620a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        path = self.globvar.get()
630a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if not path:
640a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.top.bell()
650a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            return
660a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        from idlelib.OutputWindow import OutputWindow
670a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        save = sys.stdout
680a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        try:
690a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            sys.stdout = OutputWindow(self.flist)
700a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.grep_it(prog, path)
710a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        finally:
720a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            sys.stdout = save
730a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
740a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def grep_it(self, prog, path):
750a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        dir, base = os.path.split(path)
760a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        list = self.findfiles(dir, base, self.recvar.get())
770a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        list.sort()
780a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        self.close()
790a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        pat = self.engine.getpat()
800a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        print "Searching %r in %s ..." % (pat, path)
810a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        hits = 0
820a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        for fn in list:
830a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            try:
840a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                f = open(fn)
850a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            except IOError, msg:
860a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                print msg
870a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                continue
880a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            lineno = 0
890a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            while 1:
900a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                block = f.readlines(100000)
910a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                if not block:
920a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                    break
930a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                for line in block:
940a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                    lineno = lineno + 1
950a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                    if line[-1:] == '\n':
960a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                        line = line[:-1]
970a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                    if prog.search(line):
980a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                        sys.stdout.write("%s: %s: %s\n" % (fn, lineno, line))
990a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                        hits = hits + 1
1000a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if hits:
1010a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            if hits == 1:
1020a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                s = ""
1030a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            else:
1040a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                s = "s"
1050a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            print "Found", hits, "hit%s." % s
1060a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            print "(Hint: right-click to open locations.)"
1070a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        else:
1080a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            print "No hits."
1090a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1100a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def findfiles(self, dir, base, rec):
1110a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        try:
1120a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            names = os.listdir(dir or os.curdir)
1130a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        except os.error, msg:
1140a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            print msg
1150a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            return []
1160a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        list = []
1170a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        subdirs = []
1180a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        for name in names:
1190a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            fn = os.path.join(dir, name)
1200a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            if os.path.isdir(fn):
1210a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                subdirs.append(fn)
1220a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            else:
1230a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                if fnmatch.fnmatch(name, base):
1240a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                    list.append(fn)
1250a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if rec:
1260a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            for subdir in subdirs:
1270a8c90248264a8b26970b4473770bcc3df8515fJosh Gao                list.extend(self.findfiles(subdir, base, rec))
1280a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        return list
1290a8c90248264a8b26970b4473770bcc3df8515fJosh Gao
1300a8c90248264a8b26970b4473770bcc3df8515fJosh Gao    def close(self, event=None):
1310a8c90248264a8b26970b4473770bcc3df8515fJosh Gao        if self.top:
1320a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.top.grab_release()
1330a8c90248264a8b26970b4473770bcc3df8515fJosh Gao            self.top.withdraw()
134