diff options
Diffstat (limited to 'Lib/idlelib/grep.py')
| -rw-r--r-- | Lib/idlelib/grep.py | 158 | 
1 files changed, 158 insertions, 0 deletions
diff --git a/Lib/idlelib/grep.py b/Lib/idlelib/grep.py new file mode 100644 index 0000000000..721b231a9e --- /dev/null +++ b/Lib/idlelib/grep.py @@ -0,0 +1,158 @@ +import os +import fnmatch +import re  # for htest +import sys +from tkinter import StringVar, BooleanVar, Checkbutton  # for GrepDialog +from tkinter import Tk, Text, Button, SEL, END  # for htest +from idlelib import SearchEngine +from idlelib.SearchDialogBase import SearchDialogBase +# Importing OutputWindow fails due to import loop +# EditorWindow -> GrepDialop -> OutputWindow -> EditorWindow + +def grep(text, io=None, flist=None): +    root = text._root() +    engine = SearchEngine.get(root) +    if not hasattr(engine, "_grepdialog"): +        engine._grepdialog = GrepDialog(root, engine, flist) +    dialog = engine._grepdialog +    searchphrase = text.get("sel.first", "sel.last") +    dialog.open(text, searchphrase, io) + +class GrepDialog(SearchDialogBase): + +    title = "Find in Files Dialog" +    icon = "Grep" +    needwrapbutton = 0 + +    def __init__(self, root, engine, flist): +        SearchDialogBase.__init__(self, root, engine) +        self.flist = flist +        self.globvar = StringVar(root) +        self.recvar = BooleanVar(root) + +    def open(self, text, searchphrase, io=None): +        SearchDialogBase.open(self, text, searchphrase) +        if io: +            path = io.filename or "" +        else: +            path = "" +        dir, base = os.path.split(path) +        head, tail = os.path.splitext(base) +        if not tail: +            tail = ".py" +        self.globvar.set(os.path.join(dir, "*" + tail)) + +    def create_entries(self): +        SearchDialogBase.create_entries(self) +        self.globent = self.make_entry("In files:", self.globvar)[0] + +    def create_other_buttons(self): +        f = self.make_frame()[0] + +        btn = Checkbutton(f, anchor="w", +                variable=self.recvar, +                text="Recurse down subdirectories") +        btn.pack(side="top", fill="both") +        btn.select() + +    def create_command_buttons(self): +        SearchDialogBase.create_command_buttons(self) +        self.make_button("Search Files", self.default_command, 1) + +    def default_command(self, event=None): +        prog = self.engine.getprog() +        if not prog: +            return +        path = self.globvar.get() +        if not path: +            self.top.bell() +            return +        from idlelib.OutputWindow import OutputWindow  # leave here! +        save = sys.stdout +        try: +            sys.stdout = OutputWindow(self.flist) +            self.grep_it(prog, path) +        finally: +            sys.stdout = save + +    def grep_it(self, prog, path): +        dir, base = os.path.split(path) +        list = self.findfiles(dir, base, self.recvar.get()) +        list.sort() +        self.close() +        pat = self.engine.getpat() +        print("Searching %r in %s ..." % (pat, path)) +        hits = 0 +        try: +            for fn in list: +                try: +                    with open(fn, errors='replace') as f: +                        for lineno, line in enumerate(f, 1): +                            if line[-1:] == '\n': +                                line = line[:-1] +                            if prog.search(line): +                                sys.stdout.write("%s: %s: %s\n" % +                                                 (fn, lineno, line)) +                                hits += 1 +                except OSError as msg: +                    print(msg) +            print(("Hits found: %s\n" +                  "(Hint: right-click to open locations.)" +                  % hits) if hits else "No hits.") +        except AttributeError: +            # Tk window has been closed, OutputWindow.text = None, +            # so in OW.write, OW.text.insert fails. +            pass + +    def findfiles(self, dir, base, rec): +        try: +            names = os.listdir(dir or os.curdir) +        except OSError as msg: +            print(msg) +            return [] +        list = [] +        subdirs = [] +        for name in names: +            fn = os.path.join(dir, name) +            if os.path.isdir(fn): +                subdirs.append(fn) +            else: +                if fnmatch.fnmatch(name, base): +                    list.append(fn) +        if rec: +            for subdir in subdirs: +                list.extend(self.findfiles(subdir, base, rec)) +        return list + +    def close(self, event=None): +        if self.top: +            self.top.grab_release() +            self.top.withdraw() + + +def _grep_dialog(parent):  # htest # +    from idlelib.PyShell import PyShellFileList +    root = Tk() +    root.title("Test GrepDialog") +    width, height, x, y = list(map(int, re.split('[x+]', parent.geometry()))) +    root.geometry("+%d+%d"%(x, y + 150)) + +    flist = PyShellFileList(root) +    text = Text(root, height=5) +    text.pack() + +    def show_grep_dialog(): +        text.tag_add(SEL, "1.0", END) +        grep(text, flist=flist) +        text.tag_remove(SEL, "1.0", END) + +    button = Button(root, text="Show GrepDialog", command=show_grep_dialog) +    button.pack() +    root.mainloop() + +if __name__ == "__main__": +    import unittest +    unittest.main('idlelib.idle_test.test_grep', verbosity=2, exit=False) + +    from idlelib.idle_test.htest import run +    run(_grep_dialog)  | 
