blob: 61c77c349389a5ded084f0584e19b85e608c735d [file] [log] [blame]
David Scherer7aced172000-08-15 01:13:23 +00001import string
2import os
3import re
4import fnmatch
5import sys
6from Tkinter import *
7import tkMessageBox
8import SearchEngine
9from SearchDialogBase import SearchDialogBase
10
11def grep(text, io=None, flist=None):
12 root = text._root()
13 engine = SearchEngine.get(root)
14 if not hasattr(engine, "_grepdialog"):
15 engine._grepdialog = GrepDialog(root, engine, flist)
16 dialog = engine._grepdialog
17 dialog.open(io)
18
19class GrepDialog(SearchDialogBase):
20
21 title = "Find in Files Dialog"
22 icon = "Grep"
23 needwrapbutton = 0
24
25 def __init__(self, root, engine, flist):
26 SearchDialogBase.__init__(self, root, engine)
27 self.flist = flist
28 self.globvar = StringVar(root)
29 self.recvar = BooleanVar(root)
30
31 def open(self, io=None):
32 SearchDialogBase.open(self, None)
33 if io:
34 path = io.filename or ""
35 else:
36 path = ""
37 dir, base = os.path.split(path)
38 head, tail = os.path.splitext(base)
39 if not tail:
40 tail = ".py"
41 self.globvar.set(os.path.join(dir, "*" + tail))
42
43 def create_entries(self):
44 SearchDialogBase.create_entries(self)
45 self.globent = self.make_entry("In files:", self.globvar)
46
47 def create_other_buttons(self):
48 f = self.make_frame()
49
50 btn = Checkbutton(f, anchor="w",
51 variable=self.recvar,
52 text="Recurse down subdirectories")
53 btn.pack(side="top", fill="both")
54 btn.select()
55
56 def create_command_buttons(self):
57 SearchDialogBase.create_command_buttons(self)
58 self.make_button("Search Files", self.default_command, 1)
59
60 def default_command(self, event=None):
61 prog = self.engine.getprog()
62 if not prog:
63 return
64 path = self.globvar.get()
65 if not path:
66 self.top.bell()
67 return
68 from OutputWindow import OutputWindow
69 save = sys.stdout
70 try:
71 sys.stdout = OutputWindow(self.flist)
72 self.grep_it(prog, path)
73 finally:
74 sys.stdout = save
75
76 def grep_it(self, prog, path):
77 dir, base = os.path.split(path)
78 list = self.findfiles(dir, base, self.recvar.get())
79 list.sort()
80 self.close()
81 pat = self.engine.getpat()
82 print "Searching %s in %s ..." % (`pat`, path)
83 hits = 0
84 for fn in list:
85 try:
86 f = open(fn)
87 except IOError, msg:
88 print msg
89 continue
90 lineno = 0
91 while 1:
92 block = f.readlines(100000)
93 if not block:
94 break
95 for line in block:
96 lineno = lineno + 1
97 if line[-1:] == '\n':
98 line = line[:-1]
99 if prog.search(line):
100 sys.stdout.write("%s: %s: %s\n" % (fn, lineno, line))
101 hits = hits + 1
102 if hits:
103 if hits == 1:
104 s = ""
105 else:
106 s = "s"
107 print "Found", hits, "hit%s." % s
108 print "(Hint: right-click to open locations.)"
109 else:
110 print "No hits."
111
112 def findfiles(self, dir, base, rec):
113 try:
114 names = os.listdir(dir or os.curdir)
115 except os.error, msg:
116 print msg
117 return []
118 list = []
119 subdirs = []
120 for name in names:
121 fn = os.path.join(dir, name)
122 if os.path.isdir(fn):
123 subdirs.append(fn)
124 else:
125 if fnmatch.fnmatch(name, base):
126 list.append(fn)
127 if rec:
128 for subdir in subdirs:
129 list.extend(self.findfiles(subdir, base, rec))
130 return list
131
132 def close(self, event=None):
133 if self.top:
134 self.top.grab_release()
135 self.top.withdraw()