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