blob: 6826c658661b57f2b4c603dd602832dd6614f01f [file] [log] [blame]
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001"""A (less & less) simple Python editor"""
2
3import W
4import Wtraceback
5from Wkeys import *
6
Just van Rossum40f9b7b1999-01-30 22:39:17 +00007import MacOS
Jack Jansenfd0b00e2003-01-26 22:15:48 +00008import EasyDialogs
Jack Jansen5a6fdcd2001-08-25 12:15:04 +00009from Carbon import Win
10from Carbon import Res
11from Carbon import Evt
Just van Rossum2ad94192002-07-12 12:06:17 +000012from Carbon import Qd
Jack Jansene7ee17c2003-02-06 22:32:35 +000013from Carbon import File
Just van Rossum40f9b7b1999-01-30 22:39:17 +000014import os
15import imp
16import sys
17import string
18import marshal
Jack Jansen9ad27522001-02-21 13:54:31 +000019import re
Just van Rossum40f9b7b1999-01-30 22:39:17 +000020
Jack Jansene7ee17c2003-02-06 22:32:35 +000021smAllScripts = -3
22
Just van Rossum40144012002-02-04 12:52:44 +000023if hasattr(Win, "FrontNonFloatingWindow"):
24 MyFrontWindow = Win.FrontNonFloatingWindow
25else:
26 MyFrontWindow = Win.FrontWindow
27
28
Just van Rossum40f9b7b1999-01-30 22:39:17 +000029_scriptuntitledcounter = 1
Fred Drake79e75e12001-07-20 19:05:50 +000030_wordchars = string.ascii_letters + string.digits + "_"
Just van Rossum40f9b7b1999-01-30 22:39:17 +000031
32
Just van Rossum73efed22000-04-09 19:45:22 +000033runButtonLabels = ["Run all", "Stop!"]
34runSelButtonLabels = ["Run selection", "Pause!", "Resume"]
35
36
Just van Rossum40f9b7b1999-01-30 22:39:17 +000037class Editor(W.Window):
38
39 def __init__(self, path = "", title = ""):
40 defaultfontsettings, defaulttabsettings, defaultwindowsize = geteditorprefs()
41 global _scriptuntitledcounter
42 if not path:
43 if title:
44 self.title = title
45 else:
Walter Dörwald70a6b492004-02-12 17:35:32 +000046 self.title = "Untitled Script %r" % (_scriptuntitledcounter,)
Just van Rossum40f9b7b1999-01-30 22:39:17 +000047 _scriptuntitledcounter = _scriptuntitledcounter + 1
48 text = ""
49 self._creator = W._signature
Jack Jansen9a389472002-03-29 21:26:04 +000050 self._eoln = os.linesep
Just van Rossum40f9b7b1999-01-30 22:39:17 +000051 elif os.path.exists(path):
52 path = resolvealiases(path)
53 dir, name = os.path.split(path)
54 self.title = name
55 f = open(path, "rb")
56 text = f.read()
57 f.close()
Jack Jansene7ee17c2003-02-06 22:32:35 +000058 self._creator, filetype = MacOS.GetCreatorAndType(path)
Jack Jansenc00b6d72003-02-25 15:08:02 +000059 self.addrecentfile(path)
Just van Rossum4e6b3c52003-11-18 22:41:16 +000060 if '\n' in text:
61 if string.find(text, '\r\n') >= 0:
62 self._eoln = '\r\n'
63 else:
64 self._eoln = '\n'
65 text = string.replace(text, self._eoln, '\r')
66 else:
67 self._eoln = '\r'
Just van Rossum40f9b7b1999-01-30 22:39:17 +000068 else:
69 raise IOError, "file '%s' does not exist" % path
70 self.path = path
71
72 self.settings = {}
73 if self.path:
74 self.readwindowsettings()
75 if self.settings.has_key("windowbounds"):
76 bounds = self.settings["windowbounds"]
77 else:
78 bounds = defaultwindowsize
79 if self.settings.has_key("fontsettings"):
80 self.fontsettings = self.settings["fontsettings"]
81 else:
82 self.fontsettings = defaultfontsettings
83 if self.settings.has_key("tabsize"):
84 try:
85 self.tabsettings = (tabsize, tabmode) = self.settings["tabsize"]
86 except:
87 self.tabsettings = defaulttabsettings
88 else:
89 self.tabsettings = defaulttabsettings
Just van Rossum40f9b7b1999-01-30 22:39:17 +000090
Just van Rossumc7ba0801999-05-21 21:42:27 +000091 W.Window.__init__(self, bounds, self.title, minsize = (330, 120), tabbable = 0)
Just van Rossum40f9b7b1999-01-30 22:39:17 +000092 self.setupwidgets(text)
Just van Rossumc7ba0801999-05-21 21:42:27 +000093
Just van Rossum40f9b7b1999-01-30 22:39:17 +000094 if self.settings.has_key("selection"):
95 selstart, selend = self.settings["selection"]
96 self.setselection(selstart, selend)
97 self.open()
98 self.setinfotext()
99 self.globals = {}
100 self._buf = "" # for write method
101 self.debugging = 0
102 self.profiling = 0
Jack Jansenff773eb2002-03-31 22:01:33 +0000103 self.run_as_main = self.settings.get("run_as_main", 0)
104 self.run_with_interpreter = self.settings.get("run_with_interpreter", 0)
105 self.run_with_cl_interpreter = self.settings.get("run_with_cl_interpreter", 0)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000106
107 def readwindowsettings(self):
108 try:
Jack Jansend13c3852000-06-20 21:59:25 +0000109 resref = Res.FSpOpenResFile(self.path, 1)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000110 except Res.Error:
111 return
112 try:
113 Res.UseResFile(resref)
114 data = Res.Get1Resource('PyWS', 128)
115 self.settings = marshal.loads(data.data)
116 except:
117 pass
118 Res.CloseResFile(resref)
119
120 def writewindowsettings(self):
121 try:
Jack Jansend13c3852000-06-20 21:59:25 +0000122 resref = Res.FSpOpenResFile(self.path, 3)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000123 except Res.Error:
Jack Jansene7ee17c2003-02-06 22:32:35 +0000124 Res.FSpCreateResFile(self.path, self._creator, 'TEXT', smAllScripts)
Jack Jansend13c3852000-06-20 21:59:25 +0000125 resref = Res.FSpOpenResFile(self.path, 3)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000126 try:
127 data = Res.Resource(marshal.dumps(self.settings))
128 Res.UseResFile(resref)
129 try:
130 temp = Res.Get1Resource('PyWS', 128)
131 temp.RemoveResource()
132 except Res.Error:
133 pass
134 data.AddResource('PyWS', 128, "window settings")
135 finally:
136 Res.UpdateResFile(resref)
137 Res.CloseResFile(resref)
138
139 def getsettings(self):
140 self.settings = {}
141 self.settings["windowbounds"] = self.getbounds()
142 self.settings["selection"] = self.getselection()
143 self.settings["fontsettings"] = self.editgroup.editor.getfontsettings()
144 self.settings["tabsize"] = self.editgroup.editor.gettabsettings()
145 self.settings["run_as_main"] = self.run_as_main
Just van Rossum0f2fd162000-10-20 06:36:30 +0000146 self.settings["run_with_interpreter"] = self.run_with_interpreter
Jack Jansenff773eb2002-03-31 22:01:33 +0000147 self.settings["run_with_cl_interpreter"] = self.run_with_cl_interpreter
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000148
149 def get(self):
150 return self.editgroup.editor.get()
151
152 def getselection(self):
153 return self.editgroup.editor.ted.WEGetSelection()
154
155 def setselection(self, selstart, selend):
156 self.editgroup.editor.setselection(selstart, selend)
Jack Jansen9a791822003-05-06 14:28:31 +0000157
158 def getselectedtext(self):
159 return self.editgroup.editor.getselectedtext()
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000160
161 def getfilename(self):
162 if self.path:
163 return self.path
164 return '<%s>' % self.title
165
166 def setupwidgets(self, text):
Just van Rossumf376ef02001-11-18 14:12:43 +0000167 topbarheight = 24
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000168 popfieldwidth = 80
169 self.lastlineno = None
170
171 # make an editor
172 self.editgroup = W.Group((0, topbarheight + 1, 0, 0))
173 editor = W.PyEditor((0, 0, -15,-15), text,
174 fontsettings = self.fontsettings,
175 tabsettings = self.tabsettings,
176 file = self.getfilename())
177
178 # make the widgets
179 self.popfield = ClassFinder((popfieldwidth - 17, -15, 16, 16), [], self.popselectline)
180 self.linefield = W.EditText((-1, -15, popfieldwidth - 15, 16), inset = (6, 1))
181 self.editgroup._barx = W.Scrollbar((popfieldwidth - 2, -15, -14, 16), editor.hscroll, max = 32767)
182 self.editgroup._bary = W.Scrollbar((-15, 14, 16, -14), editor.vscroll, max = 32767)
183 self.editgroup.editor = editor # add editor *after* scrollbars
184
185 self.editgroup.optionsmenu = W.PopupMenu((-15, -1, 16, 16), [])
186 self.editgroup.optionsmenu.bind('<click>', self.makeoptionsmenu)
187
188 self.bevelbox = W.BevelBox((0, 0, 0, topbarheight))
189 self.hline = W.HorizontalLine((0, topbarheight, 0, 0))
Just van Rossumf376ef02001-11-18 14:12:43 +0000190 self.infotext = W.TextBox((175, 6, -4, 14), backgroundcolor = (0xe000, 0xe000, 0xe000))
191 self.runbutton = W.BevelButton((6, 4, 80, 16), runButtonLabels[0], self.run)
192 self.runselbutton = W.BevelButton((90, 4, 80, 16), runSelButtonLabels[0], self.runselection)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000193
194 # bind some keys
195 editor.bind("cmdr", self.runbutton.push)
196 editor.bind("enter", self.runselbutton.push)
197 editor.bind("cmdj", self.domenu_gotoline)
198 editor.bind("cmdd", self.domenu_toggledebugger)
199 editor.bind("<idle>", self.updateselection)
200
201 editor.bind("cmde", searchengine.setfindstring)
202 editor.bind("cmdf", searchengine.show)
203 editor.bind("cmdg", searchengine.findnext)
204 editor.bind("cmdshiftr", searchengine.replace)
205 editor.bind("cmdt", searchengine.replacefind)
206
207 self.linefield.bind("return", self.dolinefield)
208 self.linefield.bind("enter", self.dolinefield)
209 self.linefield.bind("tab", self.dolinefield)
210
211 # intercept clicks
212 editor.bind("<click>", self.clickeditor)
213 self.linefield.bind("<click>", self.clicklinefield)
214
215 def makeoptionsmenu(self):
Just van Rossumdc3c6172001-06-19 21:37:33 +0000216 menuitems = [('Font settings\xc9', self.domenu_fontsettings),
217 ("Save options\xc9", self.domenu_options),
Just van Rossum12710051999-02-27 17:18:30 +0000218 '-',
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000219 ('\0' + chr(self.run_as_main) + 'Run as __main__', self.domenu_toggle_run_as_main),
Jack Jansenff773eb2002-03-31 22:01:33 +0000220 #('\0' + chr(self.run_with_interpreter) + 'Run with Interpreter', self.domenu_dtoggle_run_with_interpreter),
221 ('\0' + chr(self.run_with_cl_interpreter) + 'Run with commandline Python', self.domenu_toggle_run_with_cl_interpreter),
222 '-',
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000223 ('Modularize', self.domenu_modularize),
Just van Rossumdc3c6172001-06-19 21:37:33 +0000224 ('Browse namespace\xc9', self.domenu_browsenamespace),
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000225 '-']
226 if self.profiling:
227 menuitems = menuitems + [('Disable profiler', self.domenu_toggleprofiler)]
228 else:
229 menuitems = menuitems + [('Enable profiler', self.domenu_toggleprofiler)]
230 if self.editgroup.editor._debugger:
231 menuitems = menuitems + [('Disable debugger', self.domenu_toggledebugger),
232 ('Clear breakpoints', self.domenu_clearbreakpoints),
Just van Rossumdc3c6172001-06-19 21:37:33 +0000233 ('Edit breakpoints\xc9', self.domenu_editbreakpoints)]
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000234 else:
235 menuitems = menuitems + [('Enable debugger', self.domenu_toggledebugger)]
236 self.editgroup.optionsmenu.set(menuitems)
237
238 def domenu_toggle_run_as_main(self):
239 self.run_as_main = not self.run_as_main
Just van Rossum0f2fd162000-10-20 06:36:30 +0000240 self.run_with_interpreter = 0
Jack Jansenff773eb2002-03-31 22:01:33 +0000241 self.run_with_cl_interpreter = 0
Just van Rossumf7f93882001-11-02 19:24:41 +0000242 self.editgroup.editor.selectionchanged()
Just van Rossum0f2fd162000-10-20 06:36:30 +0000243
Jack Jansenff773eb2002-03-31 22:01:33 +0000244 def XXdomenu_toggle_run_with_interpreter(self):
Just van Rossum0f2fd162000-10-20 06:36:30 +0000245 self.run_with_interpreter = not self.run_with_interpreter
246 self.run_as_main = 0
Jack Jansenff773eb2002-03-31 22:01:33 +0000247 self.run_with_cl_interpreter = 0
248 self.editgroup.editor.selectionchanged()
249
250 def domenu_toggle_run_with_cl_interpreter(self):
251 self.run_with_cl_interpreter = not self.run_with_cl_interpreter
252 self.run_as_main = 0
253 self.run_with_interpreter = 0
Just van Rossumf7f93882001-11-02 19:24:41 +0000254 self.editgroup.editor.selectionchanged()
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000255
256 def showbreakpoints(self, onoff):
257 self.editgroup.editor.showbreakpoints(onoff)
258 self.debugging = onoff
259
260 def domenu_clearbreakpoints(self, *args):
261 self.editgroup.editor.clearbreakpoints()
262
263 def domenu_editbreakpoints(self, *args):
264 self.editgroup.editor.editbreakpoints()
265
266 def domenu_toggledebugger(self, *args):
267 if not self.debugging:
268 W.SetCursor('watch')
269 self.debugging = not self.debugging
270 self.editgroup.editor.togglebreakpoints()
271
272 def domenu_toggleprofiler(self, *args):
273 self.profiling = not self.profiling
274
275 def domenu_browsenamespace(self, *args):
276 import PyBrowser, W
277 W.SetCursor('watch')
278 globals, file, modname = self.getenvironment()
279 if not modname:
280 modname = self.title
281 PyBrowser.Browser(globals, "Object browser: " + modname)
282
283 def domenu_modularize(self, *args):
284 modname = _filename_as_modname(self.title)
285 if not modname:
Just van Rossumdc3c6172001-06-19 21:37:33 +0000286 raise W.AlertError, "Can't modularize \"%s\"" % self.title
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000287 run_as_main = self.run_as_main
288 self.run_as_main = 0
289 self.run()
290 self.run_as_main = run_as_main
291 if self.path:
292 file = self.path
293 else:
294 file = self.title
295
296 if self.globals and not sys.modules.has_key(modname):
297 module = imp.new_module(modname)
298 for attr in self.globals.keys():
299 setattr(module,attr,self.globals[attr])
300 sys.modules[modname] = module
301 self.globals = {}
302
303 def domenu_fontsettings(self, *args):
304 import FontSettings
305 fontsettings = self.editgroup.editor.getfontsettings()
306 tabsettings = self.editgroup.editor.gettabsettings()
307 settings = FontSettings.FontDialog(fontsettings, tabsettings)
308 if settings:
309 fontsettings, tabsettings = settings
310 self.editgroup.editor.setfontsettings(fontsettings)
311 self.editgroup.editor.settabsettings(tabsettings)
312
Just van Rossum12710051999-02-27 17:18:30 +0000313 def domenu_options(self, *args):
Just van Rossumca3d3072002-03-29 21:48:42 +0000314 rv = SaveOptions(self._creator, self._eoln)
315 if rv:
Just van Rossumf7f93882001-11-02 19:24:41 +0000316 self.editgroup.editor.selectionchanged() # ouch...
Just van Rossumca3d3072002-03-29 21:48:42 +0000317 self._creator, self._eoln = rv
Just van Rossum12710051999-02-27 17:18:30 +0000318
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000319 def clicklinefield(self):
320 if self._currentwidget <> self.linefield:
321 self.linefield.select(1)
322 self.linefield.selectall()
323 return 1
324
325 def clickeditor(self):
326 if self._currentwidget <> self.editgroup.editor:
327 self.dolinefield()
328 return 1
329
330 def updateselection(self, force = 0):
331 sel = min(self.editgroup.editor.getselection())
332 lineno = self.editgroup.editor.offsettoline(sel)
333 if lineno <> self.lastlineno or force:
334 self.lastlineno = lineno
335 self.linefield.set(str(lineno + 1))
336 self.linefield.selview()
337
338 def dolinefield(self):
339 try:
340 lineno = string.atoi(self.linefield.get()) - 1
341 if lineno <> self.lastlineno:
342 self.editgroup.editor.selectline(lineno)
343 self.updateselection(1)
344 except:
345 self.updateselection(1)
346 self.editgroup.editor.select(1)
347
348 def setinfotext(self):
349 if not hasattr(self, 'infotext'):
350 return
351 if self.path:
352 self.infotext.set(self.path)
353 else:
354 self.infotext.set("")
355
356 def close(self):
357 if self.editgroup.editor.changed:
Just van Rossum25ddc632001-07-05 07:06:26 +0000358 Qd.InitCursor()
359 save = EasyDialogs.AskYesNoCancel('Save window "%s" before closing?' % self.title,
360 default=1, no="Don\xd5t save")
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000361 if save > 0:
362 if self.domenu_save():
363 return 1
364 elif save < 0:
365 return 1
Just van Rossum25ddc632001-07-05 07:06:26 +0000366 self.globals = None
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000367 W.Window.close(self)
368
369 def domenu_close(self, *args):
370 return self.close()
371
372 def domenu_save(self, *args):
373 if not self.path:
374 # Will call us recursively
375 return self.domenu_save_as()
376 data = self.editgroup.editor.get()
Jack Jansen9a389472002-03-29 21:26:04 +0000377 if self._eoln != '\r':
378 data = string.replace(data, '\r', self._eoln)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000379 fp = open(self.path, 'wb') # open file in binary mode, data has '\r' line-endings
380 fp.write(data)
381 fp.close()
Jack Jansene7ee17c2003-02-06 22:32:35 +0000382 MacOS.SetCreatorAndType(self.path, self._creator, 'TEXT')
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000383 self.getsettings()
384 self.writewindowsettings()
385 self.editgroup.editor.changed = 0
386 self.editgroup.editor.selchanged = 0
387 import linecache
388 if linecache.cache.has_key(self.path):
389 del linecache.cache[self.path]
390 import macostools
391 macostools.touched(self.path)
Jack Jansenc00b6d72003-02-25 15:08:02 +0000392 self.addrecentfile(self.path)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000393
394 def can_save(self, menuitem):
395 return self.editgroup.editor.changed or self.editgroup.editor.selchanged
396
397 def domenu_save_as(self, *args):
Jack Jansenfd0b00e2003-01-26 22:15:48 +0000398 path = EasyDialogs.AskFileForSave(message='Save as:', savedFileName=self.title)
399 if not path:
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000400 return 1
401 self.showbreakpoints(0)
Jack Jansenfd0b00e2003-01-26 22:15:48 +0000402 self.path = path
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000403 self.setinfotext()
404 self.title = os.path.split(self.path)[-1]
405 self.wid.SetWTitle(self.title)
406 self.domenu_save()
407 self.editgroup.editor.setfile(self.getfilename())
408 app = W.getapplication()
409 app.makeopenwindowsmenu()
410 if hasattr(app, 'makescriptsmenu'):
411 app = W.getapplication()
Jack Jansene7ee17c2003-02-06 22:32:35 +0000412 fsr, changed = app.scriptsfolder.FSResolveAlias(None)
413 path = fsr.as_pathname()
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000414 if path == self.path[:len(path)]:
415 W.getapplication().makescriptsmenu()
416
417 def domenu_save_as_applet(self, *args):
Just van Rossumdc3c6172001-06-19 21:37:33 +0000418 import buildtools
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000419
420 buildtools.DEBUG = 0 # ouch.
421
422 if self.title[-3:] == ".py":
423 destname = self.title[:-3]
424 else:
425 destname = self.title + ".applet"
Jack Jansenfd0b00e2003-01-26 22:15:48 +0000426 destname = EasyDialogs.AskFileForSave(message='Save as Applet:',
427 savedFileName=destname)
428 if not destname:
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000429 return 1
430 W.SetCursor("watch")
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000431 if self.path:
432 filename = self.path
433 if filename[-3:] == ".py":
434 rsrcname = filename[:-3] + '.rsrc'
435 else:
436 rsrcname = filename + '.rsrc'
437 else:
438 filename = self.title
439 rsrcname = ""
440
441 pytext = self.editgroup.editor.get()
442 pytext = string.split(pytext, '\r')
443 pytext = string.join(pytext, '\n') + '\n'
444 try:
445 code = compile(pytext, filename, "exec")
446 except (SyntaxError, EOFError):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000447 raise buildtools.BuildError, "Syntax error in script %r" % (filename,)
Jack Jansenc0452da2003-02-12 15:38:37 +0000448
449 import tempfile
450 tmpdir = tempfile.mkdtemp()
451
452 if filename[-3:] != ".py":
453 filename = filename + ".py"
454 filename = os.path.join(tmpdir, os.path.split(filename)[1])
455 fp = open(filename, "w")
456 fp.write(pytext)
457 fp.close()
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000458
459 # Try removing the output file
460 try:
461 os.remove(destname)
462 except os.error:
463 pass
464 template = buildtools.findtemplate()
Jack Jansen5bb97e62003-02-21 22:33:55 +0000465 buildtools.process(template, filename, destname, 1, rsrcname=rsrcname, progress=None)
Jack Jansenfd3e54c2003-02-16 21:28:51 +0000466 try:
467 os.remove(filename)
468 os.rmdir(tmpdir)
469 except os.error:
470 pass
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000471
472 def domenu_gotoline(self, *args):
473 self.linefield.selectall()
474 self.linefield.select(1)
475 self.linefield.selectall()
476
477 def domenu_selectline(self, *args):
478 self.editgroup.editor.expandselection()
479
480 def domenu_find(self, *args):
481 searchengine.show()
482
483 def domenu_entersearchstring(self, *args):
484 searchengine.setfindstring()
485
486 def domenu_replace(self, *args):
487 searchengine.replace()
488
489 def domenu_findnext(self, *args):
490 searchengine.findnext()
491
492 def domenu_replacefind(self, *args):
493 searchengine.replacefind()
494
495 def domenu_run(self, *args):
496 self.runbutton.push()
497
498 def domenu_runselection(self, *args):
499 self.runselbutton.push()
500
501 def run(self):
Just van Rossum476736e2003-05-09 08:33:58 +0000502 self._run()
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000503
504 def _run(self):
Just van Rossum0f2fd162000-10-20 06:36:30 +0000505 if self.run_with_interpreter:
506 if self.editgroup.editor.changed:
Just van Rossum2ad94192002-07-12 12:06:17 +0000507 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()
Jack Jansenff773eb2002-03-31 22:01:33 +0000517 elif self.run_with_cl_interpreter:
Jack Jansenff773eb2002-03-31 22:01:33 +0000518 if self.editgroup.editor.changed:
Just van Rossum2ad94192002-07-12 12:06:17 +0000519 Qd.InitCursor()
Jack Jansenff773eb2002-03-31 22:01:33 +0000520 save = EasyDialogs.AskYesNoCancel('Save "%s" before running?' % self.title, 1)
521 if save > 0:
522 if self.domenu_save():
523 return
524 elif save < 0:
525 return
526 if not self.path:
527 raise W.AlertError, "Can't run unsaved file"
528 self._run_with_cl_interpreter()
Just van Rossum0f2fd162000-10-20 06:36:30 +0000529 else:
530 pytext = self.editgroup.editor.get()
531 globals, file, modname = self.getenvironment()
532 self.execstring(pytext, globals, globals, file, modname)
533
534 def _run_with_interpreter(self):
535 interp_path = os.path.join(sys.exec_prefix, "PythonInterpreter")
536 if not os.path.exists(interp_path):
537 raise W.AlertError, "Can't find interpreter"
538 import findertools
539 XXX
Jack Jansenff773eb2002-03-31 22:01:33 +0000540
541 def _run_with_cl_interpreter(self):
542 import Terminal
543 interp_path = os.path.join(sys.exec_prefix, "bin", "python")
544 file_path = self.path
545 if not os.path.exists(interp_path):
Jack Jansene7ee17c2003-02-06 22:32:35 +0000546 # This "can happen" if we are running IDE under MacPython-OS9.
547 raise W.AlertError, "Can't find command-line Python"
Jack Jansenff773eb2002-03-31 22:01:33 +0000548 cmd = '"%s" "%s" ; exit' % (interp_path, file_path)
549 t = Terminal.Terminal()
550 t.do_script(with_command=cmd)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000551
552 def runselection(self):
Just van Rossum476736e2003-05-09 08:33:58 +0000553 self._runselection()
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000554
555 def _runselection(self):
Jack Jansenff773eb2002-03-31 22:01:33 +0000556 if self.run_with_interpreter or self.run_with_cl_interpreter:
Just van Rossum0f2fd162000-10-20 06:36:30 +0000557 raise W.AlertError, "Can't run selection with Interpreter"
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000558 globals, file, modname = self.getenvironment()
559 locals = globals
560 # select whole lines
561 self.editgroup.editor.expandselection()
562
563 # get lineno of first selected line
564 selstart, selend = self.editgroup.editor.getselection()
565 selstart, selend = min(selstart, selend), max(selstart, selend)
566 selfirstline = self.editgroup.editor.offsettoline(selstart)
567 alltext = self.editgroup.editor.get()
568 pytext = alltext[selstart:selend]
569 lines = string.split(pytext, '\r')
570 indent = getminindent(lines)
571 if indent == 1:
572 classname = ''
573 alllines = string.split(alltext, '\r')
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000574 for i in range(selfirstline - 1, -1, -1):
575 line = alllines[i]
576 if line[:6] == 'class ':
577 classname = string.split(string.strip(line[6:]))[0]
578 classend = identifieRE_match(classname)
579 if classend < 1:
Just van Rossumdc3c6172001-06-19 21:37:33 +0000580 raise W.AlertError, "Can't find a class."
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000581 classname = classname[:classend]
582 break
583 elif line and line[0] not in '\t#':
Just van Rossumdc3c6172001-06-19 21:37:33 +0000584 raise W.AlertError, "Can't find a class."
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000585 else:
Just van Rossumdc3c6172001-06-19 21:37:33 +0000586 raise W.AlertError, "Can't find a class."
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000587 if globals.has_key(classname):
Just van Rossum25ddc632001-07-05 07:06:26 +0000588 klass = globals[classname]
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000589 else:
Just van Rossumdc3c6172001-06-19 21:37:33 +0000590 raise W.AlertError, "Can't find class \"%s\"." % classname
Just van Rossum25ddc632001-07-05 07:06:26 +0000591 # add class def
592 pytext = ("class %s:\n" % classname) + pytext
593 selfirstline = selfirstline - 1
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000594 elif indent > 0:
Just van Rossumdc3c6172001-06-19 21:37:33 +0000595 raise W.AlertError, "Can't run indented code."
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000596
597 # add "newlines" to fool compile/exec:
598 # now a traceback will give the right line number
599 pytext = selfirstline * '\r' + pytext
600 self.execstring(pytext, globals, locals, file, modname)
Just van Rossum25ddc632001-07-05 07:06:26 +0000601 if indent == 1 and globals[classname] is not klass:
602 # update the class in place
603 klass.__dict__.update(globals[classname].__dict__)
604 globals[classname] = klass
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000605
606 def execstring(self, pytext, globals, locals, file, modname):
607 tracebackwindow.hide()
608 # update windows
609 W.getapplication().refreshwindows()
610 if self.run_as_main:
611 modname = "__main__"
612 if self.path:
613 dir = os.path.dirname(self.path)
614 savedir = os.getcwd()
615 os.chdir(dir)
Just van Rossuma61f4ac1999-02-01 16:34:08 +0000616 sys.path.insert(0, dir)
Just van Rossumeb64af92003-05-09 08:58:02 +0000617 self._scriptDone = False
618 if sys.platform == "darwin":
619 # On MacOSX, MacPython doesn't poll for command-period
620 # (cancel), so to enable the user to cancel a running
621 # script, we have to spawn a thread which does the
622 # polling. It will send a SIGINT to the main thread
623 # (in which the script is running) when the user types
624 # command-period.
625 from threading import Thread
626 t = Thread(target=self._userCancelledMonitor,
627 name="UserCancelledMonitor")
628 t.start()
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000629 try:
Just van Rossum5ef0e7c2003-05-09 08:27:33 +0000630 execstring(pytext, globals, locals, file, self.debugging,
631 modname, self.profiling)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000632 finally:
Just van Rossumeb64af92003-05-09 08:58:02 +0000633 self._scriptDone = True
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000634 if self.path:
635 os.chdir(savedir)
Just van Rossuma61f4ac1999-02-01 16:34:08 +0000636 del sys.path[0]
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000637
Just van Rossumeb64af92003-05-09 08:58:02 +0000638 def _userCancelledMonitor(self):
639 import time
640 from signal import SIGINT
641 while not self._scriptDone:
642 if Evt.CheckEventQueueForUserCancel():
643 # Send a SIGINT signal to ourselves.
644 # This gets delivered to the main thread,
645 # cancelling the running script.
646 os.kill(os.getpid(), SIGINT)
647 break
648 time.sleep(0.25)
649
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000650 def getenvironment(self):
651 if self.path:
652 file = self.path
653 dir = os.path.dirname(file)
654 # check if we're part of a package
655 modname = ""
656 while os.path.exists(os.path.join(dir, "__init__.py")):
657 dir, dirname = os.path.split(dir)
Just van Rossum2aaeb521999-02-05 21:58:25 +0000658 modname = dirname + '.' + modname
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000659 subname = _filename_as_modname(self.title)
Just van Rossumf7f93882001-11-02 19:24:41 +0000660 if subname is None:
661 return self.globals, file, None
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000662 if modname:
663 if subname == "__init__":
Just van Rossum2aaeb521999-02-05 21:58:25 +0000664 # strip trailing period
665 modname = modname[:-1]
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000666 else:
Just van Rossum2aaeb521999-02-05 21:58:25 +0000667 modname = modname + subname
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000668 else:
669 modname = subname
670 if sys.modules.has_key(modname):
671 globals = sys.modules[modname].__dict__
672 self.globals = {}
673 else:
674 globals = self.globals
Just van Rossum73efed22000-04-09 19:45:22 +0000675 modname = subname
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000676 else:
677 file = '<%s>' % self.title
678 globals = self.globals
679 modname = file
680 return globals, file, modname
681
682 def write(self, stuff):
683 """for use as stdout"""
684 self._buf = self._buf + stuff
685 if '\n' in self._buf:
686 self.flush()
687
688 def flush(self):
689 stuff = string.split(self._buf, '\n')
690 stuff = string.join(stuff, '\r')
691 end = self.editgroup.editor.ted.WEGetTextLength()
692 self.editgroup.editor.ted.WESetSelection(end, end)
693 self.editgroup.editor.ted.WEInsert(stuff, None, None)
694 self.editgroup.editor.updatescrollbars()
695 self._buf = ""
696 # ? optional:
697 #self.wid.SelectWindow()
698
699 def getclasslist(self):
700 from string import find, strip
Just van Rossum24073ea1999-12-23 15:46:57 +0000701 methodRE = re.compile(r"\r[ \t]+def ")
702 findMethod = methodRE.search
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000703 editor = self.editgroup.editor
704 text = editor.get()
705 list = []
706 append = list.append
707 functag = "func"
708 classtag = "class"
709 methodtag = "method"
710 pos = -1
711 if text[:4] == 'def ':
712 append((pos + 4, functag))
713 pos = 4
714 while 1:
715 pos = find(text, '\rdef ', pos + 1)
716 if pos < 0:
717 break
718 append((pos + 5, functag))
719 pos = -1
720 if text[:6] == 'class ':
721 append((pos + 6, classtag))
722 pos = 6
723 while 1:
724 pos = find(text, '\rclass ', pos + 1)
725 if pos < 0:
726 break
727 append((pos + 7, classtag))
728 pos = 0
729 while 1:
Just van Rossum24073ea1999-12-23 15:46:57 +0000730 m = findMethod(text, pos + 1)
731 if m is None:
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000732 break
Just van Rossum24073ea1999-12-23 15:46:57 +0000733 pos = m.regs[0][0]
734 #pos = find(text, '\r\tdef ', pos + 1)
735 append((m.regs[0][1], methodtag))
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000736 list.sort()
737 classlist = []
738 methodlistappend = None
739 offsetToLine = editor.ted.WEOffsetToLine
740 getLineRange = editor.ted.WEGetLineRange
741 append = classlist.append
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000742 for pos, tag in list:
743 lineno = offsetToLine(pos)
744 lineStart, lineEnd = getLineRange(lineno)
745 line = strip(text[pos:lineEnd])
746 line = line[:identifieRE_match(line)]
747 if tag is functag:
748 append(("def " + line, lineno + 1))
749 methodlistappend = None
750 elif tag is classtag:
751 append(["class " + line])
752 methodlistappend = classlist[-1].append
753 elif methodlistappend and tag is methodtag:
754 methodlistappend(("def " + line, lineno + 1))
755 return classlist
756
757 def popselectline(self, lineno):
758 self.editgroup.editor.selectline(lineno - 1)
759
760 def selectline(self, lineno, charoffset = 0):
761 self.editgroup.editor.selectline(lineno - 1, charoffset)
Jack Jansenc00b6d72003-02-25 15:08:02 +0000762
763 def addrecentfile(self, filename):
764 app = W.getapplication()
765 app.addrecentfile(filename)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000766
Just van Rossum12710051999-02-27 17:18:30 +0000767class _saveoptions:
768
Jack Jansen9a389472002-03-29 21:26:04 +0000769 def __init__(self, creator, eoln):
Just van Rossum12710051999-02-27 17:18:30 +0000770 self.rv = None
Jack Jansen9a389472002-03-29 21:26:04 +0000771 self.eoln = eoln
772 self.w = w = W.ModalDialog((260, 160), 'Save options')
Just van Rossum12710051999-02-27 17:18:30 +0000773 radiobuttons = []
774 w.label = W.TextBox((8, 8, 80, 18), "File creator:")
Just van Rossum3af507d1999-04-22 22:23:46 +0000775 w.ide_radio = W.RadioButton((8, 22, 160, 18), "This application", radiobuttons, self.ide_hit)
Jack Jansen9a389472002-03-29 21:26:04 +0000776 w.interp_radio = W.RadioButton((8, 42, 160, 18), "MacPython Interpreter", radiobuttons, self.interp_hit)
777 w.interpx_radio = W.RadioButton((8, 62, 160, 18), "OSX PythonW Interpreter", radiobuttons, self.interpx_hit)
778 w.other_radio = W.RadioButton((8, 82, 50, 18), "Other:", radiobuttons)
779 w.other_creator = W.EditText((62, 82, 40, 20), creator, self.otherselect)
780 w.none_radio = W.RadioButton((8, 102, 160, 18), "None", radiobuttons, self.none_hit)
Just van Rossum12710051999-02-27 17:18:30 +0000781 w.cancelbutton = W.Button((-180, -30, 80, 16), "Cancel", self.cancelbuttonhit)
782 w.okbutton = W.Button((-90, -30, 80, 16), "Done", self.okbuttonhit)
783 w.setdefaultbutton(w.okbutton)
784 if creator == 'Pyth':
785 w.interp_radio.set(1)
Just van Rossum3af507d1999-04-22 22:23:46 +0000786 elif creator == W._signature:
Just van Rossum12710051999-02-27 17:18:30 +0000787 w.ide_radio.set(1)
Jack Jansen9a389472002-03-29 21:26:04 +0000788 elif creator == 'PytX':
789 w.interpx_radio.set(1)
790 elif creator == '\0\0\0\0':
791 w.none_radio.set(1)
Just van Rossum12710051999-02-27 17:18:30 +0000792 else:
793 w.other_radio.set(1)
Jack Jansen9a389472002-03-29 21:26:04 +0000794
795 w.eolnlabel = W.TextBox((168, 8, 80, 18), "Newline style:")
796 radiobuttons = []
797 w.unix_radio = W.RadioButton((168, 22, 80, 18), "Unix", radiobuttons, self.unix_hit)
798 w.mac_radio = W.RadioButton((168, 42, 80, 18), "Macintosh", radiobuttons, self.mac_hit)
799 w.win_radio = W.RadioButton((168, 62, 80, 18), "Windows", radiobuttons, self.win_hit)
800 if self.eoln == '\n':
801 w.unix_radio.set(1)
802 elif self.eoln == '\r\n':
803 w.win_radio.set(1)
804 else:
805 w.mac_radio.set(1)
806
Just van Rossum12710051999-02-27 17:18:30 +0000807 w.bind("cmd.", w.cancelbutton.push)
808 w.open()
809
810 def ide_hit(self):
Just van Rossum3af507d1999-04-22 22:23:46 +0000811 self.w.other_creator.set(W._signature)
Just van Rossum12710051999-02-27 17:18:30 +0000812
813 def interp_hit(self):
814 self.w.other_creator.set("Pyth")
815
Jack Jansen9a389472002-03-29 21:26:04 +0000816 def interpx_hit(self):
817 self.w.other_creator.set("PytX")
818
819 def none_hit(self):
820 self.w.other_creator.set("\0\0\0\0")
821
Just van Rossum12710051999-02-27 17:18:30 +0000822 def otherselect(self, *args):
823 sel_from, sel_to = self.w.other_creator.getselection()
824 creator = self.w.other_creator.get()[:4]
825 creator = creator + " " * (4 - len(creator))
826 self.w.other_creator.set(creator)
827 self.w.other_creator.setselection(sel_from, sel_to)
828 self.w.other_radio.set(1)
829
Jack Jansen9a389472002-03-29 21:26:04 +0000830 def mac_hit(self):
831 self.eoln = '\r'
832
833 def unix_hit(self):
834 self.eoln = '\n'
835
836 def win_hit(self):
837 self.eoln = '\r\n'
838
Just van Rossum12710051999-02-27 17:18:30 +0000839 def cancelbuttonhit(self):
840 self.w.close()
841
842 def okbuttonhit(self):
Jack Jansen9a389472002-03-29 21:26:04 +0000843 self.rv = (self.w.other_creator.get()[:4], self.eoln)
Just van Rossum12710051999-02-27 17:18:30 +0000844 self.w.close()
845
846
Jack Jansen9a389472002-03-29 21:26:04 +0000847def SaveOptions(creator, eoln):
848 s = _saveoptions(creator, eoln)
Just van Rossum12710051999-02-27 17:18:30 +0000849 return s.rv
850
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000851
852def _escape(where, what) :
853 return string.join(string.split(where, what), '\\' + what)
854
855def _makewholewordpattern(word):
856 # first, escape special regex chars
Just van Rossum3eec7622001-07-10 19:25:40 +0000857 for esc in "\\[]()|.*^+$?":
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000858 word = _escape(word, esc)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000859 notwordcharspat = '[^' + _wordchars + ']'
Jack Jansen9ad27522001-02-21 13:54:31 +0000860 pattern = '(' + word + ')'
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000861 if word[0] in _wordchars:
862 pattern = notwordcharspat + pattern
863 if word[-1] in _wordchars:
864 pattern = pattern + notwordcharspat
Jack Jansen9ad27522001-02-21 13:54:31 +0000865 return re.compile(pattern)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000866
Just van Rossumf376ef02001-11-18 14:12:43 +0000867
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000868class SearchEngine:
869
870 def __init__(self):
871 self.visible = 0
872 self.w = None
873 self.parms = { "find": "",
874 "replace": "",
875 "wrap": 1,
876 "casesens": 1,
877 "wholeword": 1
878 }
879 import MacPrefs
880 prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath)
881 if prefs.searchengine:
882 self.parms["casesens"] = prefs.searchengine.casesens
883 self.parms["wrap"] = prefs.searchengine.wrap
884 self.parms["wholeword"] = prefs.searchengine.wholeword
885
886 def show(self):
887 self.visible = 1
888 if self.w:
889 self.w.wid.ShowWindow()
890 self.w.wid.SelectWindow()
891 self.w.find.edit.select(1)
892 self.w.find.edit.selectall()
893 return
894 self.w = W.Dialog((420, 150), "Find")
895
896 self.w.find = TitledEditText((10, 4, 300, 36), "Search for:")
897 self.w.replace = TitledEditText((10, 100, 300, 36), "Replace with:")
898
899 self.w.boxes = W.Group((10, 50, 300, 40))
900 self.w.boxes.casesens = W.CheckBox((0, 0, 100, 16), "Case sensitive")
901 self.w.boxes.wholeword = W.CheckBox((0, 20, 100, 16), "Whole word")
902 self.w.boxes.wrap = W.CheckBox((110, 0, 100, 16), "Wrap around")
903
904 self.buttons = [ ("Find", "cmdf", self.find),
905 ("Replace", "cmdr", self.replace),
906 ("Replace all", None, self.replaceall),
Just van Rossumdc3c6172001-06-19 21:37:33 +0000907 ("Don't find", "cmdd", self.dont),
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000908 ("Cancel", "cmd.", self.cancel)
909 ]
910 for i in range(len(self.buttons)):
911 bounds = -90, 22 + i * 24, 80, 16
912 title, shortcut, callback = self.buttons[i]
913 self.w[title] = W.Button(bounds, title, callback)
914 if shortcut:
915 self.w.bind(shortcut, self.w[title].push)
Just van Rossumdc3c6172001-06-19 21:37:33 +0000916 self.w.setdefaultbutton(self.w["Don't find"])
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000917 self.w.find.edit.bind("<key>", self.key)
918 self.w.bind("<activate>", self.activate)
919 self.w.bind("<close>", self.close)
920 self.w.open()
921 self.setparms()
922 self.w.find.edit.select(1)
923 self.w.find.edit.selectall()
924 self.checkbuttons()
925
926 def close(self):
927 self.hide()
928 return -1
929
930 def key(self, char, modifiers):
931 self.w.find.edit.key(char, modifiers)
932 self.checkbuttons()
933 return 1
934
935 def activate(self, onoff):
936 if onoff:
937 self.checkbuttons()
938
939 def checkbuttons(self):
940 editor = findeditor(self)
941 if editor:
942 if self.w.find.get():
943 for title, cmd, call in self.buttons[:-2]:
944 self.w[title].enable(1)
945 self.w.setdefaultbutton(self.w["Find"])
946 else:
947 for title, cmd, call in self.buttons[:-2]:
948 self.w[title].enable(0)
Just van Rossumdc3c6172001-06-19 21:37:33 +0000949 self.w.setdefaultbutton(self.w["Don't find"])
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000950 else:
951 for title, cmd, call in self.buttons[:-2]:
952 self.w[title].enable(0)
Just van Rossumdc3c6172001-06-19 21:37:33 +0000953 self.w.setdefaultbutton(self.w["Don't find"])
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000954
955 def find(self):
956 self.getparmsfromwindow()
957 if self.findnext():
958 self.hide()
959
960 def replace(self):
961 editor = findeditor(self)
962 if not editor:
963 return
964 if self.visible:
965 self.getparmsfromwindow()
966 text = editor.getselectedtext()
967 find = self.parms["find"]
968 if not self.parms["casesens"]:
969 find = string.lower(find)
970 text = string.lower(text)
971 if text == find:
972 self.hide()
973 editor.insert(self.parms["replace"])
974
975 def replaceall(self):
976 editor = findeditor(self)
977 if not editor:
978 return
979 if self.visible:
980 self.getparmsfromwindow()
981 W.SetCursor("watch")
982 find = self.parms["find"]
983 if not find:
984 return
985 findlen = len(find)
986 replace = self.parms["replace"]
987 replacelen = len(replace)
988 Text = editor.get()
989 if not self.parms["casesens"]:
990 find = string.lower(find)
991 text = string.lower(Text)
992 else:
993 text = Text
994 newtext = ""
995 pos = 0
996 counter = 0
997 while 1:
998 if self.parms["wholeword"]:
999 wholewordRE = _makewholewordpattern(find)
Jack Jansen9ad27522001-02-21 13:54:31 +00001000 match = wholewordRE.search(text, pos)
1001 if match:
1002 pos = match.start(1)
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001003 else:
1004 pos = -1
1005 else:
1006 pos = string.find(text, find, pos)
1007 if pos < 0:
1008 break
1009 counter = counter + 1
1010 text = text[:pos] + replace + text[pos + findlen:]
1011 Text = Text[:pos] + replace + Text[pos + findlen:]
1012 pos = pos + replacelen
1013 W.SetCursor("arrow")
1014 if counter:
1015 self.hide()
Jack Jansen5a6fdcd2001-08-25 12:15:04 +00001016 from Carbon import Res
Just van Rossumf7f93882001-11-02 19:24:41 +00001017 editor.textchanged()
1018 editor.selectionchanged()
Just van Rossum7b025512002-10-24 20:03:29 +00001019 editor.set(Text)
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001020 EasyDialogs.Message("Replaced %d occurrences" % counter)
1021
1022 def dont(self):
1023 self.getparmsfromwindow()
1024 self.hide()
1025
1026 def replacefind(self):
1027 self.replace()
1028 self.findnext()
1029
1030 def setfindstring(self):
1031 editor = findeditor(self)
1032 if not editor:
1033 return
1034 find = editor.getselectedtext()
1035 if not find:
1036 return
1037 self.parms["find"] = find
1038 if self.w:
1039 self.w.find.edit.set(self.parms["find"])
1040 self.w.find.edit.selectall()
1041
1042 def findnext(self):
1043 editor = findeditor(self)
1044 if not editor:
1045 return
1046 find = self.parms["find"]
1047 if not find:
1048 return
1049 text = editor.get()
1050 if not self.parms["casesens"]:
1051 find = string.lower(find)
1052 text = string.lower(text)
1053 selstart, selend = editor.getselection()
1054 selstart, selend = min(selstart, selend), max(selstart, selend)
1055 if self.parms["wholeword"]:
1056 wholewordRE = _makewholewordpattern(find)
Jack Jansen9ad27522001-02-21 13:54:31 +00001057 match = wholewordRE.search(text, selend)
1058 if match:
1059 pos = match.start(1)
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001060 else:
1061 pos = -1
1062 else:
1063 pos = string.find(text, find, selend)
1064 if pos >= 0:
1065 editor.setselection(pos, pos + len(find))
1066 return 1
1067 elif self.parms["wrap"]:
1068 if self.parms["wholeword"]:
Jack Jansen9ad27522001-02-21 13:54:31 +00001069 match = wholewordRE.search(text, 0)
1070 if match:
1071 pos = match.start(1)
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001072 else:
1073 pos = -1
1074 else:
1075 pos = string.find(text, find)
1076 if selstart > pos >= 0:
1077 editor.setselection(pos, pos + len(find))
1078 return 1
1079
1080 def setparms(self):
1081 for key, value in self.parms.items():
1082 try:
1083 self.w[key].set(value)
1084 except KeyError:
1085 self.w.boxes[key].set(value)
1086
1087 def getparmsfromwindow(self):
1088 if not self.w:
1089 return
1090 for key, value in self.parms.items():
1091 try:
1092 value = self.w[key].get()
1093 except KeyError:
1094 value = self.w.boxes[key].get()
1095 self.parms[key] = value
1096
1097 def cancel(self):
1098 self.hide()
1099 self.setparms()
1100
1101 def hide(self):
1102 if self.w:
1103 self.w.wid.HideWindow()
1104 self.visible = 0
1105
1106 def writeprefs(self):
1107 import MacPrefs
1108 self.getparmsfromwindow()
1109 prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath)
1110 prefs.searchengine.casesens = self.parms["casesens"]
1111 prefs.searchengine.wrap = self.parms["wrap"]
1112 prefs.searchengine.wholeword = self.parms["wholeword"]
1113 prefs.save()
1114
1115
1116class TitledEditText(W.Group):
1117
1118 def __init__(self, possize, title, text = ""):
1119 W.Group.__init__(self, possize)
1120 self.title = W.TextBox((0, 0, 0, 16), title)
1121 self.edit = W.EditText((0, 16, 0, 0), text)
1122
1123 def set(self, value):
1124 self.edit.set(value)
1125
1126 def get(self):
1127 return self.edit.get()
1128
1129
1130class ClassFinder(W.PopupWidget):
1131
1132 def click(self, point, modifiers):
1133 W.SetCursor("watch")
1134 self.set(self._parentwindow.getclasslist())
1135 W.PopupWidget.click(self, point, modifiers)
1136
1137
1138def getminindent(lines):
1139 indent = -1
1140 for line in lines:
1141 stripped = string.strip(line)
1142 if not stripped or stripped[0] == '#':
1143 continue
1144 if indent < 0 or line[:indent] <> indent * '\t':
1145 indent = 0
1146 for c in line:
1147 if c <> '\t':
1148 break
1149 indent = indent + 1
1150 return indent
1151
1152
1153def getoptionkey():
1154 return not not ord(Evt.GetKeys()[7]) & 0x04
1155
1156
1157def execstring(pytext, globals, locals, filename="<string>", debugging=0,
1158 modname="__main__", profiling=0):
1159 if debugging:
1160 import PyDebugger, bdb
1161 BdbQuit = bdb.BdbQuit
1162 else:
1163 BdbQuit = 'BdbQuitDummyException'
1164 pytext = string.split(pytext, '\r')
1165 pytext = string.join(pytext, '\n') + '\n'
1166 W.SetCursor("watch")
1167 globals['__name__'] = modname
1168 globals['__file__'] = filename
1169 sys.argv = [filename]
1170 try:
1171 code = compile(pytext, filename, "exec")
1172 except:
1173 # XXXX BAAAADDD.... We let tracebackwindow decide to treat SyntaxError
1174 # special. That's wrong because THIS case is special (could be literal
1175 # overflow!) and SyntaxError could mean we need a traceback (syntax error
1176 # in imported module!!!
1177 tracebackwindow.traceback(1, filename)
1178 return
1179 try:
1180 if debugging:
Just van Rossum5ef0e7c2003-05-09 08:27:33 +00001181 PyDebugger.startfromhere()
1182 else:
Jack Jansen815d2bf2002-01-21 23:00:52 +00001183 if hasattr(MacOS, 'EnableAppswitch'):
1184 MacOS.EnableAppswitch(0)
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001185 try:
1186 if profiling:
1187 import profile, ProfileBrowser
1188 p = profile.Profile()
1189 p.set_cmd(filename)
1190 try:
1191 p.runctx(code, globals, locals)
1192 finally:
1193 import pstats
1194
1195 stats = pstats.Stats(p)
1196 ProfileBrowser.ProfileBrowser(stats)
1197 else:
1198 exec code in globals, locals
1199 finally:
Just van Rossum5ef0e7c2003-05-09 08:27:33 +00001200 if hasattr(MacOS, 'EnableAppswitch'):
1201 MacOS.EnableAppswitch(-1)
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001202 except W.AlertError, detail:
1203 raise W.AlertError, detail
1204 except (KeyboardInterrupt, BdbQuit):
1205 pass
Just van Rossumf7f93882001-11-02 19:24:41 +00001206 except SystemExit, arg:
1207 if arg.code:
1208 sys.stderr.write("Script exited with status code: %s\n" % repr(arg.code))
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001209 except:
1210 if debugging:
1211 sys.settrace(None)
1212 PyDebugger.postmortem(sys.exc_type, sys.exc_value, sys.exc_traceback)
1213 return
1214 else:
1215 tracebackwindow.traceback(1, filename)
1216 if debugging:
1217 sys.settrace(None)
1218 PyDebugger.stop()
1219
1220
Just van Rossum3eec7622001-07-10 19:25:40 +00001221_identifieRE = re.compile(r"[A-Za-z_][A-Za-z_0-9]*")
Jack Jansen9ad27522001-02-21 13:54:31 +00001222
1223def identifieRE_match(str):
1224 match = _identifieRE.match(str)
1225 if not match:
1226 return -1
1227 return match.end()
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001228
1229def _filename_as_modname(fname):
1230 if fname[-3:] == '.py':
1231 modname = fname[:-3]
Jack Jansen9ad27522001-02-21 13:54:31 +00001232 match = _identifieRE.match(modname)
1233 if match and match.start() == 0 and match.end() == len(modname):
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001234 return string.join(string.split(modname, '.'), '_')
1235
1236def findeditor(topwindow, fromtop = 0):
Just van Rossum40144012002-02-04 12:52:44 +00001237 wid = MyFrontWindow()
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001238 if not fromtop:
1239 if topwindow.w and wid == topwindow.w.wid:
1240 wid = topwindow.w.wid.GetNextWindow()
1241 if not wid:
1242 return
1243 app = W.getapplication()
1244 if app._windows.has_key(wid): # KeyError otherwise can happen in RoboFog :-(
1245 window = W.getapplication()._windows[wid]
1246 else:
1247 return
1248 if not isinstance(window, Editor):
1249 return
1250 return window.editgroup.editor
1251
1252
1253class _EditorDefaultSettings:
1254
1255 def __init__(self):
1256 self.template = "%s, %d point"
1257 self.fontsettings, self.tabsettings, self.windowsize = geteditorprefs()
1258 self.w = W.Dialog((328, 120), "Editor default settings")
Just van Rossumdc3c6172001-06-19 21:37:33 +00001259 self.w.setfontbutton = W.Button((8, 8, 80, 16), "Set font\xc9", self.dofont)
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001260 self.w.fonttext = W.TextBox((98, 10, -8, 14), self.template % (self.fontsettings[0], self.fontsettings[2]))
1261
1262 self.w.picksizebutton = W.Button((8, 50, 80, 16), "Front window", self.picksize)
1263 self.w.xsizelabel = W.TextBox((98, 32, 40, 14), "Width:")
1264 self.w.ysizelabel = W.TextBox((148, 32, 40, 14), "Height:")
Walter Dörwald70a6b492004-02-12 17:35:32 +00001265 self.w.xsize = W.EditText((98, 48, 40, 20), repr(self.windowsize[0]))
1266 self.w.ysize = W.EditText((148, 48, 40, 20), repr(self.windowsize[1]))
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001267
1268 self.w.cancelbutton = W.Button((-180, -26, 80, 16), "Cancel", self.cancel)
1269 self.w.okbutton = W.Button((-90, -26, 80, 16), "Done", self.ok)
1270 self.w.setdefaultbutton(self.w.okbutton)
1271 self.w.bind('cmd.', self.w.cancelbutton.push)
1272 self.w.open()
1273
1274 def picksize(self):
1275 app = W.getapplication()
1276 editor = findeditor(self)
1277 if editor is not None:
1278 width, height = editor._parentwindow._bounds[2:]
Walter Dörwald70a6b492004-02-12 17:35:32 +00001279 self.w.xsize.set(repr(width))
1280 self.w.ysize.set(repr(height))
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001281 else:
1282 raise W.AlertError, "No edit window found"
1283
1284 def dofont(self):
1285 import FontSettings
1286 settings = FontSettings.FontDialog(self.fontsettings, self.tabsettings)
1287 if settings:
1288 self.fontsettings, self.tabsettings = settings
1289 sys.exc_traceback = None
1290 self.w.fonttext.set(self.template % (self.fontsettings[0], self.fontsettings[2]))
1291
1292 def close(self):
1293 self.w.close()
1294 del self.w
1295
1296 def cancel(self):
1297 self.close()
1298
1299 def ok(self):
1300 try:
1301 width = string.atoi(self.w.xsize.get())
1302 except:
1303 self.w.xsize.select(1)
1304 self.w.xsize.selectall()
1305 raise W.AlertError, "Bad number for window width"
1306 try:
1307 height = string.atoi(self.w.ysize.get())
1308 except:
1309 self.w.ysize.select(1)
1310 self.w.ysize.selectall()
1311 raise W.AlertError, "Bad number for window height"
1312 self.windowsize = width, height
1313 seteditorprefs(self.fontsettings, self.tabsettings, self.windowsize)
1314 self.close()
1315
1316def geteditorprefs():
1317 import MacPrefs
1318 prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath)
1319 try:
1320 fontsettings = prefs.pyedit.fontsettings
1321 tabsettings = prefs.pyedit.tabsettings
1322 windowsize = prefs.pyedit.windowsize
1323 except:
Just van Rossumf7f93882001-11-02 19:24:41 +00001324 fontsettings = prefs.pyedit.fontsettings = ("Geneva", 0, 10, (0, 0, 0))
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001325 tabsettings = prefs.pyedit.tabsettings = (8, 1)
1326 windowsize = prefs.pyedit.windowsize = (500, 250)
1327 sys.exc_traceback = None
1328 return fontsettings, tabsettings, windowsize
1329
1330def seteditorprefs(fontsettings, tabsettings, windowsize):
1331 import MacPrefs
1332 prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath)
1333 prefs.pyedit.fontsettings = fontsettings
1334 prefs.pyedit.tabsettings = tabsettings
1335 prefs.pyedit.windowsize = windowsize
1336 prefs.save()
1337
1338_defaultSettingsEditor = None
1339
1340def EditorDefaultSettings():
1341 global _defaultSettingsEditor
1342 if _defaultSettingsEditor is None or not hasattr(_defaultSettingsEditor, "w"):
1343 _defaultSettingsEditor = _EditorDefaultSettings()
1344 else:
1345 _defaultSettingsEditor.w.select()
1346
1347def resolvealiases(path):
1348 try:
Jack Jansene7ee17c2003-02-06 22:32:35 +00001349 fsr, d1, d2 = File.FSResolveAliasFile(path, 1)
1350 path = fsr.as_pathname()
1351 return path
1352 except (File.Error, ValueError), (error, str):
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001353 if error <> -120:
1354 raise
1355 dir, file = os.path.split(path)
1356 return os.path.join(resolvealiases(dir), file)
1357
1358searchengine = SearchEngine()
1359tracebackwindow = Wtraceback.TraceBack()