|
1 import os |
|
2 import fnmatch |
|
3 import sys |
|
4 from Tkinter import * |
|
5 import SearchEngine |
|
6 from 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 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() |