Mercurial > cpython-lru_cache-weakref
annotate Mac/Tools/IDE/PyDocSearch.py @ 25838:8540887bcec6 2.2
Backport of 2.183:
Fix memory leak in add_subclass() found by NealN with valgrind.
| author | Guido van Rossum <guido@python.org> |
|---|---|
| date | Fri, 18 Oct 2002 13:42:21 +0000 |
| parents | 761075280a95 |
| children | ea5ee3e7bfb1 |
| rev | line source |
|---|---|
|
16725
d170c1e772c5
Use re in stead of regex, so we get rid of the annoying warning during startup.
Jack Jansen <jack.jansen@cwi.nl>
parents:
10087
diff
changeset
|
1 import re |
| 10047 | 2 import W |
| 3 import macfs | |
| 4 import os | |
| 5 import MacPrefs | |
| 6 import MacOS | |
| 7 import string | |
|
21161
943ca81ad1df
Removed old and broken AE-based browser controller, use webbrowser.py
Just van Rossum <just@letterror.com>
parents:
19488
diff
changeset
|
8 import webbrowser |
| 10047 | 9 |
| 10 | |
| 11 app = W.getapplication() | |
| 12 | |
|
16725
d170c1e772c5
Use re in stead of regex, so we get rid of the annoying warning during startup.
Jack Jansen <jack.jansen@cwi.nl>
parents:
10087
diff
changeset
|
13 _titlepat = re.compile('<title>\([^<]*\)</title>') |
| 10047 | 14 |
| 15 def sucktitle(path): | |
| 16 f = open(path) | |
| 17 text = f.read(1024) # assume the title is in the first 1024 bytes | |
| 18 f.close() | |
|
21161
943ca81ad1df
Removed old and broken AE-based browser controller, use webbrowser.py
Just van Rossum <just@letterror.com>
parents:
19488
diff
changeset
|
19 lowertext = text.lower() |
|
16725
d170c1e772c5
Use re in stead of regex, so we get rid of the annoying warning during startup.
Jack Jansen <jack.jansen@cwi.nl>
parents:
10087
diff
changeset
|
20 matcher = _titlepat.search(lowertext) |
|
d170c1e772c5
Use re in stead of regex, so we get rid of the annoying warning during startup.
Jack Jansen <jack.jansen@cwi.nl>
parents:
10087
diff
changeset
|
21 if matcher: |
|
d170c1e772c5
Use re in stead of regex, so we get rid of the annoying warning during startup.
Jack Jansen <jack.jansen@cwi.nl>
parents:
10087
diff
changeset
|
22 return matcher.group(1) |
| 10047 | 23 return path |
| 24 | |
| 25 def verifydocpath(docpath): | |
| 26 try: | |
| 27 tut = os.path.join(docpath, "tut") | |
| 28 lib = os.path.join(docpath, "lib") | |
| 29 ref = os.path.join(docpath, "ref") | |
| 30 for path in [tut, lib, ref]: | |
| 31 if not os.path.exists(path): | |
| 32 return 0 | |
| 33 except: | |
| 34 return 0 | |
| 35 return 1 | |
| 36 | |
| 37 | |
| 38 _resultscounter = 1 | |
| 39 | |
| 40 class Results: | |
| 41 | |
| 42 def __init__(self, hits): | |
| 43 global _resultscounter | |
| 44 hits = map(lambda (path, hits): (sucktitle(path), path, hits), hits) | |
| 45 hits.sort() | |
| 46 self.hits = hits | |
| 47 nicehits = map( | |
| 48 lambda (title, path, hits): | |
| 49 title + '\r' + string.join( | |
| 50 map(lambda (c, p): "%s (%d)" % (p, c), hits), ', '), hits) | |
| 51 nicehits.sort() | |
| 52 self.w = W.Window((440, 300), "Search results %d" % _resultscounter, minsize = (200, 100)) | |
|
21161
943ca81ad1df
Removed old and broken AE-based browser controller, use webbrowser.py
Just van Rossum <just@letterror.com>
parents:
19488
diff
changeset
|
53 self.w.results = W.TwoLineList((-1, -1, 1, -14), nicehits, self.listhit) |
| 10047 | 54 self.w.open() |
| 55 self.w.bind('return', self.listhit) | |
| 56 self.w.bind('enter', self.listhit) | |
| 57 _resultscounter = _resultscounter + 1 | |
| 58 | |
| 59 def listhit(self, isdbl = 1): | |
| 60 if isdbl: | |
| 61 for i in self.w.results.getselection(): | |
|
21161
943ca81ad1df
Removed old and broken AE-based browser controller, use webbrowser.py
Just van Rossum <just@letterror.com>
parents:
19488
diff
changeset
|
62 path = self.hits[i][1] |
|
943ca81ad1df
Removed old and broken AE-based browser controller, use webbrowser.py
Just van Rossum <just@letterror.com>
parents:
19488
diff
changeset
|
63 url = "file://" + "/".join(path.split(":")) |
|
943ca81ad1df
Removed old and broken AE-based browser controller, use webbrowser.py
Just van Rossum <just@letterror.com>
parents:
19488
diff
changeset
|
64 webbrowser.open(url) |
|
943ca81ad1df
Removed old and broken AE-based browser controller, use webbrowser.py
Just van Rossum <just@letterror.com>
parents:
19488
diff
changeset
|
65 |
| 10047 | 66 |
| 67 class Status: | |
| 68 | |
| 69 def __init__(self): | |
|
18167
c5ac6f055c62
Some long overdue maintainance. Made all IDE sources 7-bit-clean, to avoid any further encoding conversion troubles.
Just van Rossum <just@letterror.com>
parents:
17844
diff
changeset
|
70 self.w = W.Dialog((440, 64), "Searching\xc9") |
|
21161
943ca81ad1df
Removed old and broken AE-based browser controller, use webbrowser.py
Just van Rossum <just@letterror.com>
parents:
19488
diff
changeset
|
71 self.w.searching = W.TextBox((4, 4, -4, 16), "") |
| 10047 | 72 self.w.hits = W.TextBox((4, 24, -4, 16), "Hits: 0") |
| 73 self.w.canceltip = W.TextBox((4, 44, -4, 16), "Type cmd-period (.) to cancel.") | |
| 74 self.w.open() | |
| 75 | |
| 76 def set(self, path, hits): | |
| 77 self.w.searching.set(path) | |
| 78 self.w.hits.set('Hits: ' + `hits`) | |
| 79 app.breathe() | |
| 80 | |
| 81 def close(self): | |
| 82 self.w.close() | |
| 83 | |
| 84 | |
| 85 def match(text, patterns, all): | |
| 86 hits = [] | |
| 87 hitsappend = hits.append | |
| 88 stringcount = string.count | |
| 89 for pat in patterns: | |
| 90 c = stringcount(text, pat) | |
| 91 if c > 0: | |
| 92 hitsappend((c, pat)) | |
| 93 elif all: | |
| 94 hits[:] = [] | |
| 95 break | |
| 96 hits.sort() | |
| 97 hits.reverse() | |
| 98 return hits | |
| 99 | |
|
21161
943ca81ad1df
Removed old and broken AE-based browser controller, use webbrowser.py
Just van Rossum <just@letterror.com>
parents:
19488
diff
changeset
|
100 |
| 10047 | 101 def dosearch(docpath, searchstring, settings): |
| 102 (docpath, kind, case, word, tut, lib, ref, ext, api) = settings | |
| 103 books = [(tut, 'tut'), (lib, 'lib'), (ref, 'ref'), (ext, 'ext'), (api, 'api')] | |
| 104 if not case: | |
| 105 searchstring = string.lower(searchstring) | |
| 106 | |
| 107 if kind == 1: | |
| 108 patterns = string.split(searchstring) | |
| 109 all = 1 | |
| 110 elif kind == 2: | |
| 111 patterns = string.split(searchstring) | |
| 112 all = 0 | |
| 113 else: | |
| 114 patterns = [searchstring] | |
| 115 all = 0 # not relevant | |
| 116 | |
| 117 ospathjoin = os.path.join | |
| 118 stringlower = string.lower | |
| 119 status = Status() | |
| 120 statusset = status.set | |
| 121 _match = match | |
| 122 _open = open | |
| 123 hits = {} | |
| 124 try: | |
| 22031 | 125 if hasattr(MacOS, 'EnableAppswitch'): |
| 126 MacOS.EnableAppswitch(0) | |
| 10047 | 127 try: |
| 128 for do, name in books: | |
| 129 if not do: | |
| 130 continue | |
| 131 bookpath = ospathjoin(docpath, name) | |
| 132 if not os.path.exists(bookpath): | |
| 133 continue | |
| 134 files = os.listdir(bookpath) | |
| 135 for file in files: | |
| 136 fullpath = ospathjoin(bookpath, file) | |
| 137 if fullpath[-5:] <> '.html': | |
| 138 continue | |
| 139 statusset(fullpath, len(hits)) | |
| 140 f = _open(fullpath) | |
| 141 text = f.read() | |
| 142 if not case: | |
| 143 text = stringlower(text) | |
| 144 f.close() | |
| 145 filehits = _match(text, patterns, all) | |
| 146 if filehits: | |
| 147 hits[fullpath] = filehits | |
| 148 finally: | |
| 22031 | 149 if hasattr(MacOS, 'EnableAppswitch'): |
| 150 MacOS.EnableAppswitch(-1) | |
| 10047 | 151 status.close() |
| 152 except KeyboardInterrupt: | |
| 153 pass | |
| 154 hits = hits.items() | |
| 155 hits.sort() | |
| 156 return hits | |
| 157 | |
| 158 | |
| 159 class PyDocSearch: | |
| 160 | |
| 161 def __init__(self): | |
| 162 prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath) | |
| 163 try: | |
| 164 (docpath, kind, case, word, tut, lib, ref, ext, api) = prefs.docsearchengine | |
| 165 except: | |
| 166 (docpath, kind, case, word, tut, lib, ref, ext, api) = prefs.docsearchengine = \ | |
| 167 ("", 0, 0, 0, 1, 1, 0, 0, 0) | |
| 168 | |
| 169 if docpath and not verifydocpath(docpath): | |
| 170 docpath = "" | |
| 171 | |
| 172 self.w = W.Window((400, 200), "Search the Python Documentation") | |
| 173 self.w.searchtext = W.EditText((10, 10, -100, 20), callback = self.checkbuttons) | |
| 174 self.w.searchbutton = W.Button((-90, 12, 80, 16), "Search", self.search) | |
| 175 buttons = [] | |
| 176 | |
| 177 gutter = 10 | |
| 178 width = 130 | |
| 179 bookstart = width + 2 * gutter | |
| 180 self.w.phraseradio = W.RadioButton((10, 38, width, 16), "As a phrase", buttons) | |
| 181 self.w.allwordsradio = W.RadioButton((10, 58, width, 16), "All words", buttons) | |
| 182 self.w.anywordsradio = W.RadioButton((10, 78, width, 16), "Any word", buttons) | |
| 183 self.w.casesens = W.CheckBox((10, 98, width, 16), "Case sensitive") | |
| 184 self.w.wholewords = W.CheckBox((10, 118, width, 16), "Whole words") | |
| 185 self.w.tutorial = W.CheckBox((bookstart, 38, -10, 16), "Tutorial") | |
| 186 self.w.library = W.CheckBox((bookstart, 58, -10, 16), "Library reference") | |
| 187 self.w.langueref = W.CheckBox((bookstart, 78, -10, 16), "Lanuage reference manual") | |
| 188 self.w.extending = W.CheckBox((bookstart, 98, -10, 16), "Extending & embedding") | |
| 189 self.w.api = W.CheckBox((bookstart, 118, -10, 16), "C/C++ API") | |
| 190 | |
|
21161
943ca81ad1df
Removed old and broken AE-based browser controller, use webbrowser.py
Just van Rossum <just@letterror.com>
parents:
19488
diff
changeset
|
191 self.w.setdocfolderbutton = W.Button((10, -30, 100, 16), "Set doc folder", self.setdocpath) |
| 10047 | 192 |
| 193 if docpath: | |
| 194 self.w.setdefaultbutton(self.w.searchbutton) | |
| 195 else: | |
| 196 self.w.setdefaultbutton(self.w.setdocfolderbutton) | |
| 197 | |
| 198 self.docpath = docpath | |
| 199 if not docpath: | |
| 200 docpath = "(please select the Python html documentation folder)" | |
|
21161
943ca81ad1df
Removed old and broken AE-based browser controller, use webbrowser.py
Just van Rossum <just@letterror.com>
parents:
19488
diff
changeset
|
201 self.w.docfolder = W.TextBox((120, -28, -10, 16), docpath) |
| 10047 | 202 |
| 203 [self.w.phraseradio, self.w.allwordsradio, self.w.anywordsradio][kind].set(1) | |
| 204 | |
| 205 self.w.casesens.set(case) | |
| 206 self.w.wholewords.set(word) | |
| 207 self.w.tutorial.set(tut) | |
| 208 self.w.library.set(lib) | |
| 209 self.w.langueref.set(ref) | |
| 210 self.w.extending.set(ext) | |
| 211 self.w.api.set(api) | |
| 212 | |
| 213 self.w.open() | |
| 214 self.w.wholewords.enable(0) | |
| 215 self.w.bind('<close>', self.close) | |
| 216 self.w.searchbutton.enable(0) | |
| 217 | |
| 218 def search(self): | |
| 219 hits = dosearch(self.docpath, self.w.searchtext.get(), self.getsettings()) | |
| 220 if hits: | |
| 221 Results(hits) | |
| 222 elif hasattr(MacOS, 'SysBeep'): | |
| 223 MacOS.SysBeep(0) | |
| 224 | |
| 225 def setdocpath(self): | |
| 226 fss, ok = macfs.GetDirectory() | |
| 227 if ok: | |
| 228 docpath = fss.as_pathname() | |
| 229 if not verifydocpath(docpath): | |
| 230 W.Message("This does not seem to be a Python documentation folder...") | |
| 231 else: | |
| 232 self.docpath = docpath | |
| 233 self.w.docfolder.set(docpath) | |
| 234 self.w.setdefaultbutton(self.w.searchbutton) | |
| 235 | |
| 236 def close(self): | |
| 237 prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath) | |
| 238 prefs.docsearchengine = self.getsettings() | |
| 239 | |
| 240 def getsettings(self): | |
| 241 radiobuttons = [self.w.phraseradio, self.w.allwordsradio, self.w.anywordsradio] | |
| 242 for i in range(3): | |
| 243 if radiobuttons[i].get(): | |
| 244 kind = i | |
| 245 break | |
| 246 docpath = self.docpath | |
| 247 case = self.w.casesens.get() | |
| 248 word = self.w.wholewords.get() | |
| 249 tut = self.w.tutorial.get() | |
| 250 lib = self.w.library.get() | |
| 251 ref = self.w.langueref.get() | |
| 252 ext = self.w.extending.get() | |
| 253 api = self.w.api.get() | |
| 254 return (docpath, kind, case, word, tut, lib, ref, ext, api) | |
| 255 | |
| 256 def checkbuttons(self): | |
| 257 self.w.searchbutton.enable(not not self.w.searchtext.get()) |
