blob: 786f0f60d400eaebef9052fe12a57ad3b3aa6569 [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
Jack Jansenff773eb2002-03-31 22:01:33 +0000113 self.run_as_main = self.settings.get("run_as_main", 0)
114 self.run_with_interpreter = self.settings.get("run_with_interpreter", 0)
115 self.run_with_cl_interpreter = self.settings.get("run_with_cl_interpreter", 0)
Just van Rossum73efed22000-04-09 19:45:22 +0000116 self._threadstate = (0, 0)
117 self._thread = None
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000118
119 def readwindowsettings(self):
120 try:
Jack Jansend13c3852000-06-20 21:59:25 +0000121 resref = Res.FSpOpenResFile(self.path, 1)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000122 except Res.Error:
123 return
124 try:
125 Res.UseResFile(resref)
126 data = Res.Get1Resource('PyWS', 128)
127 self.settings = marshal.loads(data.data)
128 except:
129 pass
130 Res.CloseResFile(resref)
131
132 def writewindowsettings(self):
133 try:
Jack Jansend13c3852000-06-20 21:59:25 +0000134 resref = Res.FSpOpenResFile(self.path, 3)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000135 except Res.Error:
Jack Jansen64aa1e22001-01-29 15:19:17 +0000136 Res.FSpCreateResFile(self.path, self._creator, 'TEXT', MACFS.smAllScripts)
Jack Jansend13c3852000-06-20 21:59:25 +0000137 resref = Res.FSpOpenResFile(self.path, 3)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000138 try:
139 data = Res.Resource(marshal.dumps(self.settings))
140 Res.UseResFile(resref)
141 try:
142 temp = Res.Get1Resource('PyWS', 128)
143 temp.RemoveResource()
144 except Res.Error:
145 pass
146 data.AddResource('PyWS', 128, "window settings")
147 finally:
148 Res.UpdateResFile(resref)
149 Res.CloseResFile(resref)
150
151 def getsettings(self):
152 self.settings = {}
153 self.settings["windowbounds"] = self.getbounds()
154 self.settings["selection"] = self.getselection()
155 self.settings["fontsettings"] = self.editgroup.editor.getfontsettings()
156 self.settings["tabsize"] = self.editgroup.editor.gettabsettings()
157 self.settings["run_as_main"] = self.run_as_main
Just van Rossum0f2fd162000-10-20 06:36:30 +0000158 self.settings["run_with_interpreter"] = self.run_with_interpreter
Jack Jansenff773eb2002-03-31 22:01:33 +0000159 self.settings["run_with_cl_interpreter"] = self.run_with_cl_interpreter
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000160
161 def get(self):
162 return self.editgroup.editor.get()
163
164 def getselection(self):
165 return self.editgroup.editor.ted.WEGetSelection()
166
167 def setselection(self, selstart, selend):
168 self.editgroup.editor.setselection(selstart, selend)
169
170 def getfilename(self):
171 if self.path:
172 return self.path
173 return '<%s>' % self.title
174
175 def setupwidgets(self, text):
Just van Rossumf376ef02001-11-18 14:12:43 +0000176 topbarheight = 24
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000177 popfieldwidth = 80
178 self.lastlineno = None
179
180 # make an editor
181 self.editgroup = W.Group((0, topbarheight + 1, 0, 0))
182 editor = W.PyEditor((0, 0, -15,-15), text,
183 fontsettings = self.fontsettings,
184 tabsettings = self.tabsettings,
185 file = self.getfilename())
186
187 # make the widgets
188 self.popfield = ClassFinder((popfieldwidth - 17, -15, 16, 16), [], self.popselectline)
189 self.linefield = W.EditText((-1, -15, popfieldwidth - 15, 16), inset = (6, 1))
190 self.editgroup._barx = W.Scrollbar((popfieldwidth - 2, -15, -14, 16), editor.hscroll, max = 32767)
191 self.editgroup._bary = W.Scrollbar((-15, 14, 16, -14), editor.vscroll, max = 32767)
192 self.editgroup.editor = editor # add editor *after* scrollbars
193
194 self.editgroup.optionsmenu = W.PopupMenu((-15, -1, 16, 16), [])
195 self.editgroup.optionsmenu.bind('<click>', self.makeoptionsmenu)
196
197 self.bevelbox = W.BevelBox((0, 0, 0, topbarheight))
198 self.hline = W.HorizontalLine((0, topbarheight, 0, 0))
Just van Rossumf376ef02001-11-18 14:12:43 +0000199 self.infotext = W.TextBox((175, 6, -4, 14), backgroundcolor = (0xe000, 0xe000, 0xe000))
200 self.runbutton = W.BevelButton((6, 4, 80, 16), runButtonLabels[0], self.run)
201 self.runselbutton = W.BevelButton((90, 4, 80, 16), runSelButtonLabels[0], self.runselection)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000202
203 # bind some keys
204 editor.bind("cmdr", self.runbutton.push)
205 editor.bind("enter", self.runselbutton.push)
206 editor.bind("cmdj", self.domenu_gotoline)
207 editor.bind("cmdd", self.domenu_toggledebugger)
208 editor.bind("<idle>", self.updateselection)
209
210 editor.bind("cmde", searchengine.setfindstring)
211 editor.bind("cmdf", searchengine.show)
212 editor.bind("cmdg", searchengine.findnext)
213 editor.bind("cmdshiftr", searchengine.replace)
214 editor.bind("cmdt", searchengine.replacefind)
215
216 self.linefield.bind("return", self.dolinefield)
217 self.linefield.bind("enter", self.dolinefield)
218 self.linefield.bind("tab", self.dolinefield)
219
220 # intercept clicks
221 editor.bind("<click>", self.clickeditor)
222 self.linefield.bind("<click>", self.clicklinefield)
223
224 def makeoptionsmenu(self):
Just van Rossumdc3c6172001-06-19 21:37:33 +0000225 menuitems = [('Font settings\xc9', self.domenu_fontsettings),
226 ("Save options\xc9", self.domenu_options),
Just van Rossum12710051999-02-27 17:18:30 +0000227 '-',
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000228 ('\0' + chr(self.run_as_main) + 'Run as __main__', self.domenu_toggle_run_as_main),
Jack Jansenff773eb2002-03-31 22:01:33 +0000229 #('\0' + chr(self.run_with_interpreter) + 'Run with Interpreter', self.domenu_dtoggle_run_with_interpreter),
230 ('\0' + chr(self.run_with_cl_interpreter) + 'Run with commandline Python', self.domenu_toggle_run_with_cl_interpreter),
231 '-',
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000232 ('Modularize', self.domenu_modularize),
Just van Rossumdc3c6172001-06-19 21:37:33 +0000233 ('Browse namespace\xc9', self.domenu_browsenamespace),
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000234 '-']
235 if self.profiling:
236 menuitems = menuitems + [('Disable profiler', self.domenu_toggleprofiler)]
237 else:
238 menuitems = menuitems + [('Enable profiler', self.domenu_toggleprofiler)]
239 if self.editgroup.editor._debugger:
240 menuitems = menuitems + [('Disable debugger', self.domenu_toggledebugger),
241 ('Clear breakpoints', self.domenu_clearbreakpoints),
Just van Rossumdc3c6172001-06-19 21:37:33 +0000242 ('Edit breakpoints\xc9', self.domenu_editbreakpoints)]
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000243 else:
244 menuitems = menuitems + [('Enable debugger', self.domenu_toggledebugger)]
245 self.editgroup.optionsmenu.set(menuitems)
246
247 def domenu_toggle_run_as_main(self):
248 self.run_as_main = not self.run_as_main
Just van Rossum0f2fd162000-10-20 06:36:30 +0000249 self.run_with_interpreter = 0
Jack Jansenff773eb2002-03-31 22:01:33 +0000250 self.run_with_cl_interpreter = 0
Just van Rossumf7f93882001-11-02 19:24:41 +0000251 self.editgroup.editor.selectionchanged()
Just van Rossum0f2fd162000-10-20 06:36:30 +0000252
Jack Jansenff773eb2002-03-31 22:01:33 +0000253 def XXdomenu_toggle_run_with_interpreter(self):
Just van Rossum0f2fd162000-10-20 06:36:30 +0000254 self.run_with_interpreter = not self.run_with_interpreter
255 self.run_as_main = 0
Jack Jansenff773eb2002-03-31 22:01:33 +0000256 self.run_with_cl_interpreter = 0
257 self.editgroup.editor.selectionchanged()
258
259 def domenu_toggle_run_with_cl_interpreter(self):
260 self.run_with_cl_interpreter = not self.run_with_cl_interpreter
261 self.run_as_main = 0
262 self.run_with_interpreter = 0
Just van Rossumf7f93882001-11-02 19:24:41 +0000263 self.editgroup.editor.selectionchanged()
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000264
265 def showbreakpoints(self, onoff):
266 self.editgroup.editor.showbreakpoints(onoff)
267 self.debugging = onoff
268
269 def domenu_clearbreakpoints(self, *args):
270 self.editgroup.editor.clearbreakpoints()
271
272 def domenu_editbreakpoints(self, *args):
273 self.editgroup.editor.editbreakpoints()
274
275 def domenu_toggledebugger(self, *args):
276 if not self.debugging:
277 W.SetCursor('watch')
278 self.debugging = not self.debugging
279 self.editgroup.editor.togglebreakpoints()
280
281 def domenu_toggleprofiler(self, *args):
282 self.profiling = not self.profiling
283
284 def domenu_browsenamespace(self, *args):
285 import PyBrowser, W
286 W.SetCursor('watch')
287 globals, file, modname = self.getenvironment()
288 if not modname:
289 modname = self.title
290 PyBrowser.Browser(globals, "Object browser: " + modname)
291
292 def domenu_modularize(self, *args):
293 modname = _filename_as_modname(self.title)
294 if not modname:
Just van Rossumdc3c6172001-06-19 21:37:33 +0000295 raise W.AlertError, "Can't modularize \"%s\"" % self.title
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000296 run_as_main = self.run_as_main
297 self.run_as_main = 0
298 self.run()
299 self.run_as_main = run_as_main
300 if self.path:
301 file = self.path
302 else:
303 file = self.title
304
305 if self.globals and not sys.modules.has_key(modname):
306 module = imp.new_module(modname)
307 for attr in self.globals.keys():
308 setattr(module,attr,self.globals[attr])
309 sys.modules[modname] = module
310 self.globals = {}
311
312 def domenu_fontsettings(self, *args):
313 import FontSettings
314 fontsettings = self.editgroup.editor.getfontsettings()
315 tabsettings = self.editgroup.editor.gettabsettings()
316 settings = FontSettings.FontDialog(fontsettings, tabsettings)
317 if settings:
318 fontsettings, tabsettings = settings
319 self.editgroup.editor.setfontsettings(fontsettings)
320 self.editgroup.editor.settabsettings(tabsettings)
321
Just van Rossum12710051999-02-27 17:18:30 +0000322 def domenu_options(self, *args):
Just van Rossumca3d3072002-03-29 21:48:42 +0000323 rv = SaveOptions(self._creator, self._eoln)
324 if rv:
Just van Rossumf7f93882001-11-02 19:24:41 +0000325 self.editgroup.editor.selectionchanged() # ouch...
Just van Rossumca3d3072002-03-29 21:48:42 +0000326 self._creator, self._eoln = rv
Just van Rossum12710051999-02-27 17:18:30 +0000327
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000328 def clicklinefield(self):
329 if self._currentwidget <> self.linefield:
330 self.linefield.select(1)
331 self.linefield.selectall()
332 return 1
333
334 def clickeditor(self):
335 if self._currentwidget <> self.editgroup.editor:
336 self.dolinefield()
337 return 1
338
339 def updateselection(self, force = 0):
340 sel = min(self.editgroup.editor.getselection())
341 lineno = self.editgroup.editor.offsettoline(sel)
342 if lineno <> self.lastlineno or force:
343 self.lastlineno = lineno
344 self.linefield.set(str(lineno + 1))
345 self.linefield.selview()
346
347 def dolinefield(self):
348 try:
349 lineno = string.atoi(self.linefield.get()) - 1
350 if lineno <> self.lastlineno:
351 self.editgroup.editor.selectline(lineno)
352 self.updateselection(1)
353 except:
354 self.updateselection(1)
355 self.editgroup.editor.select(1)
356
357 def setinfotext(self):
358 if not hasattr(self, 'infotext'):
359 return
360 if self.path:
361 self.infotext.set(self.path)
362 else:
363 self.infotext.set("")
364
365 def close(self):
366 if self.editgroup.editor.changed:
367 import EasyDialogs
Jack Jansen5a6fdcd2001-08-25 12:15:04 +0000368 from Carbon import Qd
Just van Rossum25ddc632001-07-05 07:06:26 +0000369 Qd.InitCursor()
370 save = EasyDialogs.AskYesNoCancel('Save window "%s" before closing?' % self.title,
371 default=1, no="Don\xd5t save")
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000372 if save > 0:
373 if self.domenu_save():
374 return 1
375 elif save < 0:
376 return 1
Just van Rossum25ddc632001-07-05 07:06:26 +0000377 self.globals = None
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000378 W.Window.close(self)
379
380 def domenu_close(self, *args):
381 return self.close()
382
383 def domenu_save(self, *args):
384 if not self.path:
385 # Will call us recursively
386 return self.domenu_save_as()
387 data = self.editgroup.editor.get()
Jack Jansen9a389472002-03-29 21:26:04 +0000388 if self._eoln != '\r':
389 data = string.replace(data, '\r', self._eoln)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000390 fp = open(self.path, 'wb') # open file in binary mode, data has '\r' line-endings
391 fp.write(data)
392 fp.close()
393 fss = macfs.FSSpec(self.path)
394 fss.SetCreatorType(self._creator, 'TEXT')
395 self.getsettings()
396 self.writewindowsettings()
397 self.editgroup.editor.changed = 0
398 self.editgroup.editor.selchanged = 0
399 import linecache
400 if linecache.cache.has_key(self.path):
401 del linecache.cache[self.path]
402 import macostools
403 macostools.touched(self.path)
404
405 def can_save(self, menuitem):
406 return self.editgroup.editor.changed or self.editgroup.editor.selchanged
407
408 def domenu_save_as(self, *args):
409 fss, ok = macfs.StandardPutFile('Save as:', self.title)
410 if not ok:
411 return 1
412 self.showbreakpoints(0)
413 self.path = fss.as_pathname()
414 self.setinfotext()
415 self.title = os.path.split(self.path)[-1]
416 self.wid.SetWTitle(self.title)
417 self.domenu_save()
418 self.editgroup.editor.setfile(self.getfilename())
419 app = W.getapplication()
420 app.makeopenwindowsmenu()
421 if hasattr(app, 'makescriptsmenu'):
422 app = W.getapplication()
423 fss, fss_changed = app.scriptsfolder.Resolve()
424 path = fss.as_pathname()
425 if path == self.path[:len(path)]:
426 W.getapplication().makescriptsmenu()
427
428 def domenu_save_as_applet(self, *args):
Just van Rossumdc3c6172001-06-19 21:37:33 +0000429 import buildtools
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000430
431 buildtools.DEBUG = 0 # ouch.
432
433 if self.title[-3:] == ".py":
434 destname = self.title[:-3]
435 else:
436 destname = self.title + ".applet"
437 fss, ok = macfs.StandardPutFile('Save as Applet:', destname)
438 if not ok:
439 return 1
440 W.SetCursor("watch")
441 destname = fss.as_pathname()
442 if self.path:
443 filename = self.path
444 if filename[-3:] == ".py":
445 rsrcname = filename[:-3] + '.rsrc'
446 else:
447 rsrcname = filename + '.rsrc'
448 else:
449 filename = self.title
450 rsrcname = ""
451
452 pytext = self.editgroup.editor.get()
453 pytext = string.split(pytext, '\r')
454 pytext = string.join(pytext, '\n') + '\n'
455 try:
456 code = compile(pytext, filename, "exec")
457 except (SyntaxError, EOFError):
458 raise buildtools.BuildError, "Syntax error in script %s" % `filename`
459
460 # Try removing the output file
461 try:
462 os.remove(destname)
463 except os.error:
464 pass
465 template = buildtools.findtemplate()
466 buildtools.process_common(template, None, code, rsrcname, destname, 0, 1)
467
468 def domenu_gotoline(self, *args):
469 self.linefield.selectall()
470 self.linefield.select(1)
471 self.linefield.selectall()
472
473 def domenu_selectline(self, *args):
474 self.editgroup.editor.expandselection()
475
476 def domenu_find(self, *args):
477 searchengine.show()
478
479 def domenu_entersearchstring(self, *args):
480 searchengine.setfindstring()
481
482 def domenu_replace(self, *args):
483 searchengine.replace()
484
485 def domenu_findnext(self, *args):
486 searchengine.findnext()
487
488 def domenu_replacefind(self, *args):
489 searchengine.replacefind()
490
491 def domenu_run(self, *args):
492 self.runbutton.push()
493
494 def domenu_runselection(self, *args):
495 self.runselbutton.push()
496
497 def run(self):
Just van Rossum73efed22000-04-09 19:45:22 +0000498 if self._threadstate == (0, 0):
499 self._run()
500 else:
Just van Rossum0f2fd162000-10-20 06:36:30 +0000501 lock = Wthreading.Lock()
502 lock.acquire()
503 self._thread.postException(KeyboardInterrupt)
504 if self._thread.isBlocked():
Just van Rossum73efed22000-04-09 19:45:22 +0000505 self._thread.start()
Just van Rossum0f2fd162000-10-20 06:36:30 +0000506 lock.release()
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000507
508 def _run(self):
Just van Rossum0f2fd162000-10-20 06:36:30 +0000509 if self.run_with_interpreter:
510 if self.editgroup.editor.changed:
511 import EasyDialogs
512 import Qd; Qd.InitCursor()
Just van Rossumdc3c6172001-06-19 21:37:33 +0000513 save = EasyDialogs.AskYesNoCancel('Save "%s" before running?' % self.title, 1)
Just van Rossum0f2fd162000-10-20 06:36:30 +0000514 if save > 0:
515 if self.domenu_save():
516 return
517 elif save < 0:
518 return
519 if not self.path:
520 raise W.AlertError, "Can't run unsaved file"
521 self._run_with_interpreter()
Jack Jansenff773eb2002-03-31 22:01:33 +0000522 elif self.run_with_cl_interpreter:
523 # Until universal newline support
524 if self._eoln != '\n':
525 import EasyDialogs
526 ok = EasyDialogs.AskYesNoCancel('Warning: "%s" does not have Unix line-endings'
527 % self.title, 1, yes='OK', no='')
528 if not ok:
529 return
530 if self.editgroup.editor.changed:
531 import EasyDialogs
532 import Qd; Qd.InitCursor()
533 save = EasyDialogs.AskYesNoCancel('Save "%s" before running?' % self.title, 1)
534 if save > 0:
535 if self.domenu_save():
536 return
537 elif save < 0:
538 return
539 if not self.path:
540 raise W.AlertError, "Can't run unsaved file"
541 self._run_with_cl_interpreter()
Just van Rossum0f2fd162000-10-20 06:36:30 +0000542 else:
543 pytext = self.editgroup.editor.get()
544 globals, file, modname = self.getenvironment()
545 self.execstring(pytext, globals, globals, file, modname)
546
547 def _run_with_interpreter(self):
548 interp_path = os.path.join(sys.exec_prefix, "PythonInterpreter")
549 if not os.path.exists(interp_path):
550 raise W.AlertError, "Can't find interpreter"
551 import findertools
552 XXX
Jack Jansenff773eb2002-03-31 22:01:33 +0000553
554 def _run_with_cl_interpreter(self):
555 import Terminal
556 interp_path = os.path.join(sys.exec_prefix, "bin", "python")
557 file_path = self.path
558 if not os.path.exists(interp_path):
559 # This "can happen" if we are running IDE under MacPython. Try
560 # the standard location.
561 interp_path = "/Library/Frameworks/Python.framework/Versions/2.3/bin/python"
562 try:
563 fsr = macfs.FSRef(interp_path)
564 except macfs.Error:
565 raise W.AlertError, "Can't find command-line Python"
566 file_path = macfs.FSRef(macfs.FSSpec(self.path)).as_pathname()
567 cmd = '"%s" "%s" ; exit' % (interp_path, file_path)
568 t = Terminal.Terminal()
569 t.do_script(with_command=cmd)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000570
571 def runselection(self):
Just van Rossum73efed22000-04-09 19:45:22 +0000572 if self._threadstate == (0, 0):
573 self._runselection()
574 elif self._threadstate == (1, 1):
Just van Rossum0f2fd162000-10-20 06:36:30 +0000575 self._thread.block()
Just van Rossum73efed22000-04-09 19:45:22 +0000576 self.setthreadstate((1, 2))
577 elif self._threadstate == (1, 2):
578 self._thread.start()
579 self.setthreadstate((1, 1))
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000580
581 def _runselection(self):
Jack Jansenff773eb2002-03-31 22:01:33 +0000582 if self.run_with_interpreter or self.run_with_cl_interpreter:
Just van Rossum0f2fd162000-10-20 06:36:30 +0000583 raise W.AlertError, "Can't run selection with Interpreter"
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000584 globals, file, modname = self.getenvironment()
585 locals = globals
586 # select whole lines
587 self.editgroup.editor.expandselection()
588
589 # get lineno of first selected line
590 selstart, selend = self.editgroup.editor.getselection()
591 selstart, selend = min(selstart, selend), max(selstart, selend)
592 selfirstline = self.editgroup.editor.offsettoline(selstart)
593 alltext = self.editgroup.editor.get()
594 pytext = alltext[selstart:selend]
595 lines = string.split(pytext, '\r')
596 indent = getminindent(lines)
597 if indent == 1:
598 classname = ''
599 alllines = string.split(alltext, '\r')
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000600 for i in range(selfirstline - 1, -1, -1):
601 line = alllines[i]
602 if line[:6] == 'class ':
603 classname = string.split(string.strip(line[6:]))[0]
604 classend = identifieRE_match(classname)
605 if classend < 1:
Just van Rossumdc3c6172001-06-19 21:37:33 +0000606 raise W.AlertError, "Can't find a class."
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000607 classname = classname[:classend]
608 break
609 elif line and line[0] not in '\t#':
Just van Rossumdc3c6172001-06-19 21:37:33 +0000610 raise W.AlertError, "Can't find a class."
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000611 else:
Just van Rossumdc3c6172001-06-19 21:37:33 +0000612 raise W.AlertError, "Can't find a class."
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000613 if globals.has_key(classname):
Just van Rossum25ddc632001-07-05 07:06:26 +0000614 klass = globals[classname]
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000615 else:
Just van Rossumdc3c6172001-06-19 21:37:33 +0000616 raise W.AlertError, "Can't find class \"%s\"." % classname
Just van Rossum25ddc632001-07-05 07:06:26 +0000617 # add class def
618 pytext = ("class %s:\n" % classname) + pytext
619 selfirstline = selfirstline - 1
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000620 elif indent > 0:
Just van Rossumdc3c6172001-06-19 21:37:33 +0000621 raise W.AlertError, "Can't run indented code."
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000622
623 # add "newlines" to fool compile/exec:
624 # now a traceback will give the right line number
625 pytext = selfirstline * '\r' + pytext
626 self.execstring(pytext, globals, locals, file, modname)
Just van Rossum25ddc632001-07-05 07:06:26 +0000627 if indent == 1 and globals[classname] is not klass:
628 # update the class in place
629 klass.__dict__.update(globals[classname].__dict__)
630 globals[classname] = klass
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000631
Just van Rossum73efed22000-04-09 19:45:22 +0000632 def setthreadstate(self, state):
633 oldstate = self._threadstate
634 if oldstate[0] <> state[0]:
635 self.runbutton.settitle(runButtonLabels[state[0]])
636 if oldstate[1] <> state[1]:
637 self.runselbutton.settitle(runSelButtonLabels[state[1]])
638 self._threadstate = state
639
640 def _exec_threadwrapper(self, *args, **kwargs):
641 apply(execstring, args, kwargs)
642 self.setthreadstate((0, 0))
643 self._thread = None
644
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000645 def execstring(self, pytext, globals, locals, file, modname):
646 tracebackwindow.hide()
647 # update windows
648 W.getapplication().refreshwindows()
649 if self.run_as_main:
650 modname = "__main__"
651 if self.path:
652 dir = os.path.dirname(self.path)
653 savedir = os.getcwd()
654 os.chdir(dir)
Just van Rossuma61f4ac1999-02-01 16:34:08 +0000655 sys.path.insert(0, dir)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000656 else:
657 cwdindex = None
658 try:
Just van Rossum0f2fd162000-10-20 06:36:30 +0000659 if haveThreading:
660 self._thread = Wthreading.Thread(os.path.basename(file),
Just van Rossum73efed22000-04-09 19:45:22 +0000661 self._exec_threadwrapper, pytext, globals, locals, file, self.debugging,
662 modname, self.profiling)
663 self.setthreadstate((1, 1))
664 self._thread.start()
665 else:
666 execstring(pytext, globals, locals, file, self.debugging,
667 modname, self.profiling)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000668 finally:
669 if self.path:
670 os.chdir(savedir)
Just van Rossuma61f4ac1999-02-01 16:34:08 +0000671 del sys.path[0]
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000672
673 def getenvironment(self):
674 if self.path:
675 file = self.path
676 dir = os.path.dirname(file)
677 # check if we're part of a package
678 modname = ""
679 while os.path.exists(os.path.join(dir, "__init__.py")):
680 dir, dirname = os.path.split(dir)
Just van Rossum2aaeb521999-02-05 21:58:25 +0000681 modname = dirname + '.' + modname
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000682 subname = _filename_as_modname(self.title)
Just van Rossumf7f93882001-11-02 19:24:41 +0000683 if subname is None:
684 return self.globals, file, None
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000685 if modname:
686 if subname == "__init__":
Just van Rossum2aaeb521999-02-05 21:58:25 +0000687 # strip trailing period
688 modname = modname[:-1]
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000689 else:
Just van Rossum2aaeb521999-02-05 21:58:25 +0000690 modname = modname + subname
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000691 else:
692 modname = subname
693 if sys.modules.has_key(modname):
694 globals = sys.modules[modname].__dict__
695 self.globals = {}
696 else:
697 globals = self.globals
Just van Rossum73efed22000-04-09 19:45:22 +0000698 modname = subname
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000699 else:
700 file = '<%s>' % self.title
701 globals = self.globals
702 modname = file
703 return globals, file, modname
704
705 def write(self, stuff):
706 """for use as stdout"""
707 self._buf = self._buf + stuff
708 if '\n' in self._buf:
709 self.flush()
710
711 def flush(self):
712 stuff = string.split(self._buf, '\n')
713 stuff = string.join(stuff, '\r')
714 end = self.editgroup.editor.ted.WEGetTextLength()
715 self.editgroup.editor.ted.WESetSelection(end, end)
716 self.editgroup.editor.ted.WEInsert(stuff, None, None)
717 self.editgroup.editor.updatescrollbars()
718 self._buf = ""
719 # ? optional:
720 #self.wid.SelectWindow()
721
722 def getclasslist(self):
723 from string import find, strip
Just van Rossum24073ea1999-12-23 15:46:57 +0000724 methodRE = re.compile(r"\r[ \t]+def ")
725 findMethod = methodRE.search
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000726 editor = self.editgroup.editor
727 text = editor.get()
728 list = []
729 append = list.append
730 functag = "func"
731 classtag = "class"
732 methodtag = "method"
733 pos = -1
734 if text[:4] == 'def ':
735 append((pos + 4, functag))
736 pos = 4
737 while 1:
738 pos = find(text, '\rdef ', pos + 1)
739 if pos < 0:
740 break
741 append((pos + 5, functag))
742 pos = -1
743 if text[:6] == 'class ':
744 append((pos + 6, classtag))
745 pos = 6
746 while 1:
747 pos = find(text, '\rclass ', pos + 1)
748 if pos < 0:
749 break
750 append((pos + 7, classtag))
751 pos = 0
752 while 1:
Just van Rossum24073ea1999-12-23 15:46:57 +0000753 m = findMethod(text, pos + 1)
754 if m is None:
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000755 break
Just van Rossum24073ea1999-12-23 15:46:57 +0000756 pos = m.regs[0][0]
757 #pos = find(text, '\r\tdef ', pos + 1)
758 append((m.regs[0][1], methodtag))
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000759 list.sort()
760 classlist = []
761 methodlistappend = None
762 offsetToLine = editor.ted.WEOffsetToLine
763 getLineRange = editor.ted.WEGetLineRange
764 append = classlist.append
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000765 for pos, tag in list:
766 lineno = offsetToLine(pos)
767 lineStart, lineEnd = getLineRange(lineno)
768 line = strip(text[pos:lineEnd])
769 line = line[:identifieRE_match(line)]
770 if tag is functag:
771 append(("def " + line, lineno + 1))
772 methodlistappend = None
773 elif tag is classtag:
774 append(["class " + line])
775 methodlistappend = classlist[-1].append
776 elif methodlistappend and tag is methodtag:
777 methodlistappend(("def " + line, lineno + 1))
778 return classlist
779
780 def popselectline(self, lineno):
781 self.editgroup.editor.selectline(lineno - 1)
782
783 def selectline(self, lineno, charoffset = 0):
784 self.editgroup.editor.selectline(lineno - 1, charoffset)
785
Just van Rossum12710051999-02-27 17:18:30 +0000786class _saveoptions:
787
Jack Jansen9a389472002-03-29 21:26:04 +0000788 def __init__(self, creator, eoln):
Just van Rossum12710051999-02-27 17:18:30 +0000789 self.rv = None
Jack Jansen9a389472002-03-29 21:26:04 +0000790 self.eoln = eoln
791 self.w = w = W.ModalDialog((260, 160), 'Save options')
Just van Rossum12710051999-02-27 17:18:30 +0000792 radiobuttons = []
793 w.label = W.TextBox((8, 8, 80, 18), "File creator:")
Just van Rossum3af507d1999-04-22 22:23:46 +0000794 w.ide_radio = W.RadioButton((8, 22, 160, 18), "This application", radiobuttons, self.ide_hit)
Jack Jansen9a389472002-03-29 21:26:04 +0000795 w.interp_radio = W.RadioButton((8, 42, 160, 18), "MacPython Interpreter", radiobuttons, self.interp_hit)
796 w.interpx_radio = W.RadioButton((8, 62, 160, 18), "OSX PythonW Interpreter", radiobuttons, self.interpx_hit)
797 w.other_radio = W.RadioButton((8, 82, 50, 18), "Other:", radiobuttons)
798 w.other_creator = W.EditText((62, 82, 40, 20), creator, self.otherselect)
799 w.none_radio = W.RadioButton((8, 102, 160, 18), "None", radiobuttons, self.none_hit)
Just van Rossum12710051999-02-27 17:18:30 +0000800 w.cancelbutton = W.Button((-180, -30, 80, 16), "Cancel", self.cancelbuttonhit)
801 w.okbutton = W.Button((-90, -30, 80, 16), "Done", self.okbuttonhit)
802 w.setdefaultbutton(w.okbutton)
803 if creator == 'Pyth':
804 w.interp_radio.set(1)
Just van Rossum3af507d1999-04-22 22:23:46 +0000805 elif creator == W._signature:
Just van Rossum12710051999-02-27 17:18:30 +0000806 w.ide_radio.set(1)
Jack Jansen9a389472002-03-29 21:26:04 +0000807 elif creator == 'PytX':
808 w.interpx_radio.set(1)
809 elif creator == '\0\0\0\0':
810 w.none_radio.set(1)
Just van Rossum12710051999-02-27 17:18:30 +0000811 else:
812 w.other_radio.set(1)
Jack Jansen9a389472002-03-29 21:26:04 +0000813
814 w.eolnlabel = W.TextBox((168, 8, 80, 18), "Newline style:")
815 radiobuttons = []
816 w.unix_radio = W.RadioButton((168, 22, 80, 18), "Unix", radiobuttons, self.unix_hit)
817 w.mac_radio = W.RadioButton((168, 42, 80, 18), "Macintosh", radiobuttons, self.mac_hit)
818 w.win_radio = W.RadioButton((168, 62, 80, 18), "Windows", radiobuttons, self.win_hit)
819 if self.eoln == '\n':
820 w.unix_radio.set(1)
821 elif self.eoln == '\r\n':
822 w.win_radio.set(1)
823 else:
824 w.mac_radio.set(1)
825
Just van Rossum12710051999-02-27 17:18:30 +0000826 w.bind("cmd.", w.cancelbutton.push)
827 w.open()
828
829 def ide_hit(self):
Just van Rossum3af507d1999-04-22 22:23:46 +0000830 self.w.other_creator.set(W._signature)
Just van Rossum12710051999-02-27 17:18:30 +0000831
832 def interp_hit(self):
833 self.w.other_creator.set("Pyth")
834
Jack Jansen9a389472002-03-29 21:26:04 +0000835 def interpx_hit(self):
836 self.w.other_creator.set("PytX")
837
838 def none_hit(self):
839 self.w.other_creator.set("\0\0\0\0")
840
Just van Rossum12710051999-02-27 17:18:30 +0000841 def otherselect(self, *args):
842 sel_from, sel_to = self.w.other_creator.getselection()
843 creator = self.w.other_creator.get()[:4]
844 creator = creator + " " * (4 - len(creator))
845 self.w.other_creator.set(creator)
846 self.w.other_creator.setselection(sel_from, sel_to)
847 self.w.other_radio.set(1)
848
Jack Jansen9a389472002-03-29 21:26:04 +0000849 def mac_hit(self):
850 self.eoln = '\r'
851
852 def unix_hit(self):
853 self.eoln = '\n'
854
855 def win_hit(self):
856 self.eoln = '\r\n'
857
Just van Rossum12710051999-02-27 17:18:30 +0000858 def cancelbuttonhit(self):
859 self.w.close()
860
861 def okbuttonhit(self):
Jack Jansen9a389472002-03-29 21:26:04 +0000862 self.rv = (self.w.other_creator.get()[:4], self.eoln)
Just van Rossum12710051999-02-27 17:18:30 +0000863 self.w.close()
864
865
Jack Jansen9a389472002-03-29 21:26:04 +0000866def SaveOptions(creator, eoln):
867 s = _saveoptions(creator, eoln)
Just van Rossum12710051999-02-27 17:18:30 +0000868 return s.rv
869
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000870
871def _escape(where, what) :
872 return string.join(string.split(where, what), '\\' + what)
873
874def _makewholewordpattern(word):
875 # first, escape special regex chars
Just van Rossum3eec7622001-07-10 19:25:40 +0000876 for esc in "\\[]()|.*^+$?":
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000877 word = _escape(word, esc)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000878 notwordcharspat = '[^' + _wordchars + ']'
Jack Jansen9ad27522001-02-21 13:54:31 +0000879 pattern = '(' + word + ')'
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000880 if word[0] in _wordchars:
881 pattern = notwordcharspat + pattern
882 if word[-1] in _wordchars:
883 pattern = pattern + notwordcharspat
Jack Jansen9ad27522001-02-21 13:54:31 +0000884 return re.compile(pattern)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000885
Just van Rossumf376ef02001-11-18 14:12:43 +0000886
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000887class SearchEngine:
888
889 def __init__(self):
890 self.visible = 0
891 self.w = None
892 self.parms = { "find": "",
893 "replace": "",
894 "wrap": 1,
895 "casesens": 1,
896 "wholeword": 1
897 }
898 import MacPrefs
899 prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath)
900 if prefs.searchengine:
901 self.parms["casesens"] = prefs.searchengine.casesens
902 self.parms["wrap"] = prefs.searchengine.wrap
903 self.parms["wholeword"] = prefs.searchengine.wholeword
904
905 def show(self):
906 self.visible = 1
907 if self.w:
908 self.w.wid.ShowWindow()
909 self.w.wid.SelectWindow()
910 self.w.find.edit.select(1)
911 self.w.find.edit.selectall()
912 return
913 self.w = W.Dialog((420, 150), "Find")
914
915 self.w.find = TitledEditText((10, 4, 300, 36), "Search for:")
916 self.w.replace = TitledEditText((10, 100, 300, 36), "Replace with:")
917
918 self.w.boxes = W.Group((10, 50, 300, 40))
919 self.w.boxes.casesens = W.CheckBox((0, 0, 100, 16), "Case sensitive")
920 self.w.boxes.wholeword = W.CheckBox((0, 20, 100, 16), "Whole word")
921 self.w.boxes.wrap = W.CheckBox((110, 0, 100, 16), "Wrap around")
922
923 self.buttons = [ ("Find", "cmdf", self.find),
924 ("Replace", "cmdr", self.replace),
925 ("Replace all", None, self.replaceall),
Just van Rossumdc3c6172001-06-19 21:37:33 +0000926 ("Don't find", "cmdd", self.dont),
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000927 ("Cancel", "cmd.", self.cancel)
928 ]
929 for i in range(len(self.buttons)):
930 bounds = -90, 22 + i * 24, 80, 16
931 title, shortcut, callback = self.buttons[i]
932 self.w[title] = W.Button(bounds, title, callback)
933 if shortcut:
934 self.w.bind(shortcut, self.w[title].push)
Just van Rossumdc3c6172001-06-19 21:37:33 +0000935 self.w.setdefaultbutton(self.w["Don't find"])
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000936 self.w.find.edit.bind("<key>", self.key)
937 self.w.bind("<activate>", self.activate)
938 self.w.bind("<close>", self.close)
939 self.w.open()
940 self.setparms()
941 self.w.find.edit.select(1)
942 self.w.find.edit.selectall()
943 self.checkbuttons()
944
945 def close(self):
946 self.hide()
947 return -1
948
949 def key(self, char, modifiers):
950 self.w.find.edit.key(char, modifiers)
951 self.checkbuttons()
952 return 1
953
954 def activate(self, onoff):
955 if onoff:
956 self.checkbuttons()
957
958 def checkbuttons(self):
959 editor = findeditor(self)
960 if editor:
961 if self.w.find.get():
962 for title, cmd, call in self.buttons[:-2]:
963 self.w[title].enable(1)
964 self.w.setdefaultbutton(self.w["Find"])
965 else:
966 for title, cmd, call in self.buttons[:-2]:
967 self.w[title].enable(0)
Just van Rossumdc3c6172001-06-19 21:37:33 +0000968 self.w.setdefaultbutton(self.w["Don't find"])
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000969 else:
970 for title, cmd, call in self.buttons[:-2]:
971 self.w[title].enable(0)
Just van Rossumdc3c6172001-06-19 21:37:33 +0000972 self.w.setdefaultbutton(self.w["Don't find"])
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000973
974 def find(self):
975 self.getparmsfromwindow()
976 if self.findnext():
977 self.hide()
978
979 def replace(self):
980 editor = findeditor(self)
981 if not editor:
982 return
983 if self.visible:
984 self.getparmsfromwindow()
985 text = editor.getselectedtext()
986 find = self.parms["find"]
987 if not self.parms["casesens"]:
988 find = string.lower(find)
989 text = string.lower(text)
990 if text == find:
991 self.hide()
992 editor.insert(self.parms["replace"])
993
994 def replaceall(self):
995 editor = findeditor(self)
996 if not editor:
997 return
998 if self.visible:
999 self.getparmsfromwindow()
1000 W.SetCursor("watch")
1001 find = self.parms["find"]
1002 if not find:
1003 return
1004 findlen = len(find)
1005 replace = self.parms["replace"]
1006 replacelen = len(replace)
1007 Text = editor.get()
1008 if not self.parms["casesens"]:
1009 find = string.lower(find)
1010 text = string.lower(Text)
1011 else:
1012 text = Text
1013 newtext = ""
1014 pos = 0
1015 counter = 0
1016 while 1:
1017 if self.parms["wholeword"]:
1018 wholewordRE = _makewholewordpattern(find)
Jack Jansen9ad27522001-02-21 13:54:31 +00001019 match = wholewordRE.search(text, pos)
1020 if match:
1021 pos = match.start(1)
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001022 else:
1023 pos = -1
1024 else:
1025 pos = string.find(text, find, pos)
1026 if pos < 0:
1027 break
1028 counter = counter + 1
1029 text = text[:pos] + replace + text[pos + findlen:]
1030 Text = Text[:pos] + replace + Text[pos + findlen:]
1031 pos = pos + replacelen
1032 W.SetCursor("arrow")
1033 if counter:
1034 self.hide()
1035 import EasyDialogs
Jack Jansen5a6fdcd2001-08-25 12:15:04 +00001036 from Carbon import Res
Just van Rossumf7f93882001-11-02 19:24:41 +00001037 editor.textchanged()
1038 editor.selectionchanged()
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001039 editor.ted.WEUseText(Res.Resource(Text))
1040 editor.ted.WECalText()
1041 editor.SetPort()
Jack Jansen73023402001-01-23 14:58:20 +00001042 editor.GetWindow().InvalWindowRect(editor._bounds)
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001043 #editor.ted.WEUpdate(self.w.wid.GetWindowPort().visRgn)
1044 EasyDialogs.Message("Replaced %d occurrences" % counter)
1045
1046 def dont(self):
1047 self.getparmsfromwindow()
1048 self.hide()
1049
1050 def replacefind(self):
1051 self.replace()
1052 self.findnext()
1053
1054 def setfindstring(self):
1055 editor = findeditor(self)
1056 if not editor:
1057 return
1058 find = editor.getselectedtext()
1059 if not find:
1060 return
1061 self.parms["find"] = find
1062 if self.w:
1063 self.w.find.edit.set(self.parms["find"])
1064 self.w.find.edit.selectall()
1065
1066 def findnext(self):
1067 editor = findeditor(self)
1068 if not editor:
1069 return
1070 find = self.parms["find"]
1071 if not find:
1072 return
1073 text = editor.get()
1074 if not self.parms["casesens"]:
1075 find = string.lower(find)
1076 text = string.lower(text)
1077 selstart, selend = editor.getselection()
1078 selstart, selend = min(selstart, selend), max(selstart, selend)
1079 if self.parms["wholeword"]:
1080 wholewordRE = _makewholewordpattern(find)
Jack Jansen9ad27522001-02-21 13:54:31 +00001081 match = wholewordRE.search(text, selend)
1082 if match:
1083 pos = match.start(1)
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001084 else:
1085 pos = -1
1086 else:
1087 pos = string.find(text, find, selend)
1088 if pos >= 0:
1089 editor.setselection(pos, pos + len(find))
1090 return 1
1091 elif self.parms["wrap"]:
1092 if self.parms["wholeword"]:
Jack Jansen9ad27522001-02-21 13:54:31 +00001093 match = wholewordRE.search(text, 0)
1094 if match:
1095 pos = match.start(1)
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001096 else:
1097 pos = -1
1098 else:
1099 pos = string.find(text, find)
1100 if selstart > pos >= 0:
1101 editor.setselection(pos, pos + len(find))
1102 return 1
1103
1104 def setparms(self):
1105 for key, value in self.parms.items():
1106 try:
1107 self.w[key].set(value)
1108 except KeyError:
1109 self.w.boxes[key].set(value)
1110
1111 def getparmsfromwindow(self):
1112 if not self.w:
1113 return
1114 for key, value in self.parms.items():
1115 try:
1116 value = self.w[key].get()
1117 except KeyError:
1118 value = self.w.boxes[key].get()
1119 self.parms[key] = value
1120
1121 def cancel(self):
1122 self.hide()
1123 self.setparms()
1124
1125 def hide(self):
1126 if self.w:
1127 self.w.wid.HideWindow()
1128 self.visible = 0
1129
1130 def writeprefs(self):
1131 import MacPrefs
1132 self.getparmsfromwindow()
1133 prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath)
1134 prefs.searchengine.casesens = self.parms["casesens"]
1135 prefs.searchengine.wrap = self.parms["wrap"]
1136 prefs.searchengine.wholeword = self.parms["wholeword"]
1137 prefs.save()
1138
1139
1140class TitledEditText(W.Group):
1141
1142 def __init__(self, possize, title, text = ""):
1143 W.Group.__init__(self, possize)
1144 self.title = W.TextBox((0, 0, 0, 16), title)
1145 self.edit = W.EditText((0, 16, 0, 0), text)
1146
1147 def set(self, value):
1148 self.edit.set(value)
1149
1150 def get(self):
1151 return self.edit.get()
1152
1153
1154class ClassFinder(W.PopupWidget):
1155
1156 def click(self, point, modifiers):
1157 W.SetCursor("watch")
1158 self.set(self._parentwindow.getclasslist())
1159 W.PopupWidget.click(self, point, modifiers)
1160
1161
1162def getminindent(lines):
1163 indent = -1
1164 for line in lines:
1165 stripped = string.strip(line)
1166 if not stripped or stripped[0] == '#':
1167 continue
1168 if indent < 0 or line[:indent] <> indent * '\t':
1169 indent = 0
1170 for c in line:
1171 if c <> '\t':
1172 break
1173 indent = indent + 1
1174 return indent
1175
1176
1177def getoptionkey():
1178 return not not ord(Evt.GetKeys()[7]) & 0x04
1179
1180
1181def execstring(pytext, globals, locals, filename="<string>", debugging=0,
1182 modname="__main__", profiling=0):
1183 if debugging:
1184 import PyDebugger, bdb
1185 BdbQuit = bdb.BdbQuit
1186 else:
1187 BdbQuit = 'BdbQuitDummyException'
1188 pytext = string.split(pytext, '\r')
1189 pytext = string.join(pytext, '\n') + '\n'
1190 W.SetCursor("watch")
1191 globals['__name__'] = modname
1192 globals['__file__'] = filename
1193 sys.argv = [filename]
1194 try:
1195 code = compile(pytext, filename, "exec")
1196 except:
1197 # XXXX BAAAADDD.... We let tracebackwindow decide to treat SyntaxError
1198 # special. That's wrong because THIS case is special (could be literal
1199 # overflow!) and SyntaxError could mean we need a traceback (syntax error
1200 # in imported module!!!
1201 tracebackwindow.traceback(1, filename)
1202 return
1203 try:
1204 if debugging:
Just van Rossum0f2fd162000-10-20 06:36:30 +00001205 if haveThreading:
1206 lock = Wthreading.Lock()
1207 lock.acquire()
Just van Rossum73efed22000-04-09 19:45:22 +00001208 PyDebugger.startfromhere()
Just van Rossum0f2fd162000-10-20 06:36:30 +00001209 lock.release()
Just van Rossum73efed22000-04-09 19:45:22 +00001210 else:
1211 PyDebugger.startfromhere()
Just van Rossum0f2fd162000-10-20 06:36:30 +00001212 elif not haveThreading:
Jack Jansen815d2bf2002-01-21 23:00:52 +00001213 if hasattr(MacOS, 'EnableAppswitch'):
1214 MacOS.EnableAppswitch(0)
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001215 try:
1216 if profiling:
1217 import profile, ProfileBrowser
1218 p = profile.Profile()
1219 p.set_cmd(filename)
1220 try:
1221 p.runctx(code, globals, locals)
1222 finally:
1223 import pstats
1224
1225 stats = pstats.Stats(p)
1226 ProfileBrowser.ProfileBrowser(stats)
1227 else:
1228 exec code in globals, locals
1229 finally:
Just van Rossum0f2fd162000-10-20 06:36:30 +00001230 if not haveThreading:
Jack Jansen815d2bf2002-01-21 23:00:52 +00001231 if hasattr(MacOS, 'EnableAppswitch'):
1232 MacOS.EnableAppswitch(-1)
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001233 except W.AlertError, detail:
1234 raise W.AlertError, detail
1235 except (KeyboardInterrupt, BdbQuit):
1236 pass
Just van Rossumf7f93882001-11-02 19:24:41 +00001237 except SystemExit, arg:
1238 if arg.code:
1239 sys.stderr.write("Script exited with status code: %s\n" % repr(arg.code))
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001240 except:
Just van Rossum0f2fd162000-10-20 06:36:30 +00001241 if haveThreading:
1242 import continuation
1243 lock = Wthreading.Lock()
1244 lock.acquire()
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001245 if debugging:
1246 sys.settrace(None)
1247 PyDebugger.postmortem(sys.exc_type, sys.exc_value, sys.exc_traceback)
1248 return
1249 else:
1250 tracebackwindow.traceback(1, filename)
Just van Rossum0f2fd162000-10-20 06:36:30 +00001251 if haveThreading:
1252 lock.release()
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001253 if debugging:
1254 sys.settrace(None)
1255 PyDebugger.stop()
1256
1257
Just van Rossum3eec7622001-07-10 19:25:40 +00001258_identifieRE = re.compile(r"[A-Za-z_][A-Za-z_0-9]*")
Jack Jansen9ad27522001-02-21 13:54:31 +00001259
1260def identifieRE_match(str):
1261 match = _identifieRE.match(str)
1262 if not match:
1263 return -1
1264 return match.end()
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001265
1266def _filename_as_modname(fname):
1267 if fname[-3:] == '.py':
1268 modname = fname[:-3]
Jack Jansen9ad27522001-02-21 13:54:31 +00001269 match = _identifieRE.match(modname)
1270 if match and match.start() == 0 and match.end() == len(modname):
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001271 return string.join(string.split(modname, '.'), '_')
1272
1273def findeditor(topwindow, fromtop = 0):
Just van Rossum40144012002-02-04 12:52:44 +00001274 wid = MyFrontWindow()
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001275 if not fromtop:
1276 if topwindow.w and wid == topwindow.w.wid:
1277 wid = topwindow.w.wid.GetNextWindow()
1278 if not wid:
1279 return
1280 app = W.getapplication()
1281 if app._windows.has_key(wid): # KeyError otherwise can happen in RoboFog :-(
1282 window = W.getapplication()._windows[wid]
1283 else:
1284 return
1285 if not isinstance(window, Editor):
1286 return
1287 return window.editgroup.editor
1288
1289
1290class _EditorDefaultSettings:
1291
1292 def __init__(self):
1293 self.template = "%s, %d point"
1294 self.fontsettings, self.tabsettings, self.windowsize = geteditorprefs()
1295 self.w = W.Dialog((328, 120), "Editor default settings")
Just van Rossumdc3c6172001-06-19 21:37:33 +00001296 self.w.setfontbutton = W.Button((8, 8, 80, 16), "Set font\xc9", self.dofont)
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001297 self.w.fonttext = W.TextBox((98, 10, -8, 14), self.template % (self.fontsettings[0], self.fontsettings[2]))
1298
1299 self.w.picksizebutton = W.Button((8, 50, 80, 16), "Front window", self.picksize)
1300 self.w.xsizelabel = W.TextBox((98, 32, 40, 14), "Width:")
1301 self.w.ysizelabel = W.TextBox((148, 32, 40, 14), "Height:")
1302 self.w.xsize = W.EditText((98, 48, 40, 20), `self.windowsize[0]`)
1303 self.w.ysize = W.EditText((148, 48, 40, 20), `self.windowsize[1]`)
1304
1305 self.w.cancelbutton = W.Button((-180, -26, 80, 16), "Cancel", self.cancel)
1306 self.w.okbutton = W.Button((-90, -26, 80, 16), "Done", self.ok)
1307 self.w.setdefaultbutton(self.w.okbutton)
1308 self.w.bind('cmd.', self.w.cancelbutton.push)
1309 self.w.open()
1310
1311 def picksize(self):
1312 app = W.getapplication()
1313 editor = findeditor(self)
1314 if editor is not None:
1315 width, height = editor._parentwindow._bounds[2:]
1316 self.w.xsize.set(`width`)
1317 self.w.ysize.set(`height`)
1318 else:
1319 raise W.AlertError, "No edit window found"
1320
1321 def dofont(self):
1322 import FontSettings
1323 settings = FontSettings.FontDialog(self.fontsettings, self.tabsettings)
1324 if settings:
1325 self.fontsettings, self.tabsettings = settings
1326 sys.exc_traceback = None
1327 self.w.fonttext.set(self.template % (self.fontsettings[0], self.fontsettings[2]))
1328
1329 def close(self):
1330 self.w.close()
1331 del self.w
1332
1333 def cancel(self):
1334 self.close()
1335
1336 def ok(self):
1337 try:
1338 width = string.atoi(self.w.xsize.get())
1339 except:
1340 self.w.xsize.select(1)
1341 self.w.xsize.selectall()
1342 raise W.AlertError, "Bad number for window width"
1343 try:
1344 height = string.atoi(self.w.ysize.get())
1345 except:
1346 self.w.ysize.select(1)
1347 self.w.ysize.selectall()
1348 raise W.AlertError, "Bad number for window height"
1349 self.windowsize = width, height
1350 seteditorprefs(self.fontsettings, self.tabsettings, self.windowsize)
1351 self.close()
1352
1353def geteditorprefs():
1354 import MacPrefs
1355 prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath)
1356 try:
1357 fontsettings = prefs.pyedit.fontsettings
1358 tabsettings = prefs.pyedit.tabsettings
1359 windowsize = prefs.pyedit.windowsize
1360 except:
Just van Rossumf7f93882001-11-02 19:24:41 +00001361 fontsettings = prefs.pyedit.fontsettings = ("Geneva", 0, 10, (0, 0, 0))
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001362 tabsettings = prefs.pyedit.tabsettings = (8, 1)
1363 windowsize = prefs.pyedit.windowsize = (500, 250)
1364 sys.exc_traceback = None
1365 return fontsettings, tabsettings, windowsize
1366
1367def seteditorprefs(fontsettings, tabsettings, windowsize):
1368 import MacPrefs
1369 prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath)
1370 prefs.pyedit.fontsettings = fontsettings
1371 prefs.pyedit.tabsettings = tabsettings
1372 prefs.pyedit.windowsize = windowsize
1373 prefs.save()
1374
1375_defaultSettingsEditor = None
1376
1377def EditorDefaultSettings():
1378 global _defaultSettingsEditor
1379 if _defaultSettingsEditor is None or not hasattr(_defaultSettingsEditor, "w"):
1380 _defaultSettingsEditor = _EditorDefaultSettings()
1381 else:
1382 _defaultSettingsEditor.w.select()
1383
1384def resolvealiases(path):
1385 try:
1386 return macfs.ResolveAliasFile(path)[0].as_pathname()
1387 except (macfs.error, ValueError), (error, str):
1388 if error <> -120:
1389 raise
1390 dir, file = os.path.split(path)
1391 return os.path.join(resolvealiases(dir), file)
1392
1393searchengine = SearchEngine()
1394tracebackwindow = Wtraceback.TraceBack()