blob: 89f97ca00867a42a2bc32bcd08b85f2166e7d17f [file] [log] [blame]
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001"""A (less & less) simple Python editor"""
2
3import W
4import Wtraceback
5from Wkeys import *
6
Just van Rossum40f9b7b1999-01-30 22:39:17 +00007import MacOS
Jack Jansenfd0b00e2003-01-26 22:15:48 +00008import EasyDialogs
Jack Jansen5a6fdcd2001-08-25 12:15:04 +00009from Carbon import Win
10from Carbon import Res
11from Carbon import Evt
Just van Rossum2ad94192002-07-12 12:06:17 +000012from Carbon import Qd
Jack Jansene7ee17c2003-02-06 22:32:35 +000013from Carbon import File
Just van Rossum40f9b7b1999-01-30 22:39:17 +000014import os
15import imp
16import sys
17import string
18import marshal
Jack Jansen9ad27522001-02-21 13:54:31 +000019import re
Just van Rossum40f9b7b1999-01-30 22:39:17 +000020
Jack Jansene7ee17c2003-02-06 22:32:35 +000021smAllScripts = -3
22
Just van Rossum40144012002-02-04 12:52:44 +000023if hasattr(Win, "FrontNonFloatingWindow"):
24 MyFrontWindow = Win.FrontNonFloatingWindow
25else:
26 MyFrontWindow = Win.FrontWindow
27
28
Just van Rossum73efed22000-04-09 19:45:22 +000029try:
Just van Rossum0f2fd162000-10-20 06:36:30 +000030 import Wthreading
Just van Rossum73efed22000-04-09 19:45:22 +000031except ImportError:
Just van Rossum0f2fd162000-10-20 06:36:30 +000032 haveThreading = 0
33else:
34 haveThreading = Wthreading.haveThreading
Just van Rossum73efed22000-04-09 19:45:22 +000035
Just van Rossum40f9b7b1999-01-30 22:39:17 +000036_scriptuntitledcounter = 1
Fred Drake79e75e12001-07-20 19:05:50 +000037_wordchars = string.ascii_letters + string.digits + "_"
Just van Rossum40f9b7b1999-01-30 22:39:17 +000038
39
Just van Rossum73efed22000-04-09 19:45:22 +000040runButtonLabels = ["Run all", "Stop!"]
41runSelButtonLabels = ["Run selection", "Pause!", "Resume"]
42
43
Just van Rossum40f9b7b1999-01-30 22:39:17 +000044class Editor(W.Window):
45
46 def __init__(self, path = "", title = ""):
47 defaultfontsettings, defaulttabsettings, defaultwindowsize = geteditorprefs()
48 global _scriptuntitledcounter
49 if not path:
50 if title:
51 self.title = title
52 else:
53 self.title = "Untitled Script " + `_scriptuntitledcounter`
54 _scriptuntitledcounter = _scriptuntitledcounter + 1
55 text = ""
56 self._creator = W._signature
Jack Jansen9a389472002-03-29 21:26:04 +000057 self._eoln = os.linesep
Just van Rossum40f9b7b1999-01-30 22:39:17 +000058 elif os.path.exists(path):
59 path = resolvealiases(path)
60 dir, name = os.path.split(path)
61 self.title = name
62 f = open(path, "rb")
63 text = f.read()
64 f.close()
Jack Jansene7ee17c2003-02-06 22:32:35 +000065 self._creator, filetype = MacOS.GetCreatorAndType(path)
Jack Jansenc00b6d72003-02-25 15:08:02 +000066 self.addrecentfile(path)
Just van Rossum40f9b7b1999-01-30 22:39:17 +000067 else:
68 raise IOError, "file '%s' does not exist" % path
69 self.path = path
70
Just van Rossumc7ba0801999-05-21 21:42:27 +000071 if '\n' in text:
Just van Rossumc7ba0801999-05-21 21:42:27 +000072 if string.find(text, '\r\n') >= 0:
Jack Jansen9a389472002-03-29 21:26:04 +000073 self._eoln = '\r\n'
Just van Rossumc7ba0801999-05-21 21:42:27 +000074 else:
Jack Jansen9a389472002-03-29 21:26:04 +000075 self._eoln = '\n'
76 text = string.replace(text, self._eoln, '\r')
77 change = 0
Just van Rossumc7ba0801999-05-21 21:42:27 +000078 else:
79 change = 0
Jack Jansen9a389472002-03-29 21:26:04 +000080 self._eoln = '\r'
Just van Rossumc7ba0801999-05-21 21:42:27 +000081
Just van Rossum40f9b7b1999-01-30 22:39:17 +000082 self.settings = {}
83 if self.path:
84 self.readwindowsettings()
85 if self.settings.has_key("windowbounds"):
86 bounds = self.settings["windowbounds"]
87 else:
88 bounds = defaultwindowsize
89 if self.settings.has_key("fontsettings"):
90 self.fontsettings = self.settings["fontsettings"]
91 else:
92 self.fontsettings = defaultfontsettings
93 if self.settings.has_key("tabsize"):
94 try:
95 self.tabsettings = (tabsize, tabmode) = self.settings["tabsize"]
96 except:
97 self.tabsettings = defaulttabsettings
98 else:
99 self.tabsettings = defaulttabsettings
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000100
Just van Rossumc7ba0801999-05-21 21:42:27 +0000101 W.Window.__init__(self, bounds, self.title, minsize = (330, 120), tabbable = 0)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000102 self.setupwidgets(text)
Just van Rossumc7ba0801999-05-21 21:42:27 +0000103 if change > 0:
Just van Rossumf7f93882001-11-02 19:24:41 +0000104 self.editgroup.editor.textchanged()
Just van Rossumc7ba0801999-05-21 21:42:27 +0000105
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000106 if self.settings.has_key("selection"):
107 selstart, selend = self.settings["selection"]
108 self.setselection(selstart, selend)
109 self.open()
110 self.setinfotext()
111 self.globals = {}
112 self._buf = "" # for write method
113 self.debugging = 0
114 self.profiling = 0
Jack Jansenff773eb2002-03-31 22:01:33 +0000115 self.run_as_main = self.settings.get("run_as_main", 0)
116 self.run_with_interpreter = self.settings.get("run_with_interpreter", 0)
117 self.run_with_cl_interpreter = self.settings.get("run_with_cl_interpreter", 0)
Just van Rossum73efed22000-04-09 19:45:22 +0000118 self._threadstate = (0, 0)
119 self._thread = None
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000120
121 def readwindowsettings(self):
122 try:
Jack Jansend13c3852000-06-20 21:59:25 +0000123 resref = Res.FSpOpenResFile(self.path, 1)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000124 except Res.Error:
125 return
126 try:
127 Res.UseResFile(resref)
128 data = Res.Get1Resource('PyWS', 128)
129 self.settings = marshal.loads(data.data)
130 except:
131 pass
132 Res.CloseResFile(resref)
133
134 def writewindowsettings(self):
135 try:
Jack Jansend13c3852000-06-20 21:59:25 +0000136 resref = Res.FSpOpenResFile(self.path, 3)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000137 except Res.Error:
Jack Jansene7ee17c2003-02-06 22:32:35 +0000138 Res.FSpCreateResFile(self.path, self._creator, 'TEXT', smAllScripts)
Jack Jansend13c3852000-06-20 21:59:25 +0000139 resref = Res.FSpOpenResFile(self.path, 3)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000140 try:
141 data = Res.Resource(marshal.dumps(self.settings))
142 Res.UseResFile(resref)
143 try:
144 temp = Res.Get1Resource('PyWS', 128)
145 temp.RemoveResource()
146 except Res.Error:
147 pass
148 data.AddResource('PyWS', 128, "window settings")
149 finally:
150 Res.UpdateResFile(resref)
151 Res.CloseResFile(resref)
152
153 def getsettings(self):
154 self.settings = {}
155 self.settings["windowbounds"] = self.getbounds()
156 self.settings["selection"] = self.getselection()
157 self.settings["fontsettings"] = self.editgroup.editor.getfontsettings()
158 self.settings["tabsize"] = self.editgroup.editor.gettabsettings()
159 self.settings["run_as_main"] = self.run_as_main
Just van Rossum0f2fd162000-10-20 06:36:30 +0000160 self.settings["run_with_interpreter"] = self.run_with_interpreter
Jack Jansenff773eb2002-03-31 22:01:33 +0000161 self.settings["run_with_cl_interpreter"] = self.run_with_cl_interpreter
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000162
163 def get(self):
164 return self.editgroup.editor.get()
165
166 def getselection(self):
167 return self.editgroup.editor.ted.WEGetSelection()
168
169 def setselection(self, selstart, selend):
170 self.editgroup.editor.setselection(selstart, selend)
Jack Jansen9a791822003-05-06 14:28:31 +0000171
172 def getselectedtext(self):
173 return self.editgroup.editor.getselectedtext()
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000174
175 def getfilename(self):
176 if self.path:
177 return self.path
178 return '<%s>' % self.title
179
180 def setupwidgets(self, text):
Just van Rossumf376ef02001-11-18 14:12:43 +0000181 topbarheight = 24
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000182 popfieldwidth = 80
183 self.lastlineno = None
184
185 # make an editor
186 self.editgroup = W.Group((0, topbarheight + 1, 0, 0))
187 editor = W.PyEditor((0, 0, -15,-15), text,
188 fontsettings = self.fontsettings,
189 tabsettings = self.tabsettings,
190 file = self.getfilename())
191
192 # make the widgets
193 self.popfield = ClassFinder((popfieldwidth - 17, -15, 16, 16), [], self.popselectline)
194 self.linefield = W.EditText((-1, -15, popfieldwidth - 15, 16), inset = (6, 1))
195 self.editgroup._barx = W.Scrollbar((popfieldwidth - 2, -15, -14, 16), editor.hscroll, max = 32767)
196 self.editgroup._bary = W.Scrollbar((-15, 14, 16, -14), editor.vscroll, max = 32767)
197 self.editgroup.editor = editor # add editor *after* scrollbars
198
199 self.editgroup.optionsmenu = W.PopupMenu((-15, -1, 16, 16), [])
200 self.editgroup.optionsmenu.bind('<click>', self.makeoptionsmenu)
201
202 self.bevelbox = W.BevelBox((0, 0, 0, topbarheight))
203 self.hline = W.HorizontalLine((0, topbarheight, 0, 0))
Just van Rossumf376ef02001-11-18 14:12:43 +0000204 self.infotext = W.TextBox((175, 6, -4, 14), backgroundcolor = (0xe000, 0xe000, 0xe000))
205 self.runbutton = W.BevelButton((6, 4, 80, 16), runButtonLabels[0], self.run)
206 self.runselbutton = W.BevelButton((90, 4, 80, 16), runSelButtonLabels[0], self.runselection)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000207
208 # bind some keys
209 editor.bind("cmdr", self.runbutton.push)
210 editor.bind("enter", self.runselbutton.push)
211 editor.bind("cmdj", self.domenu_gotoline)
212 editor.bind("cmdd", self.domenu_toggledebugger)
213 editor.bind("<idle>", self.updateselection)
214
215 editor.bind("cmde", searchengine.setfindstring)
216 editor.bind("cmdf", searchengine.show)
217 editor.bind("cmdg", searchengine.findnext)
218 editor.bind("cmdshiftr", searchengine.replace)
219 editor.bind("cmdt", searchengine.replacefind)
220
221 self.linefield.bind("return", self.dolinefield)
222 self.linefield.bind("enter", self.dolinefield)
223 self.linefield.bind("tab", self.dolinefield)
224
225 # intercept clicks
226 editor.bind("<click>", self.clickeditor)
227 self.linefield.bind("<click>", self.clicklinefield)
228
229 def makeoptionsmenu(self):
Just van Rossumdc3c6172001-06-19 21:37:33 +0000230 menuitems = [('Font settings\xc9', self.domenu_fontsettings),
231 ("Save options\xc9", self.domenu_options),
Just van Rossum12710051999-02-27 17:18:30 +0000232 '-',
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000233 ('\0' + chr(self.run_as_main) + 'Run as __main__', self.domenu_toggle_run_as_main),
Jack Jansenff773eb2002-03-31 22:01:33 +0000234 #('\0' + chr(self.run_with_interpreter) + 'Run with Interpreter', self.domenu_dtoggle_run_with_interpreter),
235 ('\0' + chr(self.run_with_cl_interpreter) + 'Run with commandline Python', self.domenu_toggle_run_with_cl_interpreter),
236 '-',
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000237 ('Modularize', self.domenu_modularize),
Just van Rossumdc3c6172001-06-19 21:37:33 +0000238 ('Browse namespace\xc9', self.domenu_browsenamespace),
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000239 '-']
240 if self.profiling:
241 menuitems = menuitems + [('Disable profiler', self.domenu_toggleprofiler)]
242 else:
243 menuitems = menuitems + [('Enable profiler', self.domenu_toggleprofiler)]
244 if self.editgroup.editor._debugger:
245 menuitems = menuitems + [('Disable debugger', self.domenu_toggledebugger),
246 ('Clear breakpoints', self.domenu_clearbreakpoints),
Just van Rossumdc3c6172001-06-19 21:37:33 +0000247 ('Edit breakpoints\xc9', self.domenu_editbreakpoints)]
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000248 else:
249 menuitems = menuitems + [('Enable debugger', self.domenu_toggledebugger)]
250 self.editgroup.optionsmenu.set(menuitems)
251
252 def domenu_toggle_run_as_main(self):
253 self.run_as_main = not self.run_as_main
Just van Rossum0f2fd162000-10-20 06:36:30 +0000254 self.run_with_interpreter = 0
Jack Jansenff773eb2002-03-31 22:01:33 +0000255 self.run_with_cl_interpreter = 0
Just van Rossumf7f93882001-11-02 19:24:41 +0000256 self.editgroup.editor.selectionchanged()
Just van Rossum0f2fd162000-10-20 06:36:30 +0000257
Jack Jansenff773eb2002-03-31 22:01:33 +0000258 def XXdomenu_toggle_run_with_interpreter(self):
Just van Rossum0f2fd162000-10-20 06:36:30 +0000259 self.run_with_interpreter = not self.run_with_interpreter
260 self.run_as_main = 0
Jack Jansenff773eb2002-03-31 22:01:33 +0000261 self.run_with_cl_interpreter = 0
262 self.editgroup.editor.selectionchanged()
263
264 def domenu_toggle_run_with_cl_interpreter(self):
265 self.run_with_cl_interpreter = not self.run_with_cl_interpreter
266 self.run_as_main = 0
267 self.run_with_interpreter = 0
Just van Rossumf7f93882001-11-02 19:24:41 +0000268 self.editgroup.editor.selectionchanged()
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000269
270 def showbreakpoints(self, onoff):
271 self.editgroup.editor.showbreakpoints(onoff)
272 self.debugging = onoff
273
274 def domenu_clearbreakpoints(self, *args):
275 self.editgroup.editor.clearbreakpoints()
276
277 def domenu_editbreakpoints(self, *args):
278 self.editgroup.editor.editbreakpoints()
279
280 def domenu_toggledebugger(self, *args):
281 if not self.debugging:
282 W.SetCursor('watch')
283 self.debugging = not self.debugging
284 self.editgroup.editor.togglebreakpoints()
285
286 def domenu_toggleprofiler(self, *args):
287 self.profiling = not self.profiling
288
289 def domenu_browsenamespace(self, *args):
290 import PyBrowser, W
291 W.SetCursor('watch')
292 globals, file, modname = self.getenvironment()
293 if not modname:
294 modname = self.title
295 PyBrowser.Browser(globals, "Object browser: " + modname)
296
297 def domenu_modularize(self, *args):
298 modname = _filename_as_modname(self.title)
299 if not modname:
Just van Rossumdc3c6172001-06-19 21:37:33 +0000300 raise W.AlertError, "Can't modularize \"%s\"" % self.title
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000301 run_as_main = self.run_as_main
302 self.run_as_main = 0
303 self.run()
304 self.run_as_main = run_as_main
305 if self.path:
306 file = self.path
307 else:
308 file = self.title
309
310 if self.globals and not sys.modules.has_key(modname):
311 module = imp.new_module(modname)
312 for attr in self.globals.keys():
313 setattr(module,attr,self.globals[attr])
314 sys.modules[modname] = module
315 self.globals = {}
316
317 def domenu_fontsettings(self, *args):
318 import FontSettings
319 fontsettings = self.editgroup.editor.getfontsettings()
320 tabsettings = self.editgroup.editor.gettabsettings()
321 settings = FontSettings.FontDialog(fontsettings, tabsettings)
322 if settings:
323 fontsettings, tabsettings = settings
324 self.editgroup.editor.setfontsettings(fontsettings)
325 self.editgroup.editor.settabsettings(tabsettings)
326
Just van Rossum12710051999-02-27 17:18:30 +0000327 def domenu_options(self, *args):
Just van Rossumca3d3072002-03-29 21:48:42 +0000328 rv = SaveOptions(self._creator, self._eoln)
329 if rv:
Just van Rossumf7f93882001-11-02 19:24:41 +0000330 self.editgroup.editor.selectionchanged() # ouch...
Just van Rossumca3d3072002-03-29 21:48:42 +0000331 self._creator, self._eoln = rv
Just van Rossum12710051999-02-27 17:18:30 +0000332
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000333 def clicklinefield(self):
334 if self._currentwidget <> self.linefield:
335 self.linefield.select(1)
336 self.linefield.selectall()
337 return 1
338
339 def clickeditor(self):
340 if self._currentwidget <> self.editgroup.editor:
341 self.dolinefield()
342 return 1
343
344 def updateselection(self, force = 0):
345 sel = min(self.editgroup.editor.getselection())
346 lineno = self.editgroup.editor.offsettoline(sel)
347 if lineno <> self.lastlineno or force:
348 self.lastlineno = lineno
349 self.linefield.set(str(lineno + 1))
350 self.linefield.selview()
351
352 def dolinefield(self):
353 try:
354 lineno = string.atoi(self.linefield.get()) - 1
355 if lineno <> self.lastlineno:
356 self.editgroup.editor.selectline(lineno)
357 self.updateselection(1)
358 except:
359 self.updateselection(1)
360 self.editgroup.editor.select(1)
361
362 def setinfotext(self):
363 if not hasattr(self, 'infotext'):
364 return
365 if self.path:
366 self.infotext.set(self.path)
367 else:
368 self.infotext.set("")
369
370 def close(self):
371 if self.editgroup.editor.changed:
Just van Rossum25ddc632001-07-05 07:06:26 +0000372 Qd.InitCursor()
373 save = EasyDialogs.AskYesNoCancel('Save window "%s" before closing?' % self.title,
374 default=1, no="Don\xd5t save")
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000375 if save > 0:
376 if self.domenu_save():
377 return 1
378 elif save < 0:
379 return 1
Just van Rossum25ddc632001-07-05 07:06:26 +0000380 self.globals = None
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000381 W.Window.close(self)
382
383 def domenu_close(self, *args):
384 return self.close()
385
386 def domenu_save(self, *args):
387 if not self.path:
388 # Will call us recursively
389 return self.domenu_save_as()
390 data = self.editgroup.editor.get()
Jack Jansen9a389472002-03-29 21:26:04 +0000391 if self._eoln != '\r':
392 data = string.replace(data, '\r', self._eoln)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000393 fp = open(self.path, 'wb') # open file in binary mode, data has '\r' line-endings
394 fp.write(data)
395 fp.close()
Jack Jansene7ee17c2003-02-06 22:32:35 +0000396 MacOS.SetCreatorAndType(self.path, self._creator, 'TEXT')
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000397 self.getsettings()
398 self.writewindowsettings()
399 self.editgroup.editor.changed = 0
400 self.editgroup.editor.selchanged = 0
401 import linecache
402 if linecache.cache.has_key(self.path):
403 del linecache.cache[self.path]
404 import macostools
405 macostools.touched(self.path)
Jack Jansenc00b6d72003-02-25 15:08:02 +0000406 self.addrecentfile(self.path)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000407
408 def can_save(self, menuitem):
409 return self.editgroup.editor.changed or self.editgroup.editor.selchanged
410
411 def domenu_save_as(self, *args):
Jack Jansenfd0b00e2003-01-26 22:15:48 +0000412 path = EasyDialogs.AskFileForSave(message='Save as:', savedFileName=self.title)
413 if not path:
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000414 return 1
415 self.showbreakpoints(0)
Jack Jansenfd0b00e2003-01-26 22:15:48 +0000416 self.path = path
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000417 self.setinfotext()
418 self.title = os.path.split(self.path)[-1]
419 self.wid.SetWTitle(self.title)
420 self.domenu_save()
421 self.editgroup.editor.setfile(self.getfilename())
422 app = W.getapplication()
423 app.makeopenwindowsmenu()
424 if hasattr(app, 'makescriptsmenu'):
425 app = W.getapplication()
Jack Jansene7ee17c2003-02-06 22:32:35 +0000426 fsr, changed = app.scriptsfolder.FSResolveAlias(None)
427 path = fsr.as_pathname()
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000428 if path == self.path[:len(path)]:
429 W.getapplication().makescriptsmenu()
430
431 def domenu_save_as_applet(self, *args):
Just van Rossumdc3c6172001-06-19 21:37:33 +0000432 import buildtools
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000433
434 buildtools.DEBUG = 0 # ouch.
435
436 if self.title[-3:] == ".py":
437 destname = self.title[:-3]
438 else:
439 destname = self.title + ".applet"
Jack Jansenfd0b00e2003-01-26 22:15:48 +0000440 destname = EasyDialogs.AskFileForSave(message='Save as Applet:',
441 savedFileName=destname)
442 if not destname:
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000443 return 1
444 W.SetCursor("watch")
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000445 if self.path:
446 filename = self.path
447 if filename[-3:] == ".py":
448 rsrcname = filename[:-3] + '.rsrc'
449 else:
450 rsrcname = filename + '.rsrc'
451 else:
452 filename = self.title
453 rsrcname = ""
454
455 pytext = self.editgroup.editor.get()
456 pytext = string.split(pytext, '\r')
457 pytext = string.join(pytext, '\n') + '\n'
458 try:
459 code = compile(pytext, filename, "exec")
460 except (SyntaxError, EOFError):
461 raise buildtools.BuildError, "Syntax error in script %s" % `filename`
Jack Jansenc0452da2003-02-12 15:38:37 +0000462
463 import tempfile
464 tmpdir = tempfile.mkdtemp()
465
466 if filename[-3:] != ".py":
467 filename = filename + ".py"
468 filename = os.path.join(tmpdir, os.path.split(filename)[1])
469 fp = open(filename, "w")
470 fp.write(pytext)
471 fp.close()
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000472
473 # Try removing the output file
474 try:
475 os.remove(destname)
476 except os.error:
477 pass
478 template = buildtools.findtemplate()
Jack Jansen5bb97e62003-02-21 22:33:55 +0000479 buildtools.process(template, filename, destname, 1, rsrcname=rsrcname, progress=None)
Jack Jansenfd3e54c2003-02-16 21:28:51 +0000480 try:
481 os.remove(filename)
482 os.rmdir(tmpdir)
483 except os.error:
484 pass
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000485
486 def domenu_gotoline(self, *args):
487 self.linefield.selectall()
488 self.linefield.select(1)
489 self.linefield.selectall()
490
491 def domenu_selectline(self, *args):
492 self.editgroup.editor.expandselection()
493
494 def domenu_find(self, *args):
495 searchengine.show()
496
497 def domenu_entersearchstring(self, *args):
498 searchengine.setfindstring()
499
500 def domenu_replace(self, *args):
501 searchengine.replace()
502
503 def domenu_findnext(self, *args):
504 searchengine.findnext()
505
506 def domenu_replacefind(self, *args):
507 searchengine.replacefind()
508
509 def domenu_run(self, *args):
510 self.runbutton.push()
511
512 def domenu_runselection(self, *args):
513 self.runselbutton.push()
514
515 def run(self):
Just van Rossum73efed22000-04-09 19:45:22 +0000516 if self._threadstate == (0, 0):
517 self._run()
518 else:
Just van Rossum0f2fd162000-10-20 06:36:30 +0000519 lock = Wthreading.Lock()
520 lock.acquire()
521 self._thread.postException(KeyboardInterrupt)
522 if self._thread.isBlocked():
Just van Rossum73efed22000-04-09 19:45:22 +0000523 self._thread.start()
Just van Rossum0f2fd162000-10-20 06:36:30 +0000524 lock.release()
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000525
526 def _run(self):
Just van Rossum0f2fd162000-10-20 06:36:30 +0000527 if self.run_with_interpreter:
528 if self.editgroup.editor.changed:
Just van Rossum2ad94192002-07-12 12:06:17 +0000529 Qd.InitCursor()
Just van Rossumdc3c6172001-06-19 21:37:33 +0000530 save = EasyDialogs.AskYesNoCancel('Save "%s" before running?' % self.title, 1)
Just van Rossum0f2fd162000-10-20 06:36:30 +0000531 if save > 0:
532 if self.domenu_save():
533 return
534 elif save < 0:
535 return
536 if not self.path:
537 raise W.AlertError, "Can't run unsaved file"
538 self._run_with_interpreter()
Jack Jansenff773eb2002-03-31 22:01:33 +0000539 elif self.run_with_cl_interpreter:
Jack Jansenff773eb2002-03-31 22:01:33 +0000540 if self.editgroup.editor.changed:
Just van Rossum2ad94192002-07-12 12:06:17 +0000541 Qd.InitCursor()
Jack Jansenff773eb2002-03-31 22:01:33 +0000542 save = EasyDialogs.AskYesNoCancel('Save "%s" before running?' % self.title, 1)
543 if save > 0:
544 if self.domenu_save():
545 return
546 elif save < 0:
547 return
548 if not self.path:
549 raise W.AlertError, "Can't run unsaved file"
550 self._run_with_cl_interpreter()
Just van Rossum0f2fd162000-10-20 06:36:30 +0000551 else:
552 pytext = self.editgroup.editor.get()
553 globals, file, modname = self.getenvironment()
554 self.execstring(pytext, globals, globals, file, modname)
555
556 def _run_with_interpreter(self):
557 interp_path = os.path.join(sys.exec_prefix, "PythonInterpreter")
558 if not os.path.exists(interp_path):
559 raise W.AlertError, "Can't find interpreter"
560 import findertools
561 XXX
Jack Jansenff773eb2002-03-31 22:01:33 +0000562
563 def _run_with_cl_interpreter(self):
564 import Terminal
565 interp_path = os.path.join(sys.exec_prefix, "bin", "python")
566 file_path = self.path
567 if not os.path.exists(interp_path):
Jack Jansene7ee17c2003-02-06 22:32:35 +0000568 # This "can happen" if we are running IDE under MacPython-OS9.
569 raise W.AlertError, "Can't find command-line Python"
Jack Jansenff773eb2002-03-31 22:01:33 +0000570 cmd = '"%s" "%s" ; exit' % (interp_path, file_path)
571 t = Terminal.Terminal()
572 t.do_script(with_command=cmd)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000573
574 def runselection(self):
Just van Rossum73efed22000-04-09 19:45:22 +0000575 if self._threadstate == (0, 0):
576 self._runselection()
577 elif self._threadstate == (1, 1):
Just van Rossum0f2fd162000-10-20 06:36:30 +0000578 self._thread.block()
Just van Rossum73efed22000-04-09 19:45:22 +0000579 self.setthreadstate((1, 2))
580 elif self._threadstate == (1, 2):
581 self._thread.start()
582 self.setthreadstate((1, 1))
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000583
584 def _runselection(self):
Jack Jansenff773eb2002-03-31 22:01:33 +0000585 if self.run_with_interpreter or self.run_with_cl_interpreter:
Just van Rossum0f2fd162000-10-20 06:36:30 +0000586 raise W.AlertError, "Can't run selection with Interpreter"
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000587 globals, file, modname = self.getenvironment()
588 locals = globals
589 # select whole lines
590 self.editgroup.editor.expandselection()
591
592 # get lineno of first selected line
593 selstart, selend = self.editgroup.editor.getselection()
594 selstart, selend = min(selstart, selend), max(selstart, selend)
595 selfirstline = self.editgroup.editor.offsettoline(selstart)
596 alltext = self.editgroup.editor.get()
597 pytext = alltext[selstart:selend]
598 lines = string.split(pytext, '\r')
599 indent = getminindent(lines)
600 if indent == 1:
601 classname = ''
602 alllines = string.split(alltext, '\r')
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000603 for i in range(selfirstline - 1, -1, -1):
604 line = alllines[i]
605 if line[:6] == 'class ':
606 classname = string.split(string.strip(line[6:]))[0]
607 classend = identifieRE_match(classname)
608 if classend < 1:
Just van Rossumdc3c6172001-06-19 21:37:33 +0000609 raise W.AlertError, "Can't find a class."
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000610 classname = classname[:classend]
611 break
612 elif line and line[0] not in '\t#':
Just van Rossumdc3c6172001-06-19 21:37:33 +0000613 raise W.AlertError, "Can't find a class."
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000614 else:
Just van Rossumdc3c6172001-06-19 21:37:33 +0000615 raise W.AlertError, "Can't find a class."
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000616 if globals.has_key(classname):
Just van Rossum25ddc632001-07-05 07:06:26 +0000617 klass = globals[classname]
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000618 else:
Just van Rossumdc3c6172001-06-19 21:37:33 +0000619 raise W.AlertError, "Can't find class \"%s\"." % classname
Just van Rossum25ddc632001-07-05 07:06:26 +0000620 # add class def
621 pytext = ("class %s:\n" % classname) + pytext
622 selfirstline = selfirstline - 1
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000623 elif indent > 0:
Just van Rossumdc3c6172001-06-19 21:37:33 +0000624 raise W.AlertError, "Can't run indented code."
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000625
626 # add "newlines" to fool compile/exec:
627 # now a traceback will give the right line number
628 pytext = selfirstline * '\r' + pytext
629 self.execstring(pytext, globals, locals, file, modname)
Just van Rossum25ddc632001-07-05 07:06:26 +0000630 if indent == 1 and globals[classname] is not klass:
631 # update the class in place
632 klass.__dict__.update(globals[classname].__dict__)
633 globals[classname] = klass
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000634
Just van Rossum73efed22000-04-09 19:45:22 +0000635 def setthreadstate(self, state):
636 oldstate = self._threadstate
637 if oldstate[0] <> state[0]:
638 self.runbutton.settitle(runButtonLabels[state[0]])
639 if oldstate[1] <> state[1]:
640 self.runselbutton.settitle(runSelButtonLabels[state[1]])
641 self._threadstate = state
642
643 def _exec_threadwrapper(self, *args, **kwargs):
644 apply(execstring, args, kwargs)
645 self.setthreadstate((0, 0))
646 self._thread = None
647
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000648 def execstring(self, pytext, globals, locals, file, modname):
649 tracebackwindow.hide()
650 # update windows
651 W.getapplication().refreshwindows()
652 if self.run_as_main:
653 modname = "__main__"
654 if self.path:
655 dir = os.path.dirname(self.path)
656 savedir = os.getcwd()
657 os.chdir(dir)
Just van Rossuma61f4ac1999-02-01 16:34:08 +0000658 sys.path.insert(0, dir)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000659 else:
660 cwdindex = None
661 try:
Just van Rossum0f2fd162000-10-20 06:36:30 +0000662 if haveThreading:
663 self._thread = Wthreading.Thread(os.path.basename(file),
Just van Rossum73efed22000-04-09 19:45:22 +0000664 self._exec_threadwrapper, pytext, globals, locals, file, self.debugging,
665 modname, self.profiling)
666 self.setthreadstate((1, 1))
667 self._thread.start()
668 else:
669 execstring(pytext, globals, locals, file, self.debugging,
670 modname, self.profiling)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000671 finally:
672 if self.path:
673 os.chdir(savedir)
Just van Rossuma61f4ac1999-02-01 16:34:08 +0000674 del sys.path[0]
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000675
676 def getenvironment(self):
677 if self.path:
678 file = self.path
679 dir = os.path.dirname(file)
680 # check if we're part of a package
681 modname = ""
682 while os.path.exists(os.path.join(dir, "__init__.py")):
683 dir, dirname = os.path.split(dir)
Just van Rossum2aaeb521999-02-05 21:58:25 +0000684 modname = dirname + '.' + modname
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000685 subname = _filename_as_modname(self.title)
Just van Rossumf7f93882001-11-02 19:24:41 +0000686 if subname is None:
687 return self.globals, file, None
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000688 if modname:
689 if subname == "__init__":
Just van Rossum2aaeb521999-02-05 21:58:25 +0000690 # strip trailing period
691 modname = modname[:-1]
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000692 else:
Just van Rossum2aaeb521999-02-05 21:58:25 +0000693 modname = modname + subname
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000694 else:
695 modname = subname
696 if sys.modules.has_key(modname):
697 globals = sys.modules[modname].__dict__
698 self.globals = {}
699 else:
700 globals = self.globals
Just van Rossum73efed22000-04-09 19:45:22 +0000701 modname = subname
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000702 else:
703 file = '<%s>' % self.title
704 globals = self.globals
705 modname = file
706 return globals, file, modname
707
708 def write(self, stuff):
709 """for use as stdout"""
710 self._buf = self._buf + stuff
711 if '\n' in self._buf:
712 self.flush()
713
714 def flush(self):
715 stuff = string.split(self._buf, '\n')
716 stuff = string.join(stuff, '\r')
717 end = self.editgroup.editor.ted.WEGetTextLength()
718 self.editgroup.editor.ted.WESetSelection(end, end)
719 self.editgroup.editor.ted.WEInsert(stuff, None, None)
720 self.editgroup.editor.updatescrollbars()
721 self._buf = ""
722 # ? optional:
723 #self.wid.SelectWindow()
724
725 def getclasslist(self):
726 from string import find, strip
Just van Rossum24073ea1999-12-23 15:46:57 +0000727 methodRE = re.compile(r"\r[ \t]+def ")
728 findMethod = methodRE.search
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000729 editor = self.editgroup.editor
730 text = editor.get()
731 list = []
732 append = list.append
733 functag = "func"
734 classtag = "class"
735 methodtag = "method"
736 pos = -1
737 if text[:4] == 'def ':
738 append((pos + 4, functag))
739 pos = 4
740 while 1:
741 pos = find(text, '\rdef ', pos + 1)
742 if pos < 0:
743 break
744 append((pos + 5, functag))
745 pos = -1
746 if text[:6] == 'class ':
747 append((pos + 6, classtag))
748 pos = 6
749 while 1:
750 pos = find(text, '\rclass ', pos + 1)
751 if pos < 0:
752 break
753 append((pos + 7, classtag))
754 pos = 0
755 while 1:
Just van Rossum24073ea1999-12-23 15:46:57 +0000756 m = findMethod(text, pos + 1)
757 if m is None:
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000758 break
Just van Rossum24073ea1999-12-23 15:46:57 +0000759 pos = m.regs[0][0]
760 #pos = find(text, '\r\tdef ', pos + 1)
761 append((m.regs[0][1], methodtag))
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000762 list.sort()
763 classlist = []
764 methodlistappend = None
765 offsetToLine = editor.ted.WEOffsetToLine
766 getLineRange = editor.ted.WEGetLineRange
767 append = classlist.append
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000768 for pos, tag in list:
769 lineno = offsetToLine(pos)
770 lineStart, lineEnd = getLineRange(lineno)
771 line = strip(text[pos:lineEnd])
772 line = line[:identifieRE_match(line)]
773 if tag is functag:
774 append(("def " + line, lineno + 1))
775 methodlistappend = None
776 elif tag is classtag:
777 append(["class " + line])
778 methodlistappend = classlist[-1].append
779 elif methodlistappend and tag is methodtag:
780 methodlistappend(("def " + line, lineno + 1))
781 return classlist
782
783 def popselectline(self, lineno):
784 self.editgroup.editor.selectline(lineno - 1)
785
786 def selectline(self, lineno, charoffset = 0):
787 self.editgroup.editor.selectline(lineno - 1, charoffset)
Jack Jansenc00b6d72003-02-25 15:08:02 +0000788
789 def addrecentfile(self, filename):
790 app = W.getapplication()
791 app.addrecentfile(filename)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000792
Just van Rossum12710051999-02-27 17:18:30 +0000793class _saveoptions:
794
Jack Jansen9a389472002-03-29 21:26:04 +0000795 def __init__(self, creator, eoln):
Just van Rossum12710051999-02-27 17:18:30 +0000796 self.rv = None
Jack Jansen9a389472002-03-29 21:26:04 +0000797 self.eoln = eoln
798 self.w = w = W.ModalDialog((260, 160), 'Save options')
Just van Rossum12710051999-02-27 17:18:30 +0000799 radiobuttons = []
800 w.label = W.TextBox((8, 8, 80, 18), "File creator:")
Just van Rossum3af507d1999-04-22 22:23:46 +0000801 w.ide_radio = W.RadioButton((8, 22, 160, 18), "This application", radiobuttons, self.ide_hit)
Jack Jansen9a389472002-03-29 21:26:04 +0000802 w.interp_radio = W.RadioButton((8, 42, 160, 18), "MacPython Interpreter", radiobuttons, self.interp_hit)
803 w.interpx_radio = W.RadioButton((8, 62, 160, 18), "OSX PythonW Interpreter", radiobuttons, self.interpx_hit)
804 w.other_radio = W.RadioButton((8, 82, 50, 18), "Other:", radiobuttons)
805 w.other_creator = W.EditText((62, 82, 40, 20), creator, self.otherselect)
806 w.none_radio = W.RadioButton((8, 102, 160, 18), "None", radiobuttons, self.none_hit)
Just van Rossum12710051999-02-27 17:18:30 +0000807 w.cancelbutton = W.Button((-180, -30, 80, 16), "Cancel", self.cancelbuttonhit)
808 w.okbutton = W.Button((-90, -30, 80, 16), "Done", self.okbuttonhit)
809 w.setdefaultbutton(w.okbutton)
810 if creator == 'Pyth':
811 w.interp_radio.set(1)
Just van Rossum3af507d1999-04-22 22:23:46 +0000812 elif creator == W._signature:
Just van Rossum12710051999-02-27 17:18:30 +0000813 w.ide_radio.set(1)
Jack Jansen9a389472002-03-29 21:26:04 +0000814 elif creator == 'PytX':
815 w.interpx_radio.set(1)
816 elif creator == '\0\0\0\0':
817 w.none_radio.set(1)
Just van Rossum12710051999-02-27 17:18:30 +0000818 else:
819 w.other_radio.set(1)
Jack Jansen9a389472002-03-29 21:26:04 +0000820
821 w.eolnlabel = W.TextBox((168, 8, 80, 18), "Newline style:")
822 radiobuttons = []
823 w.unix_radio = W.RadioButton((168, 22, 80, 18), "Unix", radiobuttons, self.unix_hit)
824 w.mac_radio = W.RadioButton((168, 42, 80, 18), "Macintosh", radiobuttons, self.mac_hit)
825 w.win_radio = W.RadioButton((168, 62, 80, 18), "Windows", radiobuttons, self.win_hit)
826 if self.eoln == '\n':
827 w.unix_radio.set(1)
828 elif self.eoln == '\r\n':
829 w.win_radio.set(1)
830 else:
831 w.mac_radio.set(1)
832
Just van Rossum12710051999-02-27 17:18:30 +0000833 w.bind("cmd.", w.cancelbutton.push)
834 w.open()
835
836 def ide_hit(self):
Just van Rossum3af507d1999-04-22 22:23:46 +0000837 self.w.other_creator.set(W._signature)
Just van Rossum12710051999-02-27 17:18:30 +0000838
839 def interp_hit(self):
840 self.w.other_creator.set("Pyth")
841
Jack Jansen9a389472002-03-29 21:26:04 +0000842 def interpx_hit(self):
843 self.w.other_creator.set("PytX")
844
845 def none_hit(self):
846 self.w.other_creator.set("\0\0\0\0")
847
Just van Rossum12710051999-02-27 17:18:30 +0000848 def otherselect(self, *args):
849 sel_from, sel_to = self.w.other_creator.getselection()
850 creator = self.w.other_creator.get()[:4]
851 creator = creator + " " * (4 - len(creator))
852 self.w.other_creator.set(creator)
853 self.w.other_creator.setselection(sel_from, sel_to)
854 self.w.other_radio.set(1)
855
Jack Jansen9a389472002-03-29 21:26:04 +0000856 def mac_hit(self):
857 self.eoln = '\r'
858
859 def unix_hit(self):
860 self.eoln = '\n'
861
862 def win_hit(self):
863 self.eoln = '\r\n'
864
Just van Rossum12710051999-02-27 17:18:30 +0000865 def cancelbuttonhit(self):
866 self.w.close()
867
868 def okbuttonhit(self):
Jack Jansen9a389472002-03-29 21:26:04 +0000869 self.rv = (self.w.other_creator.get()[:4], self.eoln)
Just van Rossum12710051999-02-27 17:18:30 +0000870 self.w.close()
871
872
Jack Jansen9a389472002-03-29 21:26:04 +0000873def SaveOptions(creator, eoln):
874 s = _saveoptions(creator, eoln)
Just van Rossum12710051999-02-27 17:18:30 +0000875 return s.rv
876
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000877
878def _escape(where, what) :
879 return string.join(string.split(where, what), '\\' + what)
880
881def _makewholewordpattern(word):
882 # first, escape special regex chars
Just van Rossum3eec7622001-07-10 19:25:40 +0000883 for esc in "\\[]()|.*^+$?":
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000884 word = _escape(word, esc)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000885 notwordcharspat = '[^' + _wordchars + ']'
Jack Jansen9ad27522001-02-21 13:54:31 +0000886 pattern = '(' + word + ')'
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000887 if word[0] in _wordchars:
888 pattern = notwordcharspat + pattern
889 if word[-1] in _wordchars:
890 pattern = pattern + notwordcharspat
Jack Jansen9ad27522001-02-21 13:54:31 +0000891 return re.compile(pattern)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000892
Just van Rossumf376ef02001-11-18 14:12:43 +0000893
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000894class SearchEngine:
895
896 def __init__(self):
897 self.visible = 0
898 self.w = None
899 self.parms = { "find": "",
900 "replace": "",
901 "wrap": 1,
902 "casesens": 1,
903 "wholeword": 1
904 }
905 import MacPrefs
906 prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath)
907 if prefs.searchengine:
908 self.parms["casesens"] = prefs.searchengine.casesens
909 self.parms["wrap"] = prefs.searchengine.wrap
910 self.parms["wholeword"] = prefs.searchengine.wholeword
911
912 def show(self):
913 self.visible = 1
914 if self.w:
915 self.w.wid.ShowWindow()
916 self.w.wid.SelectWindow()
917 self.w.find.edit.select(1)
918 self.w.find.edit.selectall()
919 return
920 self.w = W.Dialog((420, 150), "Find")
921
922 self.w.find = TitledEditText((10, 4, 300, 36), "Search for:")
923 self.w.replace = TitledEditText((10, 100, 300, 36), "Replace with:")
924
925 self.w.boxes = W.Group((10, 50, 300, 40))
926 self.w.boxes.casesens = W.CheckBox((0, 0, 100, 16), "Case sensitive")
927 self.w.boxes.wholeword = W.CheckBox((0, 20, 100, 16), "Whole word")
928 self.w.boxes.wrap = W.CheckBox((110, 0, 100, 16), "Wrap around")
929
930 self.buttons = [ ("Find", "cmdf", self.find),
931 ("Replace", "cmdr", self.replace),
932 ("Replace all", None, self.replaceall),
Just van Rossumdc3c6172001-06-19 21:37:33 +0000933 ("Don't find", "cmdd", self.dont),
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000934 ("Cancel", "cmd.", self.cancel)
935 ]
936 for i in range(len(self.buttons)):
937 bounds = -90, 22 + i * 24, 80, 16
938 title, shortcut, callback = self.buttons[i]
939 self.w[title] = W.Button(bounds, title, callback)
940 if shortcut:
941 self.w.bind(shortcut, self.w[title].push)
Just van Rossumdc3c6172001-06-19 21:37:33 +0000942 self.w.setdefaultbutton(self.w["Don't find"])
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000943 self.w.find.edit.bind("<key>", self.key)
944 self.w.bind("<activate>", self.activate)
945 self.w.bind("<close>", self.close)
946 self.w.open()
947 self.setparms()
948 self.w.find.edit.select(1)
949 self.w.find.edit.selectall()
950 self.checkbuttons()
951
952 def close(self):
953 self.hide()
954 return -1
955
956 def key(self, char, modifiers):
957 self.w.find.edit.key(char, modifiers)
958 self.checkbuttons()
959 return 1
960
961 def activate(self, onoff):
962 if onoff:
963 self.checkbuttons()
964
965 def checkbuttons(self):
966 editor = findeditor(self)
967 if editor:
968 if self.w.find.get():
969 for title, cmd, call in self.buttons[:-2]:
970 self.w[title].enable(1)
971 self.w.setdefaultbutton(self.w["Find"])
972 else:
973 for title, cmd, call in self.buttons[:-2]:
974 self.w[title].enable(0)
Just van Rossumdc3c6172001-06-19 21:37:33 +0000975 self.w.setdefaultbutton(self.w["Don't find"])
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000976 else:
977 for title, cmd, call in self.buttons[:-2]:
978 self.w[title].enable(0)
Just van Rossumdc3c6172001-06-19 21:37:33 +0000979 self.w.setdefaultbutton(self.w["Don't find"])
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000980
981 def find(self):
982 self.getparmsfromwindow()
983 if self.findnext():
984 self.hide()
985
986 def replace(self):
987 editor = findeditor(self)
988 if not editor:
989 return
990 if self.visible:
991 self.getparmsfromwindow()
992 text = editor.getselectedtext()
993 find = self.parms["find"]
994 if not self.parms["casesens"]:
995 find = string.lower(find)
996 text = string.lower(text)
997 if text == find:
998 self.hide()
999 editor.insert(self.parms["replace"])
1000
1001 def replaceall(self):
1002 editor = findeditor(self)
1003 if not editor:
1004 return
1005 if self.visible:
1006 self.getparmsfromwindow()
1007 W.SetCursor("watch")
1008 find = self.parms["find"]
1009 if not find:
1010 return
1011 findlen = len(find)
1012 replace = self.parms["replace"]
1013 replacelen = len(replace)
1014 Text = editor.get()
1015 if not self.parms["casesens"]:
1016 find = string.lower(find)
1017 text = string.lower(Text)
1018 else:
1019 text = Text
1020 newtext = ""
1021 pos = 0
1022 counter = 0
1023 while 1:
1024 if self.parms["wholeword"]:
1025 wholewordRE = _makewholewordpattern(find)
Jack Jansen9ad27522001-02-21 13:54:31 +00001026 match = wholewordRE.search(text, pos)
1027 if match:
1028 pos = match.start(1)
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001029 else:
1030 pos = -1
1031 else:
1032 pos = string.find(text, find, pos)
1033 if pos < 0:
1034 break
1035 counter = counter + 1
1036 text = text[:pos] + replace + text[pos + findlen:]
1037 Text = Text[:pos] + replace + Text[pos + findlen:]
1038 pos = pos + replacelen
1039 W.SetCursor("arrow")
1040 if counter:
1041 self.hide()
Jack Jansen5a6fdcd2001-08-25 12:15:04 +00001042 from Carbon import Res
Just van Rossumf7f93882001-11-02 19:24:41 +00001043 editor.textchanged()
1044 editor.selectionchanged()
Just van Rossum7b025512002-10-24 20:03:29 +00001045 editor.set(Text)
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001046 EasyDialogs.Message("Replaced %d occurrences" % counter)
1047
1048 def dont(self):
1049 self.getparmsfromwindow()
1050 self.hide()
1051
1052 def replacefind(self):
1053 self.replace()
1054 self.findnext()
1055
1056 def setfindstring(self):
1057 editor = findeditor(self)
1058 if not editor:
1059 return
1060 find = editor.getselectedtext()
1061 if not find:
1062 return
1063 self.parms["find"] = find
1064 if self.w:
1065 self.w.find.edit.set(self.parms["find"])
1066 self.w.find.edit.selectall()
1067
1068 def findnext(self):
1069 editor = findeditor(self)
1070 if not editor:
1071 return
1072 find = self.parms["find"]
1073 if not find:
1074 return
1075 text = editor.get()
1076 if not self.parms["casesens"]:
1077 find = string.lower(find)
1078 text = string.lower(text)
1079 selstart, selend = editor.getselection()
1080 selstart, selend = min(selstart, selend), max(selstart, selend)
1081 if self.parms["wholeword"]:
1082 wholewordRE = _makewholewordpattern(find)
Jack Jansen9ad27522001-02-21 13:54:31 +00001083 match = wholewordRE.search(text, selend)
1084 if match:
1085 pos = match.start(1)
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001086 else:
1087 pos = -1
1088 else:
1089 pos = string.find(text, find, selend)
1090 if pos >= 0:
1091 editor.setselection(pos, pos + len(find))
1092 return 1
1093 elif self.parms["wrap"]:
1094 if self.parms["wholeword"]:
Jack Jansen9ad27522001-02-21 13:54:31 +00001095 match = wholewordRE.search(text, 0)
1096 if match:
1097 pos = match.start(1)
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001098 else:
1099 pos = -1
1100 else:
1101 pos = string.find(text, find)
1102 if selstart > pos >= 0:
1103 editor.setselection(pos, pos + len(find))
1104 return 1
1105
1106 def setparms(self):
1107 for key, value in self.parms.items():
1108 try:
1109 self.w[key].set(value)
1110 except KeyError:
1111 self.w.boxes[key].set(value)
1112
1113 def getparmsfromwindow(self):
1114 if not self.w:
1115 return
1116 for key, value in self.parms.items():
1117 try:
1118 value = self.w[key].get()
1119 except KeyError:
1120 value = self.w.boxes[key].get()
1121 self.parms[key] = value
1122
1123 def cancel(self):
1124 self.hide()
1125 self.setparms()
1126
1127 def hide(self):
1128 if self.w:
1129 self.w.wid.HideWindow()
1130 self.visible = 0
1131
1132 def writeprefs(self):
1133 import MacPrefs
1134 self.getparmsfromwindow()
1135 prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath)
1136 prefs.searchengine.casesens = self.parms["casesens"]
1137 prefs.searchengine.wrap = self.parms["wrap"]
1138 prefs.searchengine.wholeword = self.parms["wholeword"]
1139 prefs.save()
1140
1141
1142class TitledEditText(W.Group):
1143
1144 def __init__(self, possize, title, text = ""):
1145 W.Group.__init__(self, possize)
1146 self.title = W.TextBox((0, 0, 0, 16), title)
1147 self.edit = W.EditText((0, 16, 0, 0), text)
1148
1149 def set(self, value):
1150 self.edit.set(value)
1151
1152 def get(self):
1153 return self.edit.get()
1154
1155
1156class ClassFinder(W.PopupWidget):
1157
1158 def click(self, point, modifiers):
1159 W.SetCursor("watch")
1160 self.set(self._parentwindow.getclasslist())
1161 W.PopupWidget.click(self, point, modifiers)
1162
1163
1164def getminindent(lines):
1165 indent = -1
1166 for line in lines:
1167 stripped = string.strip(line)
1168 if not stripped or stripped[0] == '#':
1169 continue
1170 if indent < 0 or line[:indent] <> indent * '\t':
1171 indent = 0
1172 for c in line:
1173 if c <> '\t':
1174 break
1175 indent = indent + 1
1176 return indent
1177
1178
1179def getoptionkey():
1180 return not not ord(Evt.GetKeys()[7]) & 0x04
1181
1182
1183def execstring(pytext, globals, locals, filename="<string>", debugging=0,
1184 modname="__main__", profiling=0):
1185 if debugging:
1186 import PyDebugger, bdb
1187 BdbQuit = bdb.BdbQuit
1188 else:
1189 BdbQuit = 'BdbQuitDummyException'
1190 pytext = string.split(pytext, '\r')
1191 pytext = string.join(pytext, '\n') + '\n'
1192 W.SetCursor("watch")
1193 globals['__name__'] = modname
1194 globals['__file__'] = filename
1195 sys.argv = [filename]
1196 try:
1197 code = compile(pytext, filename, "exec")
1198 except:
1199 # XXXX BAAAADDD.... We let tracebackwindow decide to treat SyntaxError
1200 # special. That's wrong because THIS case is special (could be literal
1201 # overflow!) and SyntaxError could mean we need a traceback (syntax error
1202 # in imported module!!!
1203 tracebackwindow.traceback(1, filename)
1204 return
1205 try:
1206 if debugging:
Just van Rossum0f2fd162000-10-20 06:36:30 +00001207 if haveThreading:
1208 lock = Wthreading.Lock()
1209 lock.acquire()
Just van Rossum73efed22000-04-09 19:45:22 +00001210 PyDebugger.startfromhere()
Just van Rossum0f2fd162000-10-20 06:36:30 +00001211 lock.release()
Just van Rossum73efed22000-04-09 19:45:22 +00001212 else:
1213 PyDebugger.startfromhere()
Just van Rossum0f2fd162000-10-20 06:36:30 +00001214 elif not haveThreading:
Jack Jansen815d2bf2002-01-21 23:00:52 +00001215 if hasattr(MacOS, 'EnableAppswitch'):
1216 MacOS.EnableAppswitch(0)
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001217 try:
1218 if profiling:
1219 import profile, ProfileBrowser
1220 p = profile.Profile()
1221 p.set_cmd(filename)
1222 try:
1223 p.runctx(code, globals, locals)
1224 finally:
1225 import pstats
1226
1227 stats = pstats.Stats(p)
1228 ProfileBrowser.ProfileBrowser(stats)
1229 else:
1230 exec code in globals, locals
1231 finally:
Just van Rossum0f2fd162000-10-20 06:36:30 +00001232 if not haveThreading:
Jack Jansen815d2bf2002-01-21 23:00:52 +00001233 if hasattr(MacOS, 'EnableAppswitch'):
1234 MacOS.EnableAppswitch(-1)
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001235 except W.AlertError, detail:
1236 raise W.AlertError, detail
1237 except (KeyboardInterrupt, BdbQuit):
1238 pass
Just van Rossumf7f93882001-11-02 19:24:41 +00001239 except SystemExit, arg:
1240 if arg.code:
1241 sys.stderr.write("Script exited with status code: %s\n" % repr(arg.code))
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001242 except:
Just van Rossum0f2fd162000-10-20 06:36:30 +00001243 if haveThreading:
1244 import continuation
1245 lock = Wthreading.Lock()
1246 lock.acquire()
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001247 if debugging:
1248 sys.settrace(None)
1249 PyDebugger.postmortem(sys.exc_type, sys.exc_value, sys.exc_traceback)
1250 return
1251 else:
1252 tracebackwindow.traceback(1, filename)
Just van Rossum0f2fd162000-10-20 06:36:30 +00001253 if haveThreading:
1254 lock.release()
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001255 if debugging:
1256 sys.settrace(None)
1257 PyDebugger.stop()
1258
1259
Just van Rossum3eec7622001-07-10 19:25:40 +00001260_identifieRE = re.compile(r"[A-Za-z_][A-Za-z_0-9]*")
Jack Jansen9ad27522001-02-21 13:54:31 +00001261
1262def identifieRE_match(str):
1263 match = _identifieRE.match(str)
1264 if not match:
1265 return -1
1266 return match.end()
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001267
1268def _filename_as_modname(fname):
1269 if fname[-3:] == '.py':
1270 modname = fname[:-3]
Jack Jansen9ad27522001-02-21 13:54:31 +00001271 match = _identifieRE.match(modname)
1272 if match and match.start() == 0 and match.end() == len(modname):
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001273 return string.join(string.split(modname, '.'), '_')
1274
1275def findeditor(topwindow, fromtop = 0):
Just van Rossum40144012002-02-04 12:52:44 +00001276 wid = MyFrontWindow()
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001277 if not fromtop:
1278 if topwindow.w and wid == topwindow.w.wid:
1279 wid = topwindow.w.wid.GetNextWindow()
1280 if not wid:
1281 return
1282 app = W.getapplication()
1283 if app._windows.has_key(wid): # KeyError otherwise can happen in RoboFog :-(
1284 window = W.getapplication()._windows[wid]
1285 else:
1286 return
1287 if not isinstance(window, Editor):
1288 return
1289 return window.editgroup.editor
1290
1291
1292class _EditorDefaultSettings:
1293
1294 def __init__(self):
1295 self.template = "%s, %d point"
1296 self.fontsettings, self.tabsettings, self.windowsize = geteditorprefs()
1297 self.w = W.Dialog((328, 120), "Editor default settings")
Just van Rossumdc3c6172001-06-19 21:37:33 +00001298 self.w.setfontbutton = W.Button((8, 8, 80, 16), "Set font\xc9", self.dofont)
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001299 self.w.fonttext = W.TextBox((98, 10, -8, 14), self.template % (self.fontsettings[0], self.fontsettings[2]))
1300
1301 self.w.picksizebutton = W.Button((8, 50, 80, 16), "Front window", self.picksize)
1302 self.w.xsizelabel = W.TextBox((98, 32, 40, 14), "Width:")
1303 self.w.ysizelabel = W.TextBox((148, 32, 40, 14), "Height:")
1304 self.w.xsize = W.EditText((98, 48, 40, 20), `self.windowsize[0]`)
1305 self.w.ysize = W.EditText((148, 48, 40, 20), `self.windowsize[1]`)
1306
1307 self.w.cancelbutton = W.Button((-180, -26, 80, 16), "Cancel", self.cancel)
1308 self.w.okbutton = W.Button((-90, -26, 80, 16), "Done", self.ok)
1309 self.w.setdefaultbutton(self.w.okbutton)
1310 self.w.bind('cmd.', self.w.cancelbutton.push)
1311 self.w.open()
1312
1313 def picksize(self):
1314 app = W.getapplication()
1315 editor = findeditor(self)
1316 if editor is not None:
1317 width, height = editor._parentwindow._bounds[2:]
1318 self.w.xsize.set(`width`)
1319 self.w.ysize.set(`height`)
1320 else:
1321 raise W.AlertError, "No edit window found"
1322
1323 def dofont(self):
1324 import FontSettings
1325 settings = FontSettings.FontDialog(self.fontsettings, self.tabsettings)
1326 if settings:
1327 self.fontsettings, self.tabsettings = settings
1328 sys.exc_traceback = None
1329 self.w.fonttext.set(self.template % (self.fontsettings[0], self.fontsettings[2]))
1330
1331 def close(self):
1332 self.w.close()
1333 del self.w
1334
1335 def cancel(self):
1336 self.close()
1337
1338 def ok(self):
1339 try:
1340 width = string.atoi(self.w.xsize.get())
1341 except:
1342 self.w.xsize.select(1)
1343 self.w.xsize.selectall()
1344 raise W.AlertError, "Bad number for window width"
1345 try:
1346 height = string.atoi(self.w.ysize.get())
1347 except:
1348 self.w.ysize.select(1)
1349 self.w.ysize.selectall()
1350 raise W.AlertError, "Bad number for window height"
1351 self.windowsize = width, height
1352 seteditorprefs(self.fontsettings, self.tabsettings, self.windowsize)
1353 self.close()
1354
1355def geteditorprefs():
1356 import MacPrefs
1357 prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath)
1358 try:
1359 fontsettings = prefs.pyedit.fontsettings
1360 tabsettings = prefs.pyedit.tabsettings
1361 windowsize = prefs.pyedit.windowsize
1362 except:
Just van Rossumf7f93882001-11-02 19:24:41 +00001363 fontsettings = prefs.pyedit.fontsettings = ("Geneva", 0, 10, (0, 0, 0))
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001364 tabsettings = prefs.pyedit.tabsettings = (8, 1)
1365 windowsize = prefs.pyedit.windowsize = (500, 250)
1366 sys.exc_traceback = None
1367 return fontsettings, tabsettings, windowsize
1368
1369def seteditorprefs(fontsettings, tabsettings, windowsize):
1370 import MacPrefs
1371 prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath)
1372 prefs.pyedit.fontsettings = fontsettings
1373 prefs.pyedit.tabsettings = tabsettings
1374 prefs.pyedit.windowsize = windowsize
1375 prefs.save()
1376
1377_defaultSettingsEditor = None
1378
1379def EditorDefaultSettings():
1380 global _defaultSettingsEditor
1381 if _defaultSettingsEditor is None or not hasattr(_defaultSettingsEditor, "w"):
1382 _defaultSettingsEditor = _EditorDefaultSettings()
1383 else:
1384 _defaultSettingsEditor.w.select()
1385
1386def resolvealiases(path):
1387 try:
Jack Jansene7ee17c2003-02-06 22:32:35 +00001388 fsr, d1, d2 = File.FSResolveAliasFile(path, 1)
1389 path = fsr.as_pathname()
1390 return path
1391 except (File.Error, ValueError), (error, str):
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001392 if error <> -120:
1393 raise
1394 dir, file = os.path.split(path)
1395 return os.path.join(resolvealiases(dir), file)
1396
1397searchengine = SearchEngine()
1398tracebackwindow = Wtraceback.TraceBack()