blob: 91a7ab1371dba6ed8d7f65f7ad4017c4f9be3dd6 [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
7import macfs
Jack Jansen64aa1e22001-01-29 15:19:17 +00008import MACFS
Just van Rossum40f9b7b1999-01-30 22:39:17 +00009import MacOS
Jack Jansen5a6fdcd2001-08-25 12:15:04 +000010from Carbon import Win
11from Carbon import Res
12from Carbon import Evt
Just van Rossum40f9b7b1999-01-30 22:39:17 +000013import os
14import imp
15import sys
16import string
17import marshal
Jack Jansen9ad27522001-02-21 13:54:31 +000018import re
Just van Rossum40f9b7b1999-01-30 22:39:17 +000019
Just van Rossum40144012002-02-04 12:52:44 +000020if hasattr(Win, "FrontNonFloatingWindow"):
21 MyFrontWindow = Win.FrontNonFloatingWindow
22else:
23 MyFrontWindow = Win.FrontWindow
24
25
Just van Rossum73efed22000-04-09 19:45:22 +000026try:
Just van Rossum0f2fd162000-10-20 06:36:30 +000027 import Wthreading
Just van Rossum73efed22000-04-09 19:45:22 +000028except ImportError:
Just van Rossum0f2fd162000-10-20 06:36:30 +000029 haveThreading = 0
30else:
31 haveThreading = Wthreading.haveThreading
Just van Rossum73efed22000-04-09 19:45:22 +000032
Just van Rossum40f9b7b1999-01-30 22:39:17 +000033_scriptuntitledcounter = 1
Fred Drake79e75e12001-07-20 19:05:50 +000034_wordchars = string.ascii_letters + string.digits + "_"
Just van Rossum40f9b7b1999-01-30 22:39:17 +000035
36
Just van Rossum73efed22000-04-09 19:45:22 +000037runButtonLabels = ["Run all", "Stop!"]
38runSelButtonLabels = ["Run selection", "Pause!", "Resume"]
39
40
Just van Rossum40f9b7b1999-01-30 22:39:17 +000041class Editor(W.Window):
42
43 def __init__(self, path = "", title = ""):
44 defaultfontsettings, defaulttabsettings, defaultwindowsize = geteditorprefs()
45 global _scriptuntitledcounter
46 if not path:
47 if title:
48 self.title = title
49 else:
50 self.title = "Untitled Script " + `_scriptuntitledcounter`
51 _scriptuntitledcounter = _scriptuntitledcounter + 1
52 text = ""
53 self._creator = W._signature
Jack Jansen9a389472002-03-29 21:26:04 +000054 self._eoln = os.linesep
Just van Rossum40f9b7b1999-01-30 22:39:17 +000055 elif os.path.exists(path):
56 path = resolvealiases(path)
57 dir, name = os.path.split(path)
58 self.title = name
59 f = open(path, "rb")
60 text = f.read()
61 f.close()
62 fss = macfs.FSSpec(path)
63 self._creator, filetype = fss.GetCreatorType()
64 else:
65 raise IOError, "file '%s' does not exist" % path
66 self.path = path
67
Just van Rossumc7ba0801999-05-21 21:42:27 +000068 if '\n' in text:
69 import EasyDialogs
70 if string.find(text, '\r\n') >= 0:
Jack Jansen9a389472002-03-29 21:26:04 +000071 self._eoln = '\r\n'
Just van Rossumc7ba0801999-05-21 21:42:27 +000072 else:
Jack Jansen9a389472002-03-29 21:26:04 +000073 self._eoln = '\n'
74 text = string.replace(text, self._eoln, '\r')
75 change = 0
Just van Rossumc7ba0801999-05-21 21:42:27 +000076 else:
77 change = 0
Jack Jansen9a389472002-03-29 21:26:04 +000078 self._eoln = '\r'
Just van Rossumc7ba0801999-05-21 21:42:27 +000079
Just van Rossum40f9b7b1999-01-30 22:39:17 +000080 self.settings = {}
81 if self.path:
82 self.readwindowsettings()
83 if self.settings.has_key("windowbounds"):
84 bounds = self.settings["windowbounds"]
85 else:
86 bounds = defaultwindowsize
87 if self.settings.has_key("fontsettings"):
88 self.fontsettings = self.settings["fontsettings"]
89 else:
90 self.fontsettings = defaultfontsettings
91 if self.settings.has_key("tabsize"):
92 try:
93 self.tabsettings = (tabsize, tabmode) = self.settings["tabsize"]
94 except:
95 self.tabsettings = defaulttabsettings
96 else:
97 self.tabsettings = defaulttabsettings
Just van Rossum40f9b7b1999-01-30 22:39:17 +000098
Just van Rossumc7ba0801999-05-21 21:42:27 +000099 W.Window.__init__(self, bounds, self.title, minsize = (330, 120), tabbable = 0)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000100 self.setupwidgets(text)
Just van Rossumc7ba0801999-05-21 21:42:27 +0000101 if change > 0:
Just van Rossumf7f93882001-11-02 19:24:41 +0000102 self.editgroup.editor.textchanged()
Just van Rossumc7ba0801999-05-21 21:42:27 +0000103
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000104 if self.settings.has_key("selection"):
105 selstart, selend = self.settings["selection"]
106 self.setselection(selstart, selend)
107 self.open()
108 self.setinfotext()
109 self.globals = {}
110 self._buf = "" # for write method
111 self.debugging = 0
112 self.profiling = 0
113 if self.settings.has_key("run_as_main"):
114 self.run_as_main = self.settings["run_as_main"]
115 else:
116 self.run_as_main = 0
Just van Rossum0f2fd162000-10-20 06:36:30 +0000117 if self.settings.has_key("run_with_interpreter"):
118 self.run_with_interpreter = self.settings["run_with_interpreter"]
119 else:
120 self.run_with_interpreter = 0
Just van Rossum73efed22000-04-09 19:45:22 +0000121 self._threadstate = (0, 0)
122 self._thread = None
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000123
124 def readwindowsettings(self):
125 try:
Jack Jansend13c3852000-06-20 21:59:25 +0000126 resref = Res.FSpOpenResFile(self.path, 1)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000127 except Res.Error:
128 return
129 try:
130 Res.UseResFile(resref)
131 data = Res.Get1Resource('PyWS', 128)
132 self.settings = marshal.loads(data.data)
133 except:
134 pass
135 Res.CloseResFile(resref)
136
137 def writewindowsettings(self):
138 try:
Jack Jansend13c3852000-06-20 21:59:25 +0000139 resref = Res.FSpOpenResFile(self.path, 3)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000140 except Res.Error:
Jack Jansen64aa1e22001-01-29 15:19:17 +0000141 Res.FSpCreateResFile(self.path, self._creator, 'TEXT', MACFS.smAllScripts)
Jack Jansend13c3852000-06-20 21:59:25 +0000142 resref = Res.FSpOpenResFile(self.path, 3)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000143 try:
144 data = Res.Resource(marshal.dumps(self.settings))
145 Res.UseResFile(resref)
146 try:
147 temp = Res.Get1Resource('PyWS', 128)
148 temp.RemoveResource()
149 except Res.Error:
150 pass
151 data.AddResource('PyWS', 128, "window settings")
152 finally:
153 Res.UpdateResFile(resref)
154 Res.CloseResFile(resref)
155
156 def getsettings(self):
157 self.settings = {}
158 self.settings["windowbounds"] = self.getbounds()
159 self.settings["selection"] = self.getselection()
160 self.settings["fontsettings"] = self.editgroup.editor.getfontsettings()
161 self.settings["tabsize"] = self.editgroup.editor.gettabsettings()
162 self.settings["run_as_main"] = self.run_as_main
Just van Rossum0f2fd162000-10-20 06:36:30 +0000163 self.settings["run_with_interpreter"] = self.run_with_interpreter
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000164
165 def get(self):
166 return self.editgroup.editor.get()
167
168 def getselection(self):
169 return self.editgroup.editor.ted.WEGetSelection()
170
171 def setselection(self, selstart, selend):
172 self.editgroup.editor.setselection(selstart, selend)
173
174 def getfilename(self):
175 if self.path:
176 return self.path
177 return '<%s>' % self.title
178
179 def setupwidgets(self, text):
Just van Rossumf376ef02001-11-18 14:12:43 +0000180 topbarheight = 24
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000181 popfieldwidth = 80
182 self.lastlineno = None
183
184 # make an editor
185 self.editgroup = W.Group((0, topbarheight + 1, 0, 0))
186 editor = W.PyEditor((0, 0, -15,-15), text,
187 fontsettings = self.fontsettings,
188 tabsettings = self.tabsettings,
189 file = self.getfilename())
190
191 # make the widgets
192 self.popfield = ClassFinder((popfieldwidth - 17, -15, 16, 16), [], self.popselectline)
193 self.linefield = W.EditText((-1, -15, popfieldwidth - 15, 16), inset = (6, 1))
194 self.editgroup._barx = W.Scrollbar((popfieldwidth - 2, -15, -14, 16), editor.hscroll, max = 32767)
195 self.editgroup._bary = W.Scrollbar((-15, 14, 16, -14), editor.vscroll, max = 32767)
196 self.editgroup.editor = editor # add editor *after* scrollbars
197
198 self.editgroup.optionsmenu = W.PopupMenu((-15, -1, 16, 16), [])
199 self.editgroup.optionsmenu.bind('<click>', self.makeoptionsmenu)
200
201 self.bevelbox = W.BevelBox((0, 0, 0, topbarheight))
202 self.hline = W.HorizontalLine((0, topbarheight, 0, 0))
Just van Rossumf376ef02001-11-18 14:12:43 +0000203 self.infotext = W.TextBox((175, 6, -4, 14), backgroundcolor = (0xe000, 0xe000, 0xe000))
204 self.runbutton = W.BevelButton((6, 4, 80, 16), runButtonLabels[0], self.run)
205 self.runselbutton = W.BevelButton((90, 4, 80, 16), runSelButtonLabels[0], self.runselection)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000206
207 # bind some keys
208 editor.bind("cmdr", self.runbutton.push)
209 editor.bind("enter", self.runselbutton.push)
210 editor.bind("cmdj", self.domenu_gotoline)
211 editor.bind("cmdd", self.domenu_toggledebugger)
212 editor.bind("<idle>", self.updateselection)
213
214 editor.bind("cmde", searchengine.setfindstring)
215 editor.bind("cmdf", searchengine.show)
216 editor.bind("cmdg", searchengine.findnext)
217 editor.bind("cmdshiftr", searchengine.replace)
218 editor.bind("cmdt", searchengine.replacefind)
219
220 self.linefield.bind("return", self.dolinefield)
221 self.linefield.bind("enter", self.dolinefield)
222 self.linefield.bind("tab", self.dolinefield)
223
224 # intercept clicks
225 editor.bind("<click>", self.clickeditor)
226 self.linefield.bind("<click>", self.clicklinefield)
227
228 def makeoptionsmenu(self):
Just van Rossumdc3c6172001-06-19 21:37:33 +0000229 menuitems = [('Font settings\xc9', self.domenu_fontsettings),
230 ("Save options\xc9", self.domenu_options),
Just van Rossum12710051999-02-27 17:18:30 +0000231 '-',
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000232 ('\0' + chr(self.run_as_main) + 'Run as __main__', self.domenu_toggle_run_as_main),
Just van Rossum0f2fd162000-10-20 06:36:30 +0000233 #('\0' + chr(self.run_with_interpreter) + 'Run with Interpreter', self.domenu_toggle_run_with_interpreter),
234 #'-',
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000235 ('Modularize', self.domenu_modularize),
Just van Rossumdc3c6172001-06-19 21:37:33 +0000236 ('Browse namespace\xc9', self.domenu_browsenamespace),
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000237 '-']
238 if self.profiling:
239 menuitems = menuitems + [('Disable profiler', self.domenu_toggleprofiler)]
240 else:
241 menuitems = menuitems + [('Enable profiler', self.domenu_toggleprofiler)]
242 if self.editgroup.editor._debugger:
243 menuitems = menuitems + [('Disable debugger', self.domenu_toggledebugger),
244 ('Clear breakpoints', self.domenu_clearbreakpoints),
Just van Rossumdc3c6172001-06-19 21:37:33 +0000245 ('Edit breakpoints\xc9', self.domenu_editbreakpoints)]
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000246 else:
247 menuitems = menuitems + [('Enable debugger', self.domenu_toggledebugger)]
248 self.editgroup.optionsmenu.set(menuitems)
249
250 def domenu_toggle_run_as_main(self):
251 self.run_as_main = not self.run_as_main
Just van Rossum0f2fd162000-10-20 06:36:30 +0000252 self.run_with_interpreter = 0
Just van Rossumf7f93882001-11-02 19:24:41 +0000253 self.editgroup.editor.selectionchanged()
Just van Rossum0f2fd162000-10-20 06:36:30 +0000254
255 def domenu_toggle_run_with_interpreter(self):
256 self.run_with_interpreter = not self.run_with_interpreter
257 self.run_as_main = 0
Just van Rossumf7f93882001-11-02 19:24:41 +0000258 self.editgroup.editor.selectionchanged()
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000259
260 def showbreakpoints(self, onoff):
261 self.editgroup.editor.showbreakpoints(onoff)
262 self.debugging = onoff
263
264 def domenu_clearbreakpoints(self, *args):
265 self.editgroup.editor.clearbreakpoints()
266
267 def domenu_editbreakpoints(self, *args):
268 self.editgroup.editor.editbreakpoints()
269
270 def domenu_toggledebugger(self, *args):
271 if not self.debugging:
272 W.SetCursor('watch')
273 self.debugging = not self.debugging
274 self.editgroup.editor.togglebreakpoints()
275
276 def domenu_toggleprofiler(self, *args):
277 self.profiling = not self.profiling
278
279 def domenu_browsenamespace(self, *args):
280 import PyBrowser, W
281 W.SetCursor('watch')
282 globals, file, modname = self.getenvironment()
283 if not modname:
284 modname = self.title
285 PyBrowser.Browser(globals, "Object browser: " + modname)
286
287 def domenu_modularize(self, *args):
288 modname = _filename_as_modname(self.title)
289 if not modname:
Just van Rossumdc3c6172001-06-19 21:37:33 +0000290 raise W.AlertError, "Can't modularize \"%s\"" % self.title
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000291 run_as_main = self.run_as_main
292 self.run_as_main = 0
293 self.run()
294 self.run_as_main = run_as_main
295 if self.path:
296 file = self.path
297 else:
298 file = self.title
299
300 if self.globals and not sys.modules.has_key(modname):
301 module = imp.new_module(modname)
302 for attr in self.globals.keys():
303 setattr(module,attr,self.globals[attr])
304 sys.modules[modname] = module
305 self.globals = {}
306
307 def domenu_fontsettings(self, *args):
308 import FontSettings
309 fontsettings = self.editgroup.editor.getfontsettings()
310 tabsettings = self.editgroup.editor.gettabsettings()
311 settings = FontSettings.FontDialog(fontsettings, tabsettings)
312 if settings:
313 fontsettings, tabsettings = settings
314 self.editgroup.editor.setfontsettings(fontsettings)
315 self.editgroup.editor.settabsettings(tabsettings)
316
Just van Rossum12710051999-02-27 17:18:30 +0000317 def domenu_options(self, *args):
Just van Rossumca3d3072002-03-29 21:48:42 +0000318 rv = SaveOptions(self._creator, self._eoln)
319 if rv:
Just van Rossumf7f93882001-11-02 19:24:41 +0000320 self.editgroup.editor.selectionchanged() # ouch...
Just van Rossumca3d3072002-03-29 21:48:42 +0000321 self._creator, self._eoln = rv
Just van Rossum12710051999-02-27 17:18:30 +0000322
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000323 def clicklinefield(self):
324 if self._currentwidget <> self.linefield:
325 self.linefield.select(1)
326 self.linefield.selectall()
327 return 1
328
329 def clickeditor(self):
330 if self._currentwidget <> self.editgroup.editor:
331 self.dolinefield()
332 return 1
333
334 def updateselection(self, force = 0):
335 sel = min(self.editgroup.editor.getselection())
336 lineno = self.editgroup.editor.offsettoline(sel)
337 if lineno <> self.lastlineno or force:
338 self.lastlineno = lineno
339 self.linefield.set(str(lineno + 1))
340 self.linefield.selview()
341
342 def dolinefield(self):
343 try:
344 lineno = string.atoi(self.linefield.get()) - 1
345 if lineno <> self.lastlineno:
346 self.editgroup.editor.selectline(lineno)
347 self.updateselection(1)
348 except:
349 self.updateselection(1)
350 self.editgroup.editor.select(1)
351
352 def setinfotext(self):
353 if not hasattr(self, 'infotext'):
354 return
355 if self.path:
356 self.infotext.set(self.path)
357 else:
358 self.infotext.set("")
359
360 def close(self):
361 if self.editgroup.editor.changed:
362 import EasyDialogs
Jack Jansen5a6fdcd2001-08-25 12:15:04 +0000363 from Carbon import Qd
Just van Rossum25ddc632001-07-05 07:06:26 +0000364 Qd.InitCursor()
365 save = EasyDialogs.AskYesNoCancel('Save window "%s" before closing?' % self.title,
366 default=1, no="Don\xd5t save")
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000367 if save > 0:
368 if self.domenu_save():
369 return 1
370 elif save < 0:
371 return 1
Just van Rossum25ddc632001-07-05 07:06:26 +0000372 self.globals = None
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000373 W.Window.close(self)
374
375 def domenu_close(self, *args):
376 return self.close()
377
378 def domenu_save(self, *args):
379 if not self.path:
380 # Will call us recursively
381 return self.domenu_save_as()
382 data = self.editgroup.editor.get()
Jack Jansen9a389472002-03-29 21:26:04 +0000383 if self._eoln != '\r':
384 data = string.replace(data, '\r', self._eoln)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000385 fp = open(self.path, 'wb') # open file in binary mode, data has '\r' line-endings
386 fp.write(data)
387 fp.close()
388 fss = macfs.FSSpec(self.path)
389 fss.SetCreatorType(self._creator, 'TEXT')
390 self.getsettings()
391 self.writewindowsettings()
392 self.editgroup.editor.changed = 0
393 self.editgroup.editor.selchanged = 0
394 import linecache
395 if linecache.cache.has_key(self.path):
396 del linecache.cache[self.path]
397 import macostools
398 macostools.touched(self.path)
399
400 def can_save(self, menuitem):
401 return self.editgroup.editor.changed or self.editgroup.editor.selchanged
402
403 def domenu_save_as(self, *args):
404 fss, ok = macfs.StandardPutFile('Save as:', self.title)
405 if not ok:
406 return 1
407 self.showbreakpoints(0)
408 self.path = fss.as_pathname()
409 self.setinfotext()
410 self.title = os.path.split(self.path)[-1]
411 self.wid.SetWTitle(self.title)
412 self.domenu_save()
413 self.editgroup.editor.setfile(self.getfilename())
414 app = W.getapplication()
415 app.makeopenwindowsmenu()
416 if hasattr(app, 'makescriptsmenu'):
417 app = W.getapplication()
418 fss, fss_changed = app.scriptsfolder.Resolve()
419 path = fss.as_pathname()
420 if path == self.path[:len(path)]:
421 W.getapplication().makescriptsmenu()
422
423 def domenu_save_as_applet(self, *args):
Just van Rossumdc3c6172001-06-19 21:37:33 +0000424 import buildtools
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000425
426 buildtools.DEBUG = 0 # ouch.
427
428 if self.title[-3:] == ".py":
429 destname = self.title[:-3]
430 else:
431 destname = self.title + ".applet"
432 fss, ok = macfs.StandardPutFile('Save as Applet:', destname)
433 if not ok:
434 return 1
435 W.SetCursor("watch")
436 destname = fss.as_pathname()
437 if self.path:
438 filename = self.path
439 if filename[-3:] == ".py":
440 rsrcname = filename[:-3] + '.rsrc'
441 else:
442 rsrcname = filename + '.rsrc'
443 else:
444 filename = self.title
445 rsrcname = ""
446
447 pytext = self.editgroup.editor.get()
448 pytext = string.split(pytext, '\r')
449 pytext = string.join(pytext, '\n') + '\n'
450 try:
451 code = compile(pytext, filename, "exec")
452 except (SyntaxError, EOFError):
453 raise buildtools.BuildError, "Syntax error in script %s" % `filename`
454
455 # Try removing the output file
456 try:
457 os.remove(destname)
458 except os.error:
459 pass
460 template = buildtools.findtemplate()
461 buildtools.process_common(template, None, code, rsrcname, destname, 0, 1)
462
463 def domenu_gotoline(self, *args):
464 self.linefield.selectall()
465 self.linefield.select(1)
466 self.linefield.selectall()
467
468 def domenu_selectline(self, *args):
469 self.editgroup.editor.expandselection()
470
471 def domenu_find(self, *args):
472 searchengine.show()
473
474 def domenu_entersearchstring(self, *args):
475 searchengine.setfindstring()
476
477 def domenu_replace(self, *args):
478 searchengine.replace()
479
480 def domenu_findnext(self, *args):
481 searchengine.findnext()
482
483 def domenu_replacefind(self, *args):
484 searchengine.replacefind()
485
486 def domenu_run(self, *args):
487 self.runbutton.push()
488
489 def domenu_runselection(self, *args):
490 self.runselbutton.push()
491
492 def run(self):
Just van Rossum73efed22000-04-09 19:45:22 +0000493 if self._threadstate == (0, 0):
494 self._run()
495 else:
Just van Rossum0f2fd162000-10-20 06:36:30 +0000496 lock = Wthreading.Lock()
497 lock.acquire()
498 self._thread.postException(KeyboardInterrupt)
499 if self._thread.isBlocked():
Just van Rossum73efed22000-04-09 19:45:22 +0000500 self._thread.start()
Just van Rossum0f2fd162000-10-20 06:36:30 +0000501 lock.release()
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000502
503 def _run(self):
Just van Rossum0f2fd162000-10-20 06:36:30 +0000504 if self.run_with_interpreter:
505 if self.editgroup.editor.changed:
506 import EasyDialogs
507 import Qd; Qd.InitCursor()
Just van Rossumdc3c6172001-06-19 21:37:33 +0000508 save = EasyDialogs.AskYesNoCancel('Save "%s" before running?' % self.title, 1)
Just van Rossum0f2fd162000-10-20 06:36:30 +0000509 if save > 0:
510 if self.domenu_save():
511 return
512 elif save < 0:
513 return
514 if not self.path:
515 raise W.AlertError, "Can't run unsaved file"
516 self._run_with_interpreter()
517 else:
518 pytext = self.editgroup.editor.get()
519 globals, file, modname = self.getenvironment()
520 self.execstring(pytext, globals, globals, file, modname)
521
522 def _run_with_interpreter(self):
523 interp_path = os.path.join(sys.exec_prefix, "PythonInterpreter")
524 if not os.path.exists(interp_path):
525 raise W.AlertError, "Can't find interpreter"
526 import findertools
527 XXX
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000528
529 def runselection(self):
Just van Rossum73efed22000-04-09 19:45:22 +0000530 if self._threadstate == (0, 0):
531 self._runselection()
532 elif self._threadstate == (1, 1):
Just van Rossum0f2fd162000-10-20 06:36:30 +0000533 self._thread.block()
Just van Rossum73efed22000-04-09 19:45:22 +0000534 self.setthreadstate((1, 2))
535 elif self._threadstate == (1, 2):
536 self._thread.start()
537 self.setthreadstate((1, 1))
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000538
539 def _runselection(self):
Just van Rossum0f2fd162000-10-20 06:36:30 +0000540 if self.run_with_interpreter:
541 raise W.AlertError, "Can't run selection with Interpreter"
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000542 globals, file, modname = self.getenvironment()
543 locals = globals
544 # select whole lines
545 self.editgroup.editor.expandselection()
546
547 # get lineno of first selected line
548 selstart, selend = self.editgroup.editor.getselection()
549 selstart, selend = min(selstart, selend), max(selstart, selend)
550 selfirstline = self.editgroup.editor.offsettoline(selstart)
551 alltext = self.editgroup.editor.get()
552 pytext = alltext[selstart:selend]
553 lines = string.split(pytext, '\r')
554 indent = getminindent(lines)
555 if indent == 1:
556 classname = ''
557 alllines = string.split(alltext, '\r')
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000558 for i in range(selfirstline - 1, -1, -1):
559 line = alllines[i]
560 if line[:6] == 'class ':
561 classname = string.split(string.strip(line[6:]))[0]
562 classend = identifieRE_match(classname)
563 if classend < 1:
Just van Rossumdc3c6172001-06-19 21:37:33 +0000564 raise W.AlertError, "Can't find a class."
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000565 classname = classname[:classend]
566 break
567 elif line and line[0] not in '\t#':
Just van Rossumdc3c6172001-06-19 21:37:33 +0000568 raise W.AlertError, "Can't find a class."
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000569 else:
Just van Rossumdc3c6172001-06-19 21:37:33 +0000570 raise W.AlertError, "Can't find a class."
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000571 if globals.has_key(classname):
Just van Rossum25ddc632001-07-05 07:06:26 +0000572 klass = globals[classname]
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000573 else:
Just van Rossumdc3c6172001-06-19 21:37:33 +0000574 raise W.AlertError, "Can't find class \"%s\"." % classname
Just van Rossum25ddc632001-07-05 07:06:26 +0000575 # add class def
576 pytext = ("class %s:\n" % classname) + pytext
577 selfirstline = selfirstline - 1
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000578 elif indent > 0:
Just van Rossumdc3c6172001-06-19 21:37:33 +0000579 raise W.AlertError, "Can't run indented code."
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000580
581 # add "newlines" to fool compile/exec:
582 # now a traceback will give the right line number
583 pytext = selfirstline * '\r' + pytext
584 self.execstring(pytext, globals, locals, file, modname)
Just van Rossum25ddc632001-07-05 07:06:26 +0000585 if indent == 1 and globals[classname] is not klass:
586 # update the class in place
587 klass.__dict__.update(globals[classname].__dict__)
588 globals[classname] = klass
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000589
Just van Rossum73efed22000-04-09 19:45:22 +0000590 def setthreadstate(self, state):
591 oldstate = self._threadstate
592 if oldstate[0] <> state[0]:
593 self.runbutton.settitle(runButtonLabels[state[0]])
594 if oldstate[1] <> state[1]:
595 self.runselbutton.settitle(runSelButtonLabels[state[1]])
596 self._threadstate = state
597
598 def _exec_threadwrapper(self, *args, **kwargs):
599 apply(execstring, args, kwargs)
600 self.setthreadstate((0, 0))
601 self._thread = None
602
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000603 def execstring(self, pytext, globals, locals, file, modname):
604 tracebackwindow.hide()
605 # update windows
606 W.getapplication().refreshwindows()
607 if self.run_as_main:
608 modname = "__main__"
609 if self.path:
610 dir = os.path.dirname(self.path)
611 savedir = os.getcwd()
612 os.chdir(dir)
Just van Rossuma61f4ac1999-02-01 16:34:08 +0000613 sys.path.insert(0, dir)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000614 else:
615 cwdindex = None
616 try:
Just van Rossum0f2fd162000-10-20 06:36:30 +0000617 if haveThreading:
618 self._thread = Wthreading.Thread(os.path.basename(file),
Just van Rossum73efed22000-04-09 19:45:22 +0000619 self._exec_threadwrapper, pytext, globals, locals, file, self.debugging,
620 modname, self.profiling)
621 self.setthreadstate((1, 1))
622 self._thread.start()
623 else:
624 execstring(pytext, globals, locals, file, self.debugging,
625 modname, self.profiling)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000626 finally:
627 if self.path:
628 os.chdir(savedir)
Just van Rossuma61f4ac1999-02-01 16:34:08 +0000629 del sys.path[0]
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000630
631 def getenvironment(self):
632 if self.path:
633 file = self.path
634 dir = os.path.dirname(file)
635 # check if we're part of a package
636 modname = ""
637 while os.path.exists(os.path.join(dir, "__init__.py")):
638 dir, dirname = os.path.split(dir)
Just van Rossum2aaeb521999-02-05 21:58:25 +0000639 modname = dirname + '.' + modname
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000640 subname = _filename_as_modname(self.title)
Just van Rossumf7f93882001-11-02 19:24:41 +0000641 if subname is None:
642 return self.globals, file, None
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000643 if modname:
644 if subname == "__init__":
Just van Rossum2aaeb521999-02-05 21:58:25 +0000645 # strip trailing period
646 modname = modname[:-1]
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000647 else:
Just van Rossum2aaeb521999-02-05 21:58:25 +0000648 modname = modname + subname
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000649 else:
650 modname = subname
651 if sys.modules.has_key(modname):
652 globals = sys.modules[modname].__dict__
653 self.globals = {}
654 else:
655 globals = self.globals
Just van Rossum73efed22000-04-09 19:45:22 +0000656 modname = subname
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000657 else:
658 file = '<%s>' % self.title
659 globals = self.globals
660 modname = file
661 return globals, file, modname
662
663 def write(self, stuff):
664 """for use as stdout"""
665 self._buf = self._buf + stuff
666 if '\n' in self._buf:
667 self.flush()
668
669 def flush(self):
670 stuff = string.split(self._buf, '\n')
671 stuff = string.join(stuff, '\r')
672 end = self.editgroup.editor.ted.WEGetTextLength()
673 self.editgroup.editor.ted.WESetSelection(end, end)
674 self.editgroup.editor.ted.WEInsert(stuff, None, None)
675 self.editgroup.editor.updatescrollbars()
676 self._buf = ""
677 # ? optional:
678 #self.wid.SelectWindow()
679
680 def getclasslist(self):
681 from string import find, strip
Just van Rossum24073ea1999-12-23 15:46:57 +0000682 methodRE = re.compile(r"\r[ \t]+def ")
683 findMethod = methodRE.search
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000684 editor = self.editgroup.editor
685 text = editor.get()
686 list = []
687 append = list.append
688 functag = "func"
689 classtag = "class"
690 methodtag = "method"
691 pos = -1
692 if text[:4] == 'def ':
693 append((pos + 4, functag))
694 pos = 4
695 while 1:
696 pos = find(text, '\rdef ', pos + 1)
697 if pos < 0:
698 break
699 append((pos + 5, functag))
700 pos = -1
701 if text[:6] == 'class ':
702 append((pos + 6, classtag))
703 pos = 6
704 while 1:
705 pos = find(text, '\rclass ', pos + 1)
706 if pos < 0:
707 break
708 append((pos + 7, classtag))
709 pos = 0
710 while 1:
Just van Rossum24073ea1999-12-23 15:46:57 +0000711 m = findMethod(text, pos + 1)
712 if m is None:
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000713 break
Just van Rossum24073ea1999-12-23 15:46:57 +0000714 pos = m.regs[0][0]
715 #pos = find(text, '\r\tdef ', pos + 1)
716 append((m.regs[0][1], methodtag))
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000717 list.sort()
718 classlist = []
719 methodlistappend = None
720 offsetToLine = editor.ted.WEOffsetToLine
721 getLineRange = editor.ted.WEGetLineRange
722 append = classlist.append
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000723 for pos, tag in list:
724 lineno = offsetToLine(pos)
725 lineStart, lineEnd = getLineRange(lineno)
726 line = strip(text[pos:lineEnd])
727 line = line[:identifieRE_match(line)]
728 if tag is functag:
729 append(("def " + line, lineno + 1))
730 methodlistappend = None
731 elif tag is classtag:
732 append(["class " + line])
733 methodlistappend = classlist[-1].append
734 elif methodlistappend and tag is methodtag:
735 methodlistappend(("def " + line, lineno + 1))
736 return classlist
737
738 def popselectline(self, lineno):
739 self.editgroup.editor.selectline(lineno - 1)
740
741 def selectline(self, lineno, charoffset = 0):
742 self.editgroup.editor.selectline(lineno - 1, charoffset)
743
Just van Rossum12710051999-02-27 17:18:30 +0000744class _saveoptions:
745
Jack Jansen9a389472002-03-29 21:26:04 +0000746 def __init__(self, creator, eoln):
Just van Rossum12710051999-02-27 17:18:30 +0000747 self.rv = None
Jack Jansen9a389472002-03-29 21:26:04 +0000748 self.eoln = eoln
749 self.w = w = W.ModalDialog((260, 160), 'Save options')
Just van Rossum12710051999-02-27 17:18:30 +0000750 radiobuttons = []
751 w.label = W.TextBox((8, 8, 80, 18), "File creator:")
Just van Rossum3af507d1999-04-22 22:23:46 +0000752 w.ide_radio = W.RadioButton((8, 22, 160, 18), "This application", radiobuttons, self.ide_hit)
Jack Jansen9a389472002-03-29 21:26:04 +0000753 w.interp_radio = W.RadioButton((8, 42, 160, 18), "MacPython Interpreter", radiobuttons, self.interp_hit)
754 w.interpx_radio = W.RadioButton((8, 62, 160, 18), "OSX PythonW Interpreter", radiobuttons, self.interpx_hit)
755 w.other_radio = W.RadioButton((8, 82, 50, 18), "Other:", radiobuttons)
756 w.other_creator = W.EditText((62, 82, 40, 20), creator, self.otherselect)
757 w.none_radio = W.RadioButton((8, 102, 160, 18), "None", radiobuttons, self.none_hit)
Just van Rossum12710051999-02-27 17:18:30 +0000758 w.cancelbutton = W.Button((-180, -30, 80, 16), "Cancel", self.cancelbuttonhit)
759 w.okbutton = W.Button((-90, -30, 80, 16), "Done", self.okbuttonhit)
760 w.setdefaultbutton(w.okbutton)
761 if creator == 'Pyth':
762 w.interp_radio.set(1)
Just van Rossum3af507d1999-04-22 22:23:46 +0000763 elif creator == W._signature:
Just van Rossum12710051999-02-27 17:18:30 +0000764 w.ide_radio.set(1)
Jack Jansen9a389472002-03-29 21:26:04 +0000765 elif creator == 'PytX':
766 w.interpx_radio.set(1)
767 elif creator == '\0\0\0\0':
768 w.none_radio.set(1)
Just van Rossum12710051999-02-27 17:18:30 +0000769 else:
770 w.other_radio.set(1)
Jack Jansen9a389472002-03-29 21:26:04 +0000771
772 w.eolnlabel = W.TextBox((168, 8, 80, 18), "Newline style:")
773 radiobuttons = []
774 w.unix_radio = W.RadioButton((168, 22, 80, 18), "Unix", radiobuttons, self.unix_hit)
775 w.mac_radio = W.RadioButton((168, 42, 80, 18), "Macintosh", radiobuttons, self.mac_hit)
776 w.win_radio = W.RadioButton((168, 62, 80, 18), "Windows", radiobuttons, self.win_hit)
777 if self.eoln == '\n':
778 w.unix_radio.set(1)
779 elif self.eoln == '\r\n':
780 w.win_radio.set(1)
781 else:
782 w.mac_radio.set(1)
783
Just van Rossum12710051999-02-27 17:18:30 +0000784 w.bind("cmd.", w.cancelbutton.push)
785 w.open()
786
787 def ide_hit(self):
Just van Rossum3af507d1999-04-22 22:23:46 +0000788 self.w.other_creator.set(W._signature)
Just van Rossum12710051999-02-27 17:18:30 +0000789
790 def interp_hit(self):
791 self.w.other_creator.set("Pyth")
792
Jack Jansen9a389472002-03-29 21:26:04 +0000793 def interpx_hit(self):
794 self.w.other_creator.set("PytX")
795
796 def none_hit(self):
797 self.w.other_creator.set("\0\0\0\0")
798
Just van Rossum12710051999-02-27 17:18:30 +0000799 def otherselect(self, *args):
800 sel_from, sel_to = self.w.other_creator.getselection()
801 creator = self.w.other_creator.get()[:4]
802 creator = creator + " " * (4 - len(creator))
803 self.w.other_creator.set(creator)
804 self.w.other_creator.setselection(sel_from, sel_to)
805 self.w.other_radio.set(1)
806
Jack Jansen9a389472002-03-29 21:26:04 +0000807 def mac_hit(self):
808 self.eoln = '\r'
809
810 def unix_hit(self):
811 self.eoln = '\n'
812
813 def win_hit(self):
814 self.eoln = '\r\n'
815
Just van Rossum12710051999-02-27 17:18:30 +0000816 def cancelbuttonhit(self):
817 self.w.close()
818
819 def okbuttonhit(self):
Jack Jansen9a389472002-03-29 21:26:04 +0000820 self.rv = (self.w.other_creator.get()[:4], self.eoln)
Just van Rossum12710051999-02-27 17:18:30 +0000821 self.w.close()
822
823
Jack Jansen9a389472002-03-29 21:26:04 +0000824def SaveOptions(creator, eoln):
825 s = _saveoptions(creator, eoln)
Just van Rossum12710051999-02-27 17:18:30 +0000826 return s.rv
827
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000828
829def _escape(where, what) :
830 return string.join(string.split(where, what), '\\' + what)
831
832def _makewholewordpattern(word):
833 # first, escape special regex chars
Just van Rossum3eec7622001-07-10 19:25:40 +0000834 for esc in "\\[]()|.*^+$?":
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000835 word = _escape(word, esc)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000836 notwordcharspat = '[^' + _wordchars + ']'
Jack Jansen9ad27522001-02-21 13:54:31 +0000837 pattern = '(' + word + ')'
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000838 if word[0] in _wordchars:
839 pattern = notwordcharspat + pattern
840 if word[-1] in _wordchars:
841 pattern = pattern + notwordcharspat
Jack Jansen9ad27522001-02-21 13:54:31 +0000842 return re.compile(pattern)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000843
Just van Rossumf376ef02001-11-18 14:12:43 +0000844
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000845class SearchEngine:
846
847 def __init__(self):
848 self.visible = 0
849 self.w = None
850 self.parms = { "find": "",
851 "replace": "",
852 "wrap": 1,
853 "casesens": 1,
854 "wholeword": 1
855 }
856 import MacPrefs
857 prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath)
858 if prefs.searchengine:
859 self.parms["casesens"] = prefs.searchengine.casesens
860 self.parms["wrap"] = prefs.searchengine.wrap
861 self.parms["wholeword"] = prefs.searchengine.wholeword
862
863 def show(self):
864 self.visible = 1
865 if self.w:
866 self.w.wid.ShowWindow()
867 self.w.wid.SelectWindow()
868 self.w.find.edit.select(1)
869 self.w.find.edit.selectall()
870 return
871 self.w = W.Dialog((420, 150), "Find")
872
873 self.w.find = TitledEditText((10, 4, 300, 36), "Search for:")
874 self.w.replace = TitledEditText((10, 100, 300, 36), "Replace with:")
875
876 self.w.boxes = W.Group((10, 50, 300, 40))
877 self.w.boxes.casesens = W.CheckBox((0, 0, 100, 16), "Case sensitive")
878 self.w.boxes.wholeword = W.CheckBox((0, 20, 100, 16), "Whole word")
879 self.w.boxes.wrap = W.CheckBox((110, 0, 100, 16), "Wrap around")
880
881 self.buttons = [ ("Find", "cmdf", self.find),
882 ("Replace", "cmdr", self.replace),
883 ("Replace all", None, self.replaceall),
Just van Rossumdc3c6172001-06-19 21:37:33 +0000884 ("Don't find", "cmdd", self.dont),
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000885 ("Cancel", "cmd.", self.cancel)
886 ]
887 for i in range(len(self.buttons)):
888 bounds = -90, 22 + i * 24, 80, 16
889 title, shortcut, callback = self.buttons[i]
890 self.w[title] = W.Button(bounds, title, callback)
891 if shortcut:
892 self.w.bind(shortcut, self.w[title].push)
Just van Rossumdc3c6172001-06-19 21:37:33 +0000893 self.w.setdefaultbutton(self.w["Don't find"])
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000894 self.w.find.edit.bind("<key>", self.key)
895 self.w.bind("<activate>", self.activate)
896 self.w.bind("<close>", self.close)
897 self.w.open()
898 self.setparms()
899 self.w.find.edit.select(1)
900 self.w.find.edit.selectall()
901 self.checkbuttons()
902
903 def close(self):
904 self.hide()
905 return -1
906
907 def key(self, char, modifiers):
908 self.w.find.edit.key(char, modifiers)
909 self.checkbuttons()
910 return 1
911
912 def activate(self, onoff):
913 if onoff:
914 self.checkbuttons()
915
916 def checkbuttons(self):
917 editor = findeditor(self)
918 if editor:
919 if self.w.find.get():
920 for title, cmd, call in self.buttons[:-2]:
921 self.w[title].enable(1)
922 self.w.setdefaultbutton(self.w["Find"])
923 else:
924 for title, cmd, call in self.buttons[:-2]:
925 self.w[title].enable(0)
Just van Rossumdc3c6172001-06-19 21:37:33 +0000926 self.w.setdefaultbutton(self.w["Don't find"])
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000927 else:
928 for title, cmd, call in self.buttons[:-2]:
929 self.w[title].enable(0)
Just van Rossumdc3c6172001-06-19 21:37:33 +0000930 self.w.setdefaultbutton(self.w["Don't find"])
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000931
932 def find(self):
933 self.getparmsfromwindow()
934 if self.findnext():
935 self.hide()
936
937 def replace(self):
938 editor = findeditor(self)
939 if not editor:
940 return
941 if self.visible:
942 self.getparmsfromwindow()
943 text = editor.getselectedtext()
944 find = self.parms["find"]
945 if not self.parms["casesens"]:
946 find = string.lower(find)
947 text = string.lower(text)
948 if text == find:
949 self.hide()
950 editor.insert(self.parms["replace"])
951
952 def replaceall(self):
953 editor = findeditor(self)
954 if not editor:
955 return
956 if self.visible:
957 self.getparmsfromwindow()
958 W.SetCursor("watch")
959 find = self.parms["find"]
960 if not find:
961 return
962 findlen = len(find)
963 replace = self.parms["replace"]
964 replacelen = len(replace)
965 Text = editor.get()
966 if not self.parms["casesens"]:
967 find = string.lower(find)
968 text = string.lower(Text)
969 else:
970 text = Text
971 newtext = ""
972 pos = 0
973 counter = 0
974 while 1:
975 if self.parms["wholeword"]:
976 wholewordRE = _makewholewordpattern(find)
Jack Jansen9ad27522001-02-21 13:54:31 +0000977 match = wholewordRE.search(text, pos)
978 if match:
979 pos = match.start(1)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000980 else:
981 pos = -1
982 else:
983 pos = string.find(text, find, pos)
984 if pos < 0:
985 break
986 counter = counter + 1
987 text = text[:pos] + replace + text[pos + findlen:]
988 Text = Text[:pos] + replace + Text[pos + findlen:]
989 pos = pos + replacelen
990 W.SetCursor("arrow")
991 if counter:
992 self.hide()
993 import EasyDialogs
Jack Jansen5a6fdcd2001-08-25 12:15:04 +0000994 from Carbon import Res
Just van Rossumf7f93882001-11-02 19:24:41 +0000995 editor.textchanged()
996 editor.selectionchanged()
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000997 editor.ted.WEUseText(Res.Resource(Text))
998 editor.ted.WECalText()
999 editor.SetPort()
Jack Jansen73023402001-01-23 14:58:20 +00001000 editor.GetWindow().InvalWindowRect(editor._bounds)
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001001 #editor.ted.WEUpdate(self.w.wid.GetWindowPort().visRgn)
1002 EasyDialogs.Message("Replaced %d occurrences" % counter)
1003
1004 def dont(self):
1005 self.getparmsfromwindow()
1006 self.hide()
1007
1008 def replacefind(self):
1009 self.replace()
1010 self.findnext()
1011
1012 def setfindstring(self):
1013 editor = findeditor(self)
1014 if not editor:
1015 return
1016 find = editor.getselectedtext()
1017 if not find:
1018 return
1019 self.parms["find"] = find
1020 if self.w:
1021 self.w.find.edit.set(self.parms["find"])
1022 self.w.find.edit.selectall()
1023
1024 def findnext(self):
1025 editor = findeditor(self)
1026 if not editor:
1027 return
1028 find = self.parms["find"]
1029 if not find:
1030 return
1031 text = editor.get()
1032 if not self.parms["casesens"]:
1033 find = string.lower(find)
1034 text = string.lower(text)
1035 selstart, selend = editor.getselection()
1036 selstart, selend = min(selstart, selend), max(selstart, selend)
1037 if self.parms["wholeword"]:
1038 wholewordRE = _makewholewordpattern(find)
Jack Jansen9ad27522001-02-21 13:54:31 +00001039 match = wholewordRE.search(text, selend)
1040 if match:
1041 pos = match.start(1)
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001042 else:
1043 pos = -1
1044 else:
1045 pos = string.find(text, find, selend)
1046 if pos >= 0:
1047 editor.setselection(pos, pos + len(find))
1048 return 1
1049 elif self.parms["wrap"]:
1050 if self.parms["wholeword"]:
Jack Jansen9ad27522001-02-21 13:54:31 +00001051 match = wholewordRE.search(text, 0)
1052 if match:
1053 pos = match.start(1)
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001054 else:
1055 pos = -1
1056 else:
1057 pos = string.find(text, find)
1058 if selstart > pos >= 0:
1059 editor.setselection(pos, pos + len(find))
1060 return 1
1061
1062 def setparms(self):
1063 for key, value in self.parms.items():
1064 try:
1065 self.w[key].set(value)
1066 except KeyError:
1067 self.w.boxes[key].set(value)
1068
1069 def getparmsfromwindow(self):
1070 if not self.w:
1071 return
1072 for key, value in self.parms.items():
1073 try:
1074 value = self.w[key].get()
1075 except KeyError:
1076 value = self.w.boxes[key].get()
1077 self.parms[key] = value
1078
1079 def cancel(self):
1080 self.hide()
1081 self.setparms()
1082
1083 def hide(self):
1084 if self.w:
1085 self.w.wid.HideWindow()
1086 self.visible = 0
1087
1088 def writeprefs(self):
1089 import MacPrefs
1090 self.getparmsfromwindow()
1091 prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath)
1092 prefs.searchengine.casesens = self.parms["casesens"]
1093 prefs.searchengine.wrap = self.parms["wrap"]
1094 prefs.searchengine.wholeword = self.parms["wholeword"]
1095 prefs.save()
1096
1097
1098class TitledEditText(W.Group):
1099
1100 def __init__(self, possize, title, text = ""):
1101 W.Group.__init__(self, possize)
1102 self.title = W.TextBox((0, 0, 0, 16), title)
1103 self.edit = W.EditText((0, 16, 0, 0), text)
1104
1105 def set(self, value):
1106 self.edit.set(value)
1107
1108 def get(self):
1109 return self.edit.get()
1110
1111
1112class ClassFinder(W.PopupWidget):
1113
1114 def click(self, point, modifiers):
1115 W.SetCursor("watch")
1116 self.set(self._parentwindow.getclasslist())
1117 W.PopupWidget.click(self, point, modifiers)
1118
1119
1120def getminindent(lines):
1121 indent = -1
1122 for line in lines:
1123 stripped = string.strip(line)
1124 if not stripped or stripped[0] == '#':
1125 continue
1126 if indent < 0 or line[:indent] <> indent * '\t':
1127 indent = 0
1128 for c in line:
1129 if c <> '\t':
1130 break
1131 indent = indent + 1
1132 return indent
1133
1134
1135def getoptionkey():
1136 return not not ord(Evt.GetKeys()[7]) & 0x04
1137
1138
1139def execstring(pytext, globals, locals, filename="<string>", debugging=0,
1140 modname="__main__", profiling=0):
1141 if debugging:
1142 import PyDebugger, bdb
1143 BdbQuit = bdb.BdbQuit
1144 else:
1145 BdbQuit = 'BdbQuitDummyException'
1146 pytext = string.split(pytext, '\r')
1147 pytext = string.join(pytext, '\n') + '\n'
1148 W.SetCursor("watch")
1149 globals['__name__'] = modname
1150 globals['__file__'] = filename
1151 sys.argv = [filename]
1152 try:
1153 code = compile(pytext, filename, "exec")
1154 except:
1155 # XXXX BAAAADDD.... We let tracebackwindow decide to treat SyntaxError
1156 # special. That's wrong because THIS case is special (could be literal
1157 # overflow!) and SyntaxError could mean we need a traceback (syntax error
1158 # in imported module!!!
1159 tracebackwindow.traceback(1, filename)
1160 return
1161 try:
1162 if debugging:
Just van Rossum0f2fd162000-10-20 06:36:30 +00001163 if haveThreading:
1164 lock = Wthreading.Lock()
1165 lock.acquire()
Just van Rossum73efed22000-04-09 19:45:22 +00001166 PyDebugger.startfromhere()
Just van Rossum0f2fd162000-10-20 06:36:30 +00001167 lock.release()
Just van Rossum73efed22000-04-09 19:45:22 +00001168 else:
1169 PyDebugger.startfromhere()
Just van Rossum0f2fd162000-10-20 06:36:30 +00001170 elif not haveThreading:
Jack Jansen815d2bf2002-01-21 23:00:52 +00001171 if hasattr(MacOS, 'EnableAppswitch'):
1172 MacOS.EnableAppswitch(0)
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001173 try:
1174 if profiling:
1175 import profile, ProfileBrowser
1176 p = profile.Profile()
1177 p.set_cmd(filename)
1178 try:
1179 p.runctx(code, globals, locals)
1180 finally:
1181 import pstats
1182
1183 stats = pstats.Stats(p)
1184 ProfileBrowser.ProfileBrowser(stats)
1185 else:
1186 exec code in globals, locals
1187 finally:
Just van Rossum0f2fd162000-10-20 06:36:30 +00001188 if not haveThreading:
Jack Jansen815d2bf2002-01-21 23:00:52 +00001189 if hasattr(MacOS, 'EnableAppswitch'):
1190 MacOS.EnableAppswitch(-1)
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001191 except W.AlertError, detail:
1192 raise W.AlertError, detail
1193 except (KeyboardInterrupt, BdbQuit):
1194 pass
Just van Rossumf7f93882001-11-02 19:24:41 +00001195 except SystemExit, arg:
1196 if arg.code:
1197 sys.stderr.write("Script exited with status code: %s\n" % repr(arg.code))
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001198 except:
Just van Rossum0f2fd162000-10-20 06:36:30 +00001199 if haveThreading:
1200 import continuation
1201 lock = Wthreading.Lock()
1202 lock.acquire()
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001203 if debugging:
1204 sys.settrace(None)
1205 PyDebugger.postmortem(sys.exc_type, sys.exc_value, sys.exc_traceback)
1206 return
1207 else:
1208 tracebackwindow.traceback(1, filename)
Just van Rossum0f2fd162000-10-20 06:36:30 +00001209 if haveThreading:
1210 lock.release()
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001211 if debugging:
1212 sys.settrace(None)
1213 PyDebugger.stop()
1214
1215
Just van Rossum3eec7622001-07-10 19:25:40 +00001216_identifieRE = re.compile(r"[A-Za-z_][A-Za-z_0-9]*")
Jack Jansen9ad27522001-02-21 13:54:31 +00001217
1218def identifieRE_match(str):
1219 match = _identifieRE.match(str)
1220 if not match:
1221 return -1
1222 return match.end()
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001223
1224def _filename_as_modname(fname):
1225 if fname[-3:] == '.py':
1226 modname = fname[:-3]
Jack Jansen9ad27522001-02-21 13:54:31 +00001227 match = _identifieRE.match(modname)
1228 if match and match.start() == 0 and match.end() == len(modname):
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001229 return string.join(string.split(modname, '.'), '_')
1230
1231def findeditor(topwindow, fromtop = 0):
Just van Rossum40144012002-02-04 12:52:44 +00001232 wid = MyFrontWindow()
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001233 if not fromtop:
1234 if topwindow.w and wid == topwindow.w.wid:
1235 wid = topwindow.w.wid.GetNextWindow()
1236 if not wid:
1237 return
1238 app = W.getapplication()
1239 if app._windows.has_key(wid): # KeyError otherwise can happen in RoboFog :-(
1240 window = W.getapplication()._windows[wid]
1241 else:
1242 return
1243 if not isinstance(window, Editor):
1244 return
1245 return window.editgroup.editor
1246
1247
1248class _EditorDefaultSettings:
1249
1250 def __init__(self):
1251 self.template = "%s, %d point"
1252 self.fontsettings, self.tabsettings, self.windowsize = geteditorprefs()
1253 self.w = W.Dialog((328, 120), "Editor default settings")
Just van Rossumdc3c6172001-06-19 21:37:33 +00001254 self.w.setfontbutton = W.Button((8, 8, 80, 16), "Set font\xc9", self.dofont)
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001255 self.w.fonttext = W.TextBox((98, 10, -8, 14), self.template % (self.fontsettings[0], self.fontsettings[2]))
1256
1257 self.w.picksizebutton = W.Button((8, 50, 80, 16), "Front window", self.picksize)
1258 self.w.xsizelabel = W.TextBox((98, 32, 40, 14), "Width:")
1259 self.w.ysizelabel = W.TextBox((148, 32, 40, 14), "Height:")
1260 self.w.xsize = W.EditText((98, 48, 40, 20), `self.windowsize[0]`)
1261 self.w.ysize = W.EditText((148, 48, 40, 20), `self.windowsize[1]`)
1262
1263 self.w.cancelbutton = W.Button((-180, -26, 80, 16), "Cancel", self.cancel)
1264 self.w.okbutton = W.Button((-90, -26, 80, 16), "Done", self.ok)
1265 self.w.setdefaultbutton(self.w.okbutton)
1266 self.w.bind('cmd.', self.w.cancelbutton.push)
1267 self.w.open()
1268
1269 def picksize(self):
1270 app = W.getapplication()
1271 editor = findeditor(self)
1272 if editor is not None:
1273 width, height = editor._parentwindow._bounds[2:]
1274 self.w.xsize.set(`width`)
1275 self.w.ysize.set(`height`)
1276 else:
1277 raise W.AlertError, "No edit window found"
1278
1279 def dofont(self):
1280 import FontSettings
1281 settings = FontSettings.FontDialog(self.fontsettings, self.tabsettings)
1282 if settings:
1283 self.fontsettings, self.tabsettings = settings
1284 sys.exc_traceback = None
1285 self.w.fonttext.set(self.template % (self.fontsettings[0], self.fontsettings[2]))
1286
1287 def close(self):
1288 self.w.close()
1289 del self.w
1290
1291 def cancel(self):
1292 self.close()
1293
1294 def ok(self):
1295 try:
1296 width = string.atoi(self.w.xsize.get())
1297 except:
1298 self.w.xsize.select(1)
1299 self.w.xsize.selectall()
1300 raise W.AlertError, "Bad number for window width"
1301 try:
1302 height = string.atoi(self.w.ysize.get())
1303 except:
1304 self.w.ysize.select(1)
1305 self.w.ysize.selectall()
1306 raise W.AlertError, "Bad number for window height"
1307 self.windowsize = width, height
1308 seteditorprefs(self.fontsettings, self.tabsettings, self.windowsize)
1309 self.close()
1310
1311def geteditorprefs():
1312 import MacPrefs
1313 prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath)
1314 try:
1315 fontsettings = prefs.pyedit.fontsettings
1316 tabsettings = prefs.pyedit.tabsettings
1317 windowsize = prefs.pyedit.windowsize
1318 except:
Just van Rossumf7f93882001-11-02 19:24:41 +00001319 fontsettings = prefs.pyedit.fontsettings = ("Geneva", 0, 10, (0, 0, 0))
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001320 tabsettings = prefs.pyedit.tabsettings = (8, 1)
1321 windowsize = prefs.pyedit.windowsize = (500, 250)
1322 sys.exc_traceback = None
1323 return fontsettings, tabsettings, windowsize
1324
1325def seteditorprefs(fontsettings, tabsettings, windowsize):
1326 import MacPrefs
1327 prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath)
1328 prefs.pyedit.fontsettings = fontsettings
1329 prefs.pyedit.tabsettings = tabsettings
1330 prefs.pyedit.windowsize = windowsize
1331 prefs.save()
1332
1333_defaultSettingsEditor = None
1334
1335def EditorDefaultSettings():
1336 global _defaultSettingsEditor
1337 if _defaultSettingsEditor is None or not hasattr(_defaultSettingsEditor, "w"):
1338 _defaultSettingsEditor = _EditorDefaultSettings()
1339 else:
1340 _defaultSettingsEditor.w.select()
1341
1342def resolvealiases(path):
1343 try:
1344 return macfs.ResolveAliasFile(path)[0].as_pathname()
1345 except (macfs.error, ValueError), (error, str):
1346 if error <> -120:
1347 raise
1348 dir, file = os.path.split(path)
1349 return os.path.join(resolvealiases(dir), file)
1350
1351searchengine = SearchEngine()
1352tracebackwindow = Wtraceback.TraceBack()