blob: e9e0f26f17df615c736874015b8cf87c9ac548f1 [file] [log] [blame]
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001"""A (less & less) simple Python editor"""
2
3import W
4import Wtraceback
5from Wkeys import *
6
Just van Rossum40f9b7b1999-01-30 22:39:17 +00007import MacOS
Jack Jansenfd0b00e2003-01-26 22:15:48 +00008import EasyDialogs
Jack Jansen5a6fdcd2001-08-25 12:15:04 +00009from Carbon import Win
10from Carbon import Res
11from Carbon import Evt
Just van Rossum2ad94192002-07-12 12:06:17 +000012from Carbon import Qd
Jack Jansene7ee17c2003-02-06 22:32:35 +000013from Carbon import File
Just van Rossum40f9b7b1999-01-30 22:39:17 +000014import os
15import imp
16import sys
17import string
18import marshal
Jack Jansen9ad27522001-02-21 13:54:31 +000019import re
Just van Rossum40f9b7b1999-01-30 22:39:17 +000020
Jack Jansene7ee17c2003-02-06 22:32:35 +000021smAllScripts = -3
22
Just van Rossum40144012002-02-04 12:52:44 +000023if hasattr(Win, "FrontNonFloatingWindow"):
24 MyFrontWindow = Win.FrontNonFloatingWindow
25else:
26 MyFrontWindow = Win.FrontWindow
27
28
Just van Rossum73efed22000-04-09 19:45:22 +000029try:
Just van Rossum0f2fd162000-10-20 06:36:30 +000030 import Wthreading
Just van Rossum73efed22000-04-09 19:45:22 +000031except ImportError:
Just van Rossum0f2fd162000-10-20 06:36:30 +000032 haveThreading = 0
33else:
34 haveThreading = Wthreading.haveThreading
Just van Rossum73efed22000-04-09 19:45:22 +000035
Just van Rossum40f9b7b1999-01-30 22:39:17 +000036_scriptuntitledcounter = 1
Fred Drake79e75e12001-07-20 19:05:50 +000037_wordchars = string.ascii_letters + string.digits + "_"
Just van Rossum40f9b7b1999-01-30 22:39:17 +000038
39
Just van Rossum73efed22000-04-09 19:45:22 +000040runButtonLabels = ["Run all", "Stop!"]
41runSelButtonLabels = ["Run selection", "Pause!", "Resume"]
42
43
Just van Rossum40f9b7b1999-01-30 22:39:17 +000044class Editor(W.Window):
45
46 def __init__(self, path = "", title = ""):
47 defaultfontsettings, defaulttabsettings, defaultwindowsize = geteditorprefs()
48 global _scriptuntitledcounter
49 if not path:
50 if title:
51 self.title = title
52 else:
53 self.title = "Untitled Script " + `_scriptuntitledcounter`
54 _scriptuntitledcounter = _scriptuntitledcounter + 1
55 text = ""
56 self._creator = W._signature
Jack Jansen9a389472002-03-29 21:26:04 +000057 self._eoln = os.linesep
Just van Rossum40f9b7b1999-01-30 22:39:17 +000058 elif os.path.exists(path):
59 path = resolvealiases(path)
60 dir, name = os.path.split(path)
61 self.title = name
62 f = open(path, "rb")
63 text = f.read()
64 f.close()
Jack Jansene7ee17c2003-02-06 22:32:35 +000065 self._creator, filetype = MacOS.GetCreatorAndType(path)
Just van Rossum40f9b7b1999-01-30 22:39:17 +000066 else:
67 raise IOError, "file '%s' does not exist" % path
68 self.path = path
69
Just van Rossumc7ba0801999-05-21 21:42:27 +000070 if '\n' in text:
Just van Rossumc7ba0801999-05-21 21:42:27 +000071 if string.find(text, '\r\n') >= 0:
Jack Jansen9a389472002-03-29 21:26:04 +000072 self._eoln = '\r\n'
Just van Rossumc7ba0801999-05-21 21:42:27 +000073 else:
Jack Jansen9a389472002-03-29 21:26:04 +000074 self._eoln = '\n'
75 text = string.replace(text, self._eoln, '\r')
76 change = 0
Just van Rossumc7ba0801999-05-21 21:42:27 +000077 else:
78 change = 0
Jack Jansen9a389472002-03-29 21:26:04 +000079 self._eoln = '\r'
Just van Rossumc7ba0801999-05-21 21:42:27 +000080
Just van Rossum40f9b7b1999-01-30 22:39:17 +000081 self.settings = {}
82 if self.path:
83 self.readwindowsettings()
84 if self.settings.has_key("windowbounds"):
85 bounds = self.settings["windowbounds"]
86 else:
87 bounds = defaultwindowsize
88 if self.settings.has_key("fontsettings"):
89 self.fontsettings = self.settings["fontsettings"]
90 else:
91 self.fontsettings = defaultfontsettings
92 if self.settings.has_key("tabsize"):
93 try:
94 self.tabsettings = (tabsize, tabmode) = self.settings["tabsize"]
95 except:
96 self.tabsettings = defaulttabsettings
97 else:
98 self.tabsettings = defaulttabsettings
Just van Rossum40f9b7b1999-01-30 22:39:17 +000099
Just van Rossumc7ba0801999-05-21 21:42:27 +0000100 W.Window.__init__(self, bounds, self.title, minsize = (330, 120), tabbable = 0)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000101 self.setupwidgets(text)
Just van Rossumc7ba0801999-05-21 21:42:27 +0000102 if change > 0:
Just van Rossumf7f93882001-11-02 19:24:41 +0000103 self.editgroup.editor.textchanged()
Just van Rossumc7ba0801999-05-21 21:42:27 +0000104
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000105 if self.settings.has_key("selection"):
106 selstart, selend = self.settings["selection"]
107 self.setselection(selstart, selend)
108 self.open()
109 self.setinfotext()
110 self.globals = {}
111 self._buf = "" # for write method
112 self.debugging = 0
113 self.profiling = 0
Jack Jansenff773eb2002-03-31 22:01:33 +0000114 self.run_as_main = self.settings.get("run_as_main", 0)
115 self.run_with_interpreter = self.settings.get("run_with_interpreter", 0)
116 self.run_with_cl_interpreter = self.settings.get("run_with_cl_interpreter", 0)
Just van Rossum73efed22000-04-09 19:45:22 +0000117 self._threadstate = (0, 0)
118 self._thread = None
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000119
120 def readwindowsettings(self):
121 try:
Jack Jansend13c3852000-06-20 21:59:25 +0000122 resref = Res.FSpOpenResFile(self.path, 1)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000123 except Res.Error:
124 return
125 try:
126 Res.UseResFile(resref)
127 data = Res.Get1Resource('PyWS', 128)
128 self.settings = marshal.loads(data.data)
129 except:
130 pass
131 Res.CloseResFile(resref)
132
133 def writewindowsettings(self):
134 try:
Jack Jansend13c3852000-06-20 21:59:25 +0000135 resref = Res.FSpOpenResFile(self.path, 3)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000136 except Res.Error:
Jack Jansene7ee17c2003-02-06 22:32:35 +0000137 Res.FSpCreateResFile(self.path, self._creator, 'TEXT', smAllScripts)
Jack Jansend13c3852000-06-20 21:59:25 +0000138 resref = Res.FSpOpenResFile(self.path, 3)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000139 try:
140 data = Res.Resource(marshal.dumps(self.settings))
141 Res.UseResFile(resref)
142 try:
143 temp = Res.Get1Resource('PyWS', 128)
144 temp.RemoveResource()
145 except Res.Error:
146 pass
147 data.AddResource('PyWS', 128, "window settings")
148 finally:
149 Res.UpdateResFile(resref)
150 Res.CloseResFile(resref)
151
152 def getsettings(self):
153 self.settings = {}
154 self.settings["windowbounds"] = self.getbounds()
155 self.settings["selection"] = self.getselection()
156 self.settings["fontsettings"] = self.editgroup.editor.getfontsettings()
157 self.settings["tabsize"] = self.editgroup.editor.gettabsettings()
158 self.settings["run_as_main"] = self.run_as_main
Just van Rossum0f2fd162000-10-20 06:36:30 +0000159 self.settings["run_with_interpreter"] = self.run_with_interpreter
Jack Jansenff773eb2002-03-31 22:01:33 +0000160 self.settings["run_with_cl_interpreter"] = self.run_with_cl_interpreter
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000161
162 def get(self):
163 return self.editgroup.editor.get()
164
165 def getselection(self):
166 return self.editgroup.editor.ted.WEGetSelection()
167
168 def setselection(self, selstart, selend):
169 self.editgroup.editor.setselection(selstart, selend)
170
171 def getfilename(self):
172 if self.path:
173 return self.path
174 return '<%s>' % self.title
175
176 def setupwidgets(self, text):
Just van Rossumf376ef02001-11-18 14:12:43 +0000177 topbarheight = 24
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000178 popfieldwidth = 80
179 self.lastlineno = None
180
181 # make an editor
182 self.editgroup = W.Group((0, topbarheight + 1, 0, 0))
183 editor = W.PyEditor((0, 0, -15,-15), text,
184 fontsettings = self.fontsettings,
185 tabsettings = self.tabsettings,
186 file = self.getfilename())
187
188 # make the widgets
189 self.popfield = ClassFinder((popfieldwidth - 17, -15, 16, 16), [], self.popselectline)
190 self.linefield = W.EditText((-1, -15, popfieldwidth - 15, 16), inset = (6, 1))
191 self.editgroup._barx = W.Scrollbar((popfieldwidth - 2, -15, -14, 16), editor.hscroll, max = 32767)
192 self.editgroup._bary = W.Scrollbar((-15, 14, 16, -14), editor.vscroll, max = 32767)
193 self.editgroup.editor = editor # add editor *after* scrollbars
194
195 self.editgroup.optionsmenu = W.PopupMenu((-15, -1, 16, 16), [])
196 self.editgroup.optionsmenu.bind('<click>', self.makeoptionsmenu)
197
198 self.bevelbox = W.BevelBox((0, 0, 0, topbarheight))
199 self.hline = W.HorizontalLine((0, topbarheight, 0, 0))
Just van Rossumf376ef02001-11-18 14:12:43 +0000200 self.infotext = W.TextBox((175, 6, -4, 14), backgroundcolor = (0xe000, 0xe000, 0xe000))
201 self.runbutton = W.BevelButton((6, 4, 80, 16), runButtonLabels[0], self.run)
202 self.runselbutton = W.BevelButton((90, 4, 80, 16), runSelButtonLabels[0], self.runselection)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000203
204 # bind some keys
205 editor.bind("cmdr", self.runbutton.push)
206 editor.bind("enter", self.runselbutton.push)
207 editor.bind("cmdj", self.domenu_gotoline)
208 editor.bind("cmdd", self.domenu_toggledebugger)
209 editor.bind("<idle>", self.updateselection)
210
211 editor.bind("cmde", searchengine.setfindstring)
212 editor.bind("cmdf", searchengine.show)
213 editor.bind("cmdg", searchengine.findnext)
214 editor.bind("cmdshiftr", searchengine.replace)
215 editor.bind("cmdt", searchengine.replacefind)
216
217 self.linefield.bind("return", self.dolinefield)
218 self.linefield.bind("enter", self.dolinefield)
219 self.linefield.bind("tab", self.dolinefield)
220
221 # intercept clicks
222 editor.bind("<click>", self.clickeditor)
223 self.linefield.bind("<click>", self.clicklinefield)
224
225 def makeoptionsmenu(self):
Just van Rossumdc3c6172001-06-19 21:37:33 +0000226 menuitems = [('Font settings\xc9', self.domenu_fontsettings),
227 ("Save options\xc9", self.domenu_options),
Just van Rossum12710051999-02-27 17:18:30 +0000228 '-',
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000229 ('\0' + chr(self.run_as_main) + 'Run as __main__', self.domenu_toggle_run_as_main),
Jack Jansenff773eb2002-03-31 22:01:33 +0000230 #('\0' + chr(self.run_with_interpreter) + 'Run with Interpreter', self.domenu_dtoggle_run_with_interpreter),
231 ('\0' + chr(self.run_with_cl_interpreter) + 'Run with commandline Python', self.domenu_toggle_run_with_cl_interpreter),
232 '-',
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000233 ('Modularize', self.domenu_modularize),
Just van Rossumdc3c6172001-06-19 21:37:33 +0000234 ('Browse namespace\xc9', self.domenu_browsenamespace),
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000235 '-']
236 if self.profiling:
237 menuitems = menuitems + [('Disable profiler', self.domenu_toggleprofiler)]
238 else:
239 menuitems = menuitems + [('Enable profiler', self.domenu_toggleprofiler)]
240 if self.editgroup.editor._debugger:
241 menuitems = menuitems + [('Disable debugger', self.domenu_toggledebugger),
242 ('Clear breakpoints', self.domenu_clearbreakpoints),
Just van Rossumdc3c6172001-06-19 21:37:33 +0000243 ('Edit breakpoints\xc9', self.domenu_editbreakpoints)]
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000244 else:
245 menuitems = menuitems + [('Enable debugger', self.domenu_toggledebugger)]
246 self.editgroup.optionsmenu.set(menuitems)
247
248 def domenu_toggle_run_as_main(self):
249 self.run_as_main = not self.run_as_main
Just van Rossum0f2fd162000-10-20 06:36:30 +0000250 self.run_with_interpreter = 0
Jack Jansenff773eb2002-03-31 22:01:33 +0000251 self.run_with_cl_interpreter = 0
Just van Rossumf7f93882001-11-02 19:24:41 +0000252 self.editgroup.editor.selectionchanged()
Just van Rossum0f2fd162000-10-20 06:36:30 +0000253
Jack Jansenff773eb2002-03-31 22:01:33 +0000254 def XXdomenu_toggle_run_with_interpreter(self):
Just van Rossum0f2fd162000-10-20 06:36:30 +0000255 self.run_with_interpreter = not self.run_with_interpreter
256 self.run_as_main = 0
Jack Jansenff773eb2002-03-31 22:01:33 +0000257 self.run_with_cl_interpreter = 0
258 self.editgroup.editor.selectionchanged()
259
260 def domenu_toggle_run_with_cl_interpreter(self):
261 self.run_with_cl_interpreter = not self.run_with_cl_interpreter
262 self.run_as_main = 0
263 self.run_with_interpreter = 0
Just van Rossumf7f93882001-11-02 19:24:41 +0000264 self.editgroup.editor.selectionchanged()
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000265
266 def showbreakpoints(self, onoff):
267 self.editgroup.editor.showbreakpoints(onoff)
268 self.debugging = onoff
269
270 def domenu_clearbreakpoints(self, *args):
271 self.editgroup.editor.clearbreakpoints()
272
273 def domenu_editbreakpoints(self, *args):
274 self.editgroup.editor.editbreakpoints()
275
276 def domenu_toggledebugger(self, *args):
277 if not self.debugging:
278 W.SetCursor('watch')
279 self.debugging = not self.debugging
280 self.editgroup.editor.togglebreakpoints()
281
282 def domenu_toggleprofiler(self, *args):
283 self.profiling = not self.profiling
284
285 def domenu_browsenamespace(self, *args):
286 import PyBrowser, W
287 W.SetCursor('watch')
288 globals, file, modname = self.getenvironment()
289 if not modname:
290 modname = self.title
291 PyBrowser.Browser(globals, "Object browser: " + modname)
292
293 def domenu_modularize(self, *args):
294 modname = _filename_as_modname(self.title)
295 if not modname:
Just van Rossumdc3c6172001-06-19 21:37:33 +0000296 raise W.AlertError, "Can't modularize \"%s\"" % self.title
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000297 run_as_main = self.run_as_main
298 self.run_as_main = 0
299 self.run()
300 self.run_as_main = run_as_main
301 if self.path:
302 file = self.path
303 else:
304 file = self.title
305
306 if self.globals and not sys.modules.has_key(modname):
307 module = imp.new_module(modname)
308 for attr in self.globals.keys():
309 setattr(module,attr,self.globals[attr])
310 sys.modules[modname] = module
311 self.globals = {}
312
313 def domenu_fontsettings(self, *args):
314 import FontSettings
315 fontsettings = self.editgroup.editor.getfontsettings()
316 tabsettings = self.editgroup.editor.gettabsettings()
317 settings = FontSettings.FontDialog(fontsettings, tabsettings)
318 if settings:
319 fontsettings, tabsettings = settings
320 self.editgroup.editor.setfontsettings(fontsettings)
321 self.editgroup.editor.settabsettings(tabsettings)
322
Just van Rossum12710051999-02-27 17:18:30 +0000323 def domenu_options(self, *args):
Just van Rossumca3d3072002-03-29 21:48:42 +0000324 rv = SaveOptions(self._creator, self._eoln)
325 if rv:
Just van Rossumf7f93882001-11-02 19:24:41 +0000326 self.editgroup.editor.selectionchanged() # ouch...
Just van Rossumca3d3072002-03-29 21:48:42 +0000327 self._creator, self._eoln = rv
Just van Rossum12710051999-02-27 17:18:30 +0000328
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000329 def clicklinefield(self):
330 if self._currentwidget <> self.linefield:
331 self.linefield.select(1)
332 self.linefield.selectall()
333 return 1
334
335 def clickeditor(self):
336 if self._currentwidget <> self.editgroup.editor:
337 self.dolinefield()
338 return 1
339
340 def updateselection(self, force = 0):
341 sel = min(self.editgroup.editor.getselection())
342 lineno = self.editgroup.editor.offsettoline(sel)
343 if lineno <> self.lastlineno or force:
344 self.lastlineno = lineno
345 self.linefield.set(str(lineno + 1))
346 self.linefield.selview()
347
348 def dolinefield(self):
349 try:
350 lineno = string.atoi(self.linefield.get()) - 1
351 if lineno <> self.lastlineno:
352 self.editgroup.editor.selectline(lineno)
353 self.updateselection(1)
354 except:
355 self.updateselection(1)
356 self.editgroup.editor.select(1)
357
358 def setinfotext(self):
359 if not hasattr(self, 'infotext'):
360 return
361 if self.path:
362 self.infotext.set(self.path)
363 else:
364 self.infotext.set("")
365
366 def close(self):
367 if self.editgroup.editor.changed:
Just van Rossum25ddc632001-07-05 07:06:26 +0000368 Qd.InitCursor()
369 save = EasyDialogs.AskYesNoCancel('Save window "%s" before closing?' % self.title,
370 default=1, no="Don\xd5t save")
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000371 if save > 0:
372 if self.domenu_save():
373 return 1
374 elif save < 0:
375 return 1
Just van Rossum25ddc632001-07-05 07:06:26 +0000376 self.globals = None
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000377 W.Window.close(self)
378
379 def domenu_close(self, *args):
380 return self.close()
381
382 def domenu_save(self, *args):
383 if not self.path:
384 # Will call us recursively
385 return self.domenu_save_as()
386 data = self.editgroup.editor.get()
Jack Jansen9a389472002-03-29 21:26:04 +0000387 if self._eoln != '\r':
388 data = string.replace(data, '\r', self._eoln)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000389 fp = open(self.path, 'wb') # open file in binary mode, data has '\r' line-endings
390 fp.write(data)
391 fp.close()
Jack Jansene7ee17c2003-02-06 22:32:35 +0000392 MacOS.SetCreatorAndType(self.path, self._creator, 'TEXT')
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000393 self.getsettings()
394 self.writewindowsettings()
395 self.editgroup.editor.changed = 0
396 self.editgroup.editor.selchanged = 0
397 import linecache
398 if linecache.cache.has_key(self.path):
399 del linecache.cache[self.path]
400 import macostools
401 macostools.touched(self.path)
402
403 def can_save(self, menuitem):
404 return self.editgroup.editor.changed or self.editgroup.editor.selchanged
405
406 def domenu_save_as(self, *args):
Jack Jansenfd0b00e2003-01-26 22:15:48 +0000407 path = EasyDialogs.AskFileForSave(message='Save as:', savedFileName=self.title)
408 if not path:
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000409 return 1
410 self.showbreakpoints(0)
Jack Jansenfd0b00e2003-01-26 22:15:48 +0000411 self.path = path
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000412 self.setinfotext()
413 self.title = os.path.split(self.path)[-1]
414 self.wid.SetWTitle(self.title)
415 self.domenu_save()
416 self.editgroup.editor.setfile(self.getfilename())
417 app = W.getapplication()
418 app.makeopenwindowsmenu()
419 if hasattr(app, 'makescriptsmenu'):
420 app = W.getapplication()
Jack Jansene7ee17c2003-02-06 22:32:35 +0000421 fsr, changed = app.scriptsfolder.FSResolveAlias(None)
422 path = fsr.as_pathname()
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000423 if path == self.path[:len(path)]:
424 W.getapplication().makescriptsmenu()
425
426 def domenu_save_as_applet(self, *args):
Just van Rossumdc3c6172001-06-19 21:37:33 +0000427 import buildtools
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000428
429 buildtools.DEBUG = 0 # ouch.
430
431 if self.title[-3:] == ".py":
432 destname = self.title[:-3]
433 else:
434 destname = self.title + ".applet"
Jack Jansenfd0b00e2003-01-26 22:15:48 +0000435 destname = EasyDialogs.AskFileForSave(message='Save as Applet:',
436 savedFileName=destname)
437 if not destname:
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000438 return 1
439 W.SetCursor("watch")
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000440 if self.path:
441 filename = self.path
442 if filename[-3:] == ".py":
443 rsrcname = filename[:-3] + '.rsrc'
444 else:
445 rsrcname = filename + '.rsrc'
446 else:
447 filename = self.title
448 rsrcname = ""
449
450 pytext = self.editgroup.editor.get()
451 pytext = string.split(pytext, '\r')
452 pytext = string.join(pytext, '\n') + '\n'
453 try:
454 code = compile(pytext, filename, "exec")
455 except (SyntaxError, EOFError):
456 raise buildtools.BuildError, "Syntax error in script %s" % `filename`
Jack Jansenc0452da2003-02-12 15:38:37 +0000457
458 import tempfile
459 tmpdir = tempfile.mkdtemp()
460
461 if filename[-3:] != ".py":
462 filename = filename + ".py"
463 filename = os.path.join(tmpdir, os.path.split(filename)[1])
464 fp = open(filename, "w")
465 fp.write(pytext)
466 fp.close()
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000467
468 # Try removing the output file
469 try:
470 os.remove(destname)
471 except os.error:
472 pass
473 template = buildtools.findtemplate()
Jack Jansenc0452da2003-02-12 15:38:37 +0000474 buildtools.process(template, filename, destname, rsrcname=rsrcname, progress=None)
Jack Jansenfd3e54c2003-02-16 21:28:51 +0000475 try:
476 os.remove(filename)
477 os.rmdir(tmpdir)
478 except os.error:
479 pass
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000480
481 def domenu_gotoline(self, *args):
482 self.linefield.selectall()
483 self.linefield.select(1)
484 self.linefield.selectall()
485
486 def domenu_selectline(self, *args):
487 self.editgroup.editor.expandselection()
488
489 def domenu_find(self, *args):
490 searchengine.show()
491
492 def domenu_entersearchstring(self, *args):
493 searchengine.setfindstring()
494
495 def domenu_replace(self, *args):
496 searchengine.replace()
497
498 def domenu_findnext(self, *args):
499 searchengine.findnext()
500
501 def domenu_replacefind(self, *args):
502 searchengine.replacefind()
503
504 def domenu_run(self, *args):
505 self.runbutton.push()
506
507 def domenu_runselection(self, *args):
508 self.runselbutton.push()
509
510 def run(self):
Just van Rossum73efed22000-04-09 19:45:22 +0000511 if self._threadstate == (0, 0):
512 self._run()
513 else:
Just van Rossum0f2fd162000-10-20 06:36:30 +0000514 lock = Wthreading.Lock()
515 lock.acquire()
516 self._thread.postException(KeyboardInterrupt)
517 if self._thread.isBlocked():
Just van Rossum73efed22000-04-09 19:45:22 +0000518 self._thread.start()
Just van Rossum0f2fd162000-10-20 06:36:30 +0000519 lock.release()
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000520
521 def _run(self):
Just van Rossum0f2fd162000-10-20 06:36:30 +0000522 if self.run_with_interpreter:
523 if self.editgroup.editor.changed:
Just van Rossum2ad94192002-07-12 12:06:17 +0000524 Qd.InitCursor()
Just van Rossumdc3c6172001-06-19 21:37:33 +0000525 save = EasyDialogs.AskYesNoCancel('Save "%s" before running?' % self.title, 1)
Just van Rossum0f2fd162000-10-20 06:36:30 +0000526 if save > 0:
527 if self.domenu_save():
528 return
529 elif save < 0:
530 return
531 if not self.path:
532 raise W.AlertError, "Can't run unsaved file"
533 self._run_with_interpreter()
Jack Jansenff773eb2002-03-31 22:01:33 +0000534 elif self.run_with_cl_interpreter:
Jack Jansenff773eb2002-03-31 22:01:33 +0000535 if self.editgroup.editor.changed:
Just van Rossum2ad94192002-07-12 12:06:17 +0000536 Qd.InitCursor()
Jack Jansenff773eb2002-03-31 22:01:33 +0000537 save = EasyDialogs.AskYesNoCancel('Save "%s" before running?' % self.title, 1)
538 if save > 0:
539 if self.domenu_save():
540 return
541 elif save < 0:
542 return
543 if not self.path:
544 raise W.AlertError, "Can't run unsaved file"
545 self._run_with_cl_interpreter()
Just van Rossum0f2fd162000-10-20 06:36:30 +0000546 else:
547 pytext = self.editgroup.editor.get()
548 globals, file, modname = self.getenvironment()
549 self.execstring(pytext, globals, globals, file, modname)
550
551 def _run_with_interpreter(self):
552 interp_path = os.path.join(sys.exec_prefix, "PythonInterpreter")
553 if not os.path.exists(interp_path):
554 raise W.AlertError, "Can't find interpreter"
555 import findertools
556 XXX
Jack Jansenff773eb2002-03-31 22:01:33 +0000557
558 def _run_with_cl_interpreter(self):
559 import Terminal
560 interp_path = os.path.join(sys.exec_prefix, "bin", "python")
561 file_path = self.path
562 if not os.path.exists(interp_path):
Jack Jansene7ee17c2003-02-06 22:32:35 +0000563 # This "can happen" if we are running IDE under MacPython-OS9.
564 raise W.AlertError, "Can't find command-line Python"
Jack Jansenff773eb2002-03-31 22:01:33 +0000565 cmd = '"%s" "%s" ; exit' % (interp_path, file_path)
566 t = Terminal.Terminal()
567 t.do_script(with_command=cmd)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000568
569 def runselection(self):
Just van Rossum73efed22000-04-09 19:45:22 +0000570 if self._threadstate == (0, 0):
571 self._runselection()
572 elif self._threadstate == (1, 1):
Just van Rossum0f2fd162000-10-20 06:36:30 +0000573 self._thread.block()
Just van Rossum73efed22000-04-09 19:45:22 +0000574 self.setthreadstate((1, 2))
575 elif self._threadstate == (1, 2):
576 self._thread.start()
577 self.setthreadstate((1, 1))
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000578
579 def _runselection(self):
Jack Jansenff773eb2002-03-31 22:01:33 +0000580 if self.run_with_interpreter or self.run_with_cl_interpreter:
Just van Rossum0f2fd162000-10-20 06:36:30 +0000581 raise W.AlertError, "Can't run selection with Interpreter"
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000582 globals, file, modname = self.getenvironment()
583 locals = globals
584 # select whole lines
585 self.editgroup.editor.expandselection()
586
587 # get lineno of first selected line
588 selstart, selend = self.editgroup.editor.getselection()
589 selstart, selend = min(selstart, selend), max(selstart, selend)
590 selfirstline = self.editgroup.editor.offsettoline(selstart)
591 alltext = self.editgroup.editor.get()
592 pytext = alltext[selstart:selend]
593 lines = string.split(pytext, '\r')
594 indent = getminindent(lines)
595 if indent == 1:
596 classname = ''
597 alllines = string.split(alltext, '\r')
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000598 for i in range(selfirstline - 1, -1, -1):
599 line = alllines[i]
600 if line[:6] == 'class ':
601 classname = string.split(string.strip(line[6:]))[0]
602 classend = identifieRE_match(classname)
603 if classend < 1:
Just van Rossumdc3c6172001-06-19 21:37:33 +0000604 raise W.AlertError, "Can't find a class."
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000605 classname = classname[:classend]
606 break
607 elif line and line[0] not in '\t#':
Just van Rossumdc3c6172001-06-19 21:37:33 +0000608 raise W.AlertError, "Can't find a class."
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000609 else:
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 if globals.has_key(classname):
Just van Rossum25ddc632001-07-05 07:06:26 +0000612 klass = globals[classname]
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000613 else:
Just van Rossumdc3c6172001-06-19 21:37:33 +0000614 raise W.AlertError, "Can't find class \"%s\"." % classname
Just van Rossum25ddc632001-07-05 07:06:26 +0000615 # add class def
616 pytext = ("class %s:\n" % classname) + pytext
617 selfirstline = selfirstline - 1
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000618 elif indent > 0:
Just van Rossumdc3c6172001-06-19 21:37:33 +0000619 raise W.AlertError, "Can't run indented code."
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000620
621 # add "newlines" to fool compile/exec:
622 # now a traceback will give the right line number
623 pytext = selfirstline * '\r' + pytext
624 self.execstring(pytext, globals, locals, file, modname)
Just van Rossum25ddc632001-07-05 07:06:26 +0000625 if indent == 1 and globals[classname] is not klass:
626 # update the class in place
627 klass.__dict__.update(globals[classname].__dict__)
628 globals[classname] = klass
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000629
Just van Rossum73efed22000-04-09 19:45:22 +0000630 def setthreadstate(self, state):
631 oldstate = self._threadstate
632 if oldstate[0] <> state[0]:
633 self.runbutton.settitle(runButtonLabels[state[0]])
634 if oldstate[1] <> state[1]:
635 self.runselbutton.settitle(runSelButtonLabels[state[1]])
636 self._threadstate = state
637
638 def _exec_threadwrapper(self, *args, **kwargs):
639 apply(execstring, args, kwargs)
640 self.setthreadstate((0, 0))
641 self._thread = None
642
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000643 def execstring(self, pytext, globals, locals, file, modname):
644 tracebackwindow.hide()
645 # update windows
646 W.getapplication().refreshwindows()
647 if self.run_as_main:
648 modname = "__main__"
649 if self.path:
650 dir = os.path.dirname(self.path)
651 savedir = os.getcwd()
652 os.chdir(dir)
Just van Rossuma61f4ac1999-02-01 16:34:08 +0000653 sys.path.insert(0, dir)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000654 else:
655 cwdindex = None
656 try:
Just van Rossum0f2fd162000-10-20 06:36:30 +0000657 if haveThreading:
658 self._thread = Wthreading.Thread(os.path.basename(file),
Just van Rossum73efed22000-04-09 19:45:22 +0000659 self._exec_threadwrapper, pytext, globals, locals, file, self.debugging,
660 modname, self.profiling)
661 self.setthreadstate((1, 1))
662 self._thread.start()
663 else:
664 execstring(pytext, globals, locals, file, self.debugging,
665 modname, self.profiling)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000666 finally:
667 if self.path:
668 os.chdir(savedir)
Just van Rossuma61f4ac1999-02-01 16:34:08 +0000669 del sys.path[0]
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000670
671 def getenvironment(self):
672 if self.path:
673 file = self.path
674 dir = os.path.dirname(file)
675 # check if we're part of a package
676 modname = ""
677 while os.path.exists(os.path.join(dir, "__init__.py")):
678 dir, dirname = os.path.split(dir)
Just van Rossum2aaeb521999-02-05 21:58:25 +0000679 modname = dirname + '.' + modname
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000680 subname = _filename_as_modname(self.title)
Just van Rossumf7f93882001-11-02 19:24:41 +0000681 if subname is None:
682 return self.globals, file, None
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000683 if modname:
684 if subname == "__init__":
Just van Rossum2aaeb521999-02-05 21:58:25 +0000685 # strip trailing period
686 modname = modname[:-1]
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000687 else:
Just van Rossum2aaeb521999-02-05 21:58:25 +0000688 modname = modname + subname
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000689 else:
690 modname = subname
691 if sys.modules.has_key(modname):
692 globals = sys.modules[modname].__dict__
693 self.globals = {}
694 else:
695 globals = self.globals
Just van Rossum73efed22000-04-09 19:45:22 +0000696 modname = subname
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000697 else:
698 file = '<%s>' % self.title
699 globals = self.globals
700 modname = file
701 return globals, file, modname
702
703 def write(self, stuff):
704 """for use as stdout"""
705 self._buf = self._buf + stuff
706 if '\n' in self._buf:
707 self.flush()
708
709 def flush(self):
710 stuff = string.split(self._buf, '\n')
711 stuff = string.join(stuff, '\r')
712 end = self.editgroup.editor.ted.WEGetTextLength()
713 self.editgroup.editor.ted.WESetSelection(end, end)
714 self.editgroup.editor.ted.WEInsert(stuff, None, None)
715 self.editgroup.editor.updatescrollbars()
716 self._buf = ""
717 # ? optional:
718 #self.wid.SelectWindow()
719
720 def getclasslist(self):
721 from string import find, strip
Just van Rossum24073ea1999-12-23 15:46:57 +0000722 methodRE = re.compile(r"\r[ \t]+def ")
723 findMethod = methodRE.search
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000724 editor = self.editgroup.editor
725 text = editor.get()
726 list = []
727 append = list.append
728 functag = "func"
729 classtag = "class"
730 methodtag = "method"
731 pos = -1
732 if text[:4] == 'def ':
733 append((pos + 4, functag))
734 pos = 4
735 while 1:
736 pos = find(text, '\rdef ', pos + 1)
737 if pos < 0:
738 break
739 append((pos + 5, functag))
740 pos = -1
741 if text[:6] == 'class ':
742 append((pos + 6, classtag))
743 pos = 6
744 while 1:
745 pos = find(text, '\rclass ', pos + 1)
746 if pos < 0:
747 break
748 append((pos + 7, classtag))
749 pos = 0
750 while 1:
Just van Rossum24073ea1999-12-23 15:46:57 +0000751 m = findMethod(text, pos + 1)
752 if m is None:
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000753 break
Just van Rossum24073ea1999-12-23 15:46:57 +0000754 pos = m.regs[0][0]
755 #pos = find(text, '\r\tdef ', pos + 1)
756 append((m.regs[0][1], methodtag))
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000757 list.sort()
758 classlist = []
759 methodlistappend = None
760 offsetToLine = editor.ted.WEOffsetToLine
761 getLineRange = editor.ted.WEGetLineRange
762 append = classlist.append
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000763 for pos, tag in list:
764 lineno = offsetToLine(pos)
765 lineStart, lineEnd = getLineRange(lineno)
766 line = strip(text[pos:lineEnd])
767 line = line[:identifieRE_match(line)]
768 if tag is functag:
769 append(("def " + line, lineno + 1))
770 methodlistappend = None
771 elif tag is classtag:
772 append(["class " + line])
773 methodlistappend = classlist[-1].append
774 elif methodlistappend and tag is methodtag:
775 methodlistappend(("def " + line, lineno + 1))
776 return classlist
777
778 def popselectline(self, lineno):
779 self.editgroup.editor.selectline(lineno - 1)
780
781 def selectline(self, lineno, charoffset = 0):
782 self.editgroup.editor.selectline(lineno - 1, charoffset)
783
Just van Rossum12710051999-02-27 17:18:30 +0000784class _saveoptions:
785
Jack Jansen9a389472002-03-29 21:26:04 +0000786 def __init__(self, creator, eoln):
Just van Rossum12710051999-02-27 17:18:30 +0000787 self.rv = None
Jack Jansen9a389472002-03-29 21:26:04 +0000788 self.eoln = eoln
789 self.w = w = W.ModalDialog((260, 160), 'Save options')
Just van Rossum12710051999-02-27 17:18:30 +0000790 radiobuttons = []
791 w.label = W.TextBox((8, 8, 80, 18), "File creator:")
Just van Rossum3af507d1999-04-22 22:23:46 +0000792 w.ide_radio = W.RadioButton((8, 22, 160, 18), "This application", radiobuttons, self.ide_hit)
Jack Jansen9a389472002-03-29 21:26:04 +0000793 w.interp_radio = W.RadioButton((8, 42, 160, 18), "MacPython Interpreter", radiobuttons, self.interp_hit)
794 w.interpx_radio = W.RadioButton((8, 62, 160, 18), "OSX PythonW Interpreter", radiobuttons, self.interpx_hit)
795 w.other_radio = W.RadioButton((8, 82, 50, 18), "Other:", radiobuttons)
796 w.other_creator = W.EditText((62, 82, 40, 20), creator, self.otherselect)
797 w.none_radio = W.RadioButton((8, 102, 160, 18), "None", radiobuttons, self.none_hit)
Just van Rossum12710051999-02-27 17:18:30 +0000798 w.cancelbutton = W.Button((-180, -30, 80, 16), "Cancel", self.cancelbuttonhit)
799 w.okbutton = W.Button((-90, -30, 80, 16), "Done", self.okbuttonhit)
800 w.setdefaultbutton(w.okbutton)
801 if creator == 'Pyth':
802 w.interp_radio.set(1)
Just van Rossum3af507d1999-04-22 22:23:46 +0000803 elif creator == W._signature:
Just van Rossum12710051999-02-27 17:18:30 +0000804 w.ide_radio.set(1)
Jack Jansen9a389472002-03-29 21:26:04 +0000805 elif creator == 'PytX':
806 w.interpx_radio.set(1)
807 elif creator == '\0\0\0\0':
808 w.none_radio.set(1)
Just van Rossum12710051999-02-27 17:18:30 +0000809 else:
810 w.other_radio.set(1)
Jack Jansen9a389472002-03-29 21:26:04 +0000811
812 w.eolnlabel = W.TextBox((168, 8, 80, 18), "Newline style:")
813 radiobuttons = []
814 w.unix_radio = W.RadioButton((168, 22, 80, 18), "Unix", radiobuttons, self.unix_hit)
815 w.mac_radio = W.RadioButton((168, 42, 80, 18), "Macintosh", radiobuttons, self.mac_hit)
816 w.win_radio = W.RadioButton((168, 62, 80, 18), "Windows", radiobuttons, self.win_hit)
817 if self.eoln == '\n':
818 w.unix_radio.set(1)
819 elif self.eoln == '\r\n':
820 w.win_radio.set(1)
821 else:
822 w.mac_radio.set(1)
823
Just van Rossum12710051999-02-27 17:18:30 +0000824 w.bind("cmd.", w.cancelbutton.push)
825 w.open()
826
827 def ide_hit(self):
Just van Rossum3af507d1999-04-22 22:23:46 +0000828 self.w.other_creator.set(W._signature)
Just van Rossum12710051999-02-27 17:18:30 +0000829
830 def interp_hit(self):
831 self.w.other_creator.set("Pyth")
832
Jack Jansen9a389472002-03-29 21:26:04 +0000833 def interpx_hit(self):
834 self.w.other_creator.set("PytX")
835
836 def none_hit(self):
837 self.w.other_creator.set("\0\0\0\0")
838
Just van Rossum12710051999-02-27 17:18:30 +0000839 def otherselect(self, *args):
840 sel_from, sel_to = self.w.other_creator.getselection()
841 creator = self.w.other_creator.get()[:4]
842 creator = creator + " " * (4 - len(creator))
843 self.w.other_creator.set(creator)
844 self.w.other_creator.setselection(sel_from, sel_to)
845 self.w.other_radio.set(1)
846
Jack Jansen9a389472002-03-29 21:26:04 +0000847 def mac_hit(self):
848 self.eoln = '\r'
849
850 def unix_hit(self):
851 self.eoln = '\n'
852
853 def win_hit(self):
854 self.eoln = '\r\n'
855
Just van Rossum12710051999-02-27 17:18:30 +0000856 def cancelbuttonhit(self):
857 self.w.close()
858
859 def okbuttonhit(self):
Jack Jansen9a389472002-03-29 21:26:04 +0000860 self.rv = (self.w.other_creator.get()[:4], self.eoln)
Just van Rossum12710051999-02-27 17:18:30 +0000861 self.w.close()
862
863
Jack Jansen9a389472002-03-29 21:26:04 +0000864def SaveOptions(creator, eoln):
865 s = _saveoptions(creator, eoln)
Just van Rossum12710051999-02-27 17:18:30 +0000866 return s.rv
867
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000868
869def _escape(where, what) :
870 return string.join(string.split(where, what), '\\' + what)
871
872def _makewholewordpattern(word):
873 # first, escape special regex chars
Just van Rossum3eec7622001-07-10 19:25:40 +0000874 for esc in "\\[]()|.*^+$?":
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000875 word = _escape(word, esc)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000876 notwordcharspat = '[^' + _wordchars + ']'
Jack Jansen9ad27522001-02-21 13:54:31 +0000877 pattern = '(' + word + ')'
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000878 if word[0] in _wordchars:
879 pattern = notwordcharspat + pattern
880 if word[-1] in _wordchars:
881 pattern = pattern + notwordcharspat
Jack Jansen9ad27522001-02-21 13:54:31 +0000882 return re.compile(pattern)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000883
Just van Rossumf376ef02001-11-18 14:12:43 +0000884
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000885class SearchEngine:
886
887 def __init__(self):
888 self.visible = 0
889 self.w = None
890 self.parms = { "find": "",
891 "replace": "",
892 "wrap": 1,
893 "casesens": 1,
894 "wholeword": 1
895 }
896 import MacPrefs
897 prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath)
898 if prefs.searchengine:
899 self.parms["casesens"] = prefs.searchengine.casesens
900 self.parms["wrap"] = prefs.searchengine.wrap
901 self.parms["wholeword"] = prefs.searchengine.wholeword
902
903 def show(self):
904 self.visible = 1
905 if self.w:
906 self.w.wid.ShowWindow()
907 self.w.wid.SelectWindow()
908 self.w.find.edit.select(1)
909 self.w.find.edit.selectall()
910 return
911 self.w = W.Dialog((420, 150), "Find")
912
913 self.w.find = TitledEditText((10, 4, 300, 36), "Search for:")
914 self.w.replace = TitledEditText((10, 100, 300, 36), "Replace with:")
915
916 self.w.boxes = W.Group((10, 50, 300, 40))
917 self.w.boxes.casesens = W.CheckBox((0, 0, 100, 16), "Case sensitive")
918 self.w.boxes.wholeword = W.CheckBox((0, 20, 100, 16), "Whole word")
919 self.w.boxes.wrap = W.CheckBox((110, 0, 100, 16), "Wrap around")
920
921 self.buttons = [ ("Find", "cmdf", self.find),
922 ("Replace", "cmdr", self.replace),
923 ("Replace all", None, self.replaceall),
Just van Rossumdc3c6172001-06-19 21:37:33 +0000924 ("Don't find", "cmdd", self.dont),
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000925 ("Cancel", "cmd.", self.cancel)
926 ]
927 for i in range(len(self.buttons)):
928 bounds = -90, 22 + i * 24, 80, 16
929 title, shortcut, callback = self.buttons[i]
930 self.w[title] = W.Button(bounds, title, callback)
931 if shortcut:
932 self.w.bind(shortcut, self.w[title].push)
Just van Rossumdc3c6172001-06-19 21:37:33 +0000933 self.w.setdefaultbutton(self.w["Don't find"])
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000934 self.w.find.edit.bind("<key>", self.key)
935 self.w.bind("<activate>", self.activate)
936 self.w.bind("<close>", self.close)
937 self.w.open()
938 self.setparms()
939 self.w.find.edit.select(1)
940 self.w.find.edit.selectall()
941 self.checkbuttons()
942
943 def close(self):
944 self.hide()
945 return -1
946
947 def key(self, char, modifiers):
948 self.w.find.edit.key(char, modifiers)
949 self.checkbuttons()
950 return 1
951
952 def activate(self, onoff):
953 if onoff:
954 self.checkbuttons()
955
956 def checkbuttons(self):
957 editor = findeditor(self)
958 if editor:
959 if self.w.find.get():
960 for title, cmd, call in self.buttons[:-2]:
961 self.w[title].enable(1)
962 self.w.setdefaultbutton(self.w["Find"])
963 else:
964 for title, cmd, call in self.buttons[:-2]:
965 self.w[title].enable(0)
Just van Rossumdc3c6172001-06-19 21:37:33 +0000966 self.w.setdefaultbutton(self.w["Don't find"])
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000967 else:
968 for title, cmd, call in self.buttons[:-2]:
969 self.w[title].enable(0)
Just van Rossumdc3c6172001-06-19 21:37:33 +0000970 self.w.setdefaultbutton(self.w["Don't find"])
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000971
972 def find(self):
973 self.getparmsfromwindow()
974 if self.findnext():
975 self.hide()
976
977 def replace(self):
978 editor = findeditor(self)
979 if not editor:
980 return
981 if self.visible:
982 self.getparmsfromwindow()
983 text = editor.getselectedtext()
984 find = self.parms["find"]
985 if not self.parms["casesens"]:
986 find = string.lower(find)
987 text = string.lower(text)
988 if text == find:
989 self.hide()
990 editor.insert(self.parms["replace"])
991
992 def replaceall(self):
993 editor = findeditor(self)
994 if not editor:
995 return
996 if self.visible:
997 self.getparmsfromwindow()
998 W.SetCursor("watch")
999 find = self.parms["find"]
1000 if not find:
1001 return
1002 findlen = len(find)
1003 replace = self.parms["replace"]
1004 replacelen = len(replace)
1005 Text = editor.get()
1006 if not self.parms["casesens"]:
1007 find = string.lower(find)
1008 text = string.lower(Text)
1009 else:
1010 text = Text
1011 newtext = ""
1012 pos = 0
1013 counter = 0
1014 while 1:
1015 if self.parms["wholeword"]:
1016 wholewordRE = _makewholewordpattern(find)
Jack Jansen9ad27522001-02-21 13:54:31 +00001017 match = wholewordRE.search(text, pos)
1018 if match:
1019 pos = match.start(1)
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001020 else:
1021 pos = -1
1022 else:
1023 pos = string.find(text, find, pos)
1024 if pos < 0:
1025 break
1026 counter = counter + 1
1027 text = text[:pos] + replace + text[pos + findlen:]
1028 Text = Text[:pos] + replace + Text[pos + findlen:]
1029 pos = pos + replacelen
1030 W.SetCursor("arrow")
1031 if counter:
1032 self.hide()
Jack Jansen5a6fdcd2001-08-25 12:15:04 +00001033 from Carbon import Res
Just van Rossumf7f93882001-11-02 19:24:41 +00001034 editor.textchanged()
1035 editor.selectionchanged()
Just van Rossum7b025512002-10-24 20:03:29 +00001036 editor.set(Text)
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001037 EasyDialogs.Message("Replaced %d occurrences" % counter)
1038
1039 def dont(self):
1040 self.getparmsfromwindow()
1041 self.hide()
1042
1043 def replacefind(self):
1044 self.replace()
1045 self.findnext()
1046
1047 def setfindstring(self):
1048 editor = findeditor(self)
1049 if not editor:
1050 return
1051 find = editor.getselectedtext()
1052 if not find:
1053 return
1054 self.parms["find"] = find
1055 if self.w:
1056 self.w.find.edit.set(self.parms["find"])
1057 self.w.find.edit.selectall()
1058
1059 def findnext(self):
1060 editor = findeditor(self)
1061 if not editor:
1062 return
1063 find = self.parms["find"]
1064 if not find:
1065 return
1066 text = editor.get()
1067 if not self.parms["casesens"]:
1068 find = string.lower(find)
1069 text = string.lower(text)
1070 selstart, selend = editor.getselection()
1071 selstart, selend = min(selstart, selend), max(selstart, selend)
1072 if self.parms["wholeword"]:
1073 wholewordRE = _makewholewordpattern(find)
Jack Jansen9ad27522001-02-21 13:54:31 +00001074 match = wholewordRE.search(text, selend)
1075 if match:
1076 pos = match.start(1)
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001077 else:
1078 pos = -1
1079 else:
1080 pos = string.find(text, find, selend)
1081 if pos >= 0:
1082 editor.setselection(pos, pos + len(find))
1083 return 1
1084 elif self.parms["wrap"]:
1085 if self.parms["wholeword"]:
Jack Jansen9ad27522001-02-21 13:54:31 +00001086 match = wholewordRE.search(text, 0)
1087 if match:
1088 pos = match.start(1)
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001089 else:
1090 pos = -1
1091 else:
1092 pos = string.find(text, find)
1093 if selstart > pos >= 0:
1094 editor.setselection(pos, pos + len(find))
1095 return 1
1096
1097 def setparms(self):
1098 for key, value in self.parms.items():
1099 try:
1100 self.w[key].set(value)
1101 except KeyError:
1102 self.w.boxes[key].set(value)
1103
1104 def getparmsfromwindow(self):
1105 if not self.w:
1106 return
1107 for key, value in self.parms.items():
1108 try:
1109 value = self.w[key].get()
1110 except KeyError:
1111 value = self.w.boxes[key].get()
1112 self.parms[key] = value
1113
1114 def cancel(self):
1115 self.hide()
1116 self.setparms()
1117
1118 def hide(self):
1119 if self.w:
1120 self.w.wid.HideWindow()
1121 self.visible = 0
1122
1123 def writeprefs(self):
1124 import MacPrefs
1125 self.getparmsfromwindow()
1126 prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath)
1127 prefs.searchengine.casesens = self.parms["casesens"]
1128 prefs.searchengine.wrap = self.parms["wrap"]
1129 prefs.searchengine.wholeword = self.parms["wholeword"]
1130 prefs.save()
1131
1132
1133class TitledEditText(W.Group):
1134
1135 def __init__(self, possize, title, text = ""):
1136 W.Group.__init__(self, possize)
1137 self.title = W.TextBox((0, 0, 0, 16), title)
1138 self.edit = W.EditText((0, 16, 0, 0), text)
1139
1140 def set(self, value):
1141 self.edit.set(value)
1142
1143 def get(self):
1144 return self.edit.get()
1145
1146
1147class ClassFinder(W.PopupWidget):
1148
1149 def click(self, point, modifiers):
1150 W.SetCursor("watch")
1151 self.set(self._parentwindow.getclasslist())
1152 W.PopupWidget.click(self, point, modifiers)
1153
1154
1155def getminindent(lines):
1156 indent = -1
1157 for line in lines:
1158 stripped = string.strip(line)
1159 if not stripped or stripped[0] == '#':
1160 continue
1161 if indent < 0 or line[:indent] <> indent * '\t':
1162 indent = 0
1163 for c in line:
1164 if c <> '\t':
1165 break
1166 indent = indent + 1
1167 return indent
1168
1169
1170def getoptionkey():
1171 return not not ord(Evt.GetKeys()[7]) & 0x04
1172
1173
1174def execstring(pytext, globals, locals, filename="<string>", debugging=0,
1175 modname="__main__", profiling=0):
1176 if debugging:
1177 import PyDebugger, bdb
1178 BdbQuit = bdb.BdbQuit
1179 else:
1180 BdbQuit = 'BdbQuitDummyException'
1181 pytext = string.split(pytext, '\r')
1182 pytext = string.join(pytext, '\n') + '\n'
1183 W.SetCursor("watch")
1184 globals['__name__'] = modname
1185 globals['__file__'] = filename
1186 sys.argv = [filename]
1187 try:
1188 code = compile(pytext, filename, "exec")
1189 except:
1190 # XXXX BAAAADDD.... We let tracebackwindow decide to treat SyntaxError
1191 # special. That's wrong because THIS case is special (could be literal
1192 # overflow!) and SyntaxError could mean we need a traceback (syntax error
1193 # in imported module!!!
1194 tracebackwindow.traceback(1, filename)
1195 return
1196 try:
1197 if debugging:
Just van Rossum0f2fd162000-10-20 06:36:30 +00001198 if haveThreading:
1199 lock = Wthreading.Lock()
1200 lock.acquire()
Just van Rossum73efed22000-04-09 19:45:22 +00001201 PyDebugger.startfromhere()
Just van Rossum0f2fd162000-10-20 06:36:30 +00001202 lock.release()
Just van Rossum73efed22000-04-09 19:45:22 +00001203 else:
1204 PyDebugger.startfromhere()
Just van Rossum0f2fd162000-10-20 06:36:30 +00001205 elif not haveThreading:
Jack Jansen815d2bf2002-01-21 23:00:52 +00001206 if hasattr(MacOS, 'EnableAppswitch'):
1207 MacOS.EnableAppswitch(0)
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001208 try:
1209 if profiling:
1210 import profile, ProfileBrowser
1211 p = profile.Profile()
1212 p.set_cmd(filename)
1213 try:
1214 p.runctx(code, globals, locals)
1215 finally:
1216 import pstats
1217
1218 stats = pstats.Stats(p)
1219 ProfileBrowser.ProfileBrowser(stats)
1220 else:
1221 exec code in globals, locals
1222 finally:
Just van Rossum0f2fd162000-10-20 06:36:30 +00001223 if not haveThreading:
Jack Jansen815d2bf2002-01-21 23:00:52 +00001224 if hasattr(MacOS, 'EnableAppswitch'):
1225 MacOS.EnableAppswitch(-1)
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001226 except W.AlertError, detail:
1227 raise W.AlertError, detail
1228 except (KeyboardInterrupt, BdbQuit):
1229 pass
Just van Rossumf7f93882001-11-02 19:24:41 +00001230 except SystemExit, arg:
1231 if arg.code:
1232 sys.stderr.write("Script exited with status code: %s\n" % repr(arg.code))
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001233 except:
Just van Rossum0f2fd162000-10-20 06:36:30 +00001234 if haveThreading:
1235 import continuation
1236 lock = Wthreading.Lock()
1237 lock.acquire()
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001238 if debugging:
1239 sys.settrace(None)
1240 PyDebugger.postmortem(sys.exc_type, sys.exc_value, sys.exc_traceback)
1241 return
1242 else:
1243 tracebackwindow.traceback(1, filename)
Just van Rossum0f2fd162000-10-20 06:36:30 +00001244 if haveThreading:
1245 lock.release()
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001246 if debugging:
1247 sys.settrace(None)
1248 PyDebugger.stop()
1249
1250
Just van Rossum3eec7622001-07-10 19:25:40 +00001251_identifieRE = re.compile(r"[A-Za-z_][A-Za-z_0-9]*")
Jack Jansen9ad27522001-02-21 13:54:31 +00001252
1253def identifieRE_match(str):
1254 match = _identifieRE.match(str)
1255 if not match:
1256 return -1
1257 return match.end()
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001258
1259def _filename_as_modname(fname):
1260 if fname[-3:] == '.py':
1261 modname = fname[:-3]
Jack Jansen9ad27522001-02-21 13:54:31 +00001262 match = _identifieRE.match(modname)
1263 if match and match.start() == 0 and match.end() == len(modname):
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001264 return string.join(string.split(modname, '.'), '_')
1265
1266def findeditor(topwindow, fromtop = 0):
Just van Rossum40144012002-02-04 12:52:44 +00001267 wid = MyFrontWindow()
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001268 if not fromtop:
1269 if topwindow.w and wid == topwindow.w.wid:
1270 wid = topwindow.w.wid.GetNextWindow()
1271 if not wid:
1272 return
1273 app = W.getapplication()
1274 if app._windows.has_key(wid): # KeyError otherwise can happen in RoboFog :-(
1275 window = W.getapplication()._windows[wid]
1276 else:
1277 return
1278 if not isinstance(window, Editor):
1279 return
1280 return window.editgroup.editor
1281
1282
1283class _EditorDefaultSettings:
1284
1285 def __init__(self):
1286 self.template = "%s, %d point"
1287 self.fontsettings, self.tabsettings, self.windowsize = geteditorprefs()
1288 self.w = W.Dialog((328, 120), "Editor default settings")
Just van Rossumdc3c6172001-06-19 21:37:33 +00001289 self.w.setfontbutton = W.Button((8, 8, 80, 16), "Set font\xc9", self.dofont)
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001290 self.w.fonttext = W.TextBox((98, 10, -8, 14), self.template % (self.fontsettings[0], self.fontsettings[2]))
1291
1292 self.w.picksizebutton = W.Button((8, 50, 80, 16), "Front window", self.picksize)
1293 self.w.xsizelabel = W.TextBox((98, 32, 40, 14), "Width:")
1294 self.w.ysizelabel = W.TextBox((148, 32, 40, 14), "Height:")
1295 self.w.xsize = W.EditText((98, 48, 40, 20), `self.windowsize[0]`)
1296 self.w.ysize = W.EditText((148, 48, 40, 20), `self.windowsize[1]`)
1297
1298 self.w.cancelbutton = W.Button((-180, -26, 80, 16), "Cancel", self.cancel)
1299 self.w.okbutton = W.Button((-90, -26, 80, 16), "Done", self.ok)
1300 self.w.setdefaultbutton(self.w.okbutton)
1301 self.w.bind('cmd.', self.w.cancelbutton.push)
1302 self.w.open()
1303
1304 def picksize(self):
1305 app = W.getapplication()
1306 editor = findeditor(self)
1307 if editor is not None:
1308 width, height = editor._parentwindow._bounds[2:]
1309 self.w.xsize.set(`width`)
1310 self.w.ysize.set(`height`)
1311 else:
1312 raise W.AlertError, "No edit window found"
1313
1314 def dofont(self):
1315 import FontSettings
1316 settings = FontSettings.FontDialog(self.fontsettings, self.tabsettings)
1317 if settings:
1318 self.fontsettings, self.tabsettings = settings
1319 sys.exc_traceback = None
1320 self.w.fonttext.set(self.template % (self.fontsettings[0], self.fontsettings[2]))
1321
1322 def close(self):
1323 self.w.close()
1324 del self.w
1325
1326 def cancel(self):
1327 self.close()
1328
1329 def ok(self):
1330 try:
1331 width = string.atoi(self.w.xsize.get())
1332 except:
1333 self.w.xsize.select(1)
1334 self.w.xsize.selectall()
1335 raise W.AlertError, "Bad number for window width"
1336 try:
1337 height = string.atoi(self.w.ysize.get())
1338 except:
1339 self.w.ysize.select(1)
1340 self.w.ysize.selectall()
1341 raise W.AlertError, "Bad number for window height"
1342 self.windowsize = width, height
1343 seteditorprefs(self.fontsettings, self.tabsettings, self.windowsize)
1344 self.close()
1345
1346def geteditorprefs():
1347 import MacPrefs
1348 prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath)
1349 try:
1350 fontsettings = prefs.pyedit.fontsettings
1351 tabsettings = prefs.pyedit.tabsettings
1352 windowsize = prefs.pyedit.windowsize
1353 except:
Just van Rossumf7f93882001-11-02 19:24:41 +00001354 fontsettings = prefs.pyedit.fontsettings = ("Geneva", 0, 10, (0, 0, 0))
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001355 tabsettings = prefs.pyedit.tabsettings = (8, 1)
1356 windowsize = prefs.pyedit.windowsize = (500, 250)
1357 sys.exc_traceback = None
1358 return fontsettings, tabsettings, windowsize
1359
1360def seteditorprefs(fontsettings, tabsettings, windowsize):
1361 import MacPrefs
1362 prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath)
1363 prefs.pyedit.fontsettings = fontsettings
1364 prefs.pyedit.tabsettings = tabsettings
1365 prefs.pyedit.windowsize = windowsize
1366 prefs.save()
1367
1368_defaultSettingsEditor = None
1369
1370def EditorDefaultSettings():
1371 global _defaultSettingsEditor
1372 if _defaultSettingsEditor is None or not hasattr(_defaultSettingsEditor, "w"):
1373 _defaultSettingsEditor = _EditorDefaultSettings()
1374 else:
1375 _defaultSettingsEditor.w.select()
1376
1377def resolvealiases(path):
1378 try:
Jack Jansene7ee17c2003-02-06 22:32:35 +00001379 fsr, d1, d2 = File.FSResolveAliasFile(path, 1)
1380 path = fsr.as_pathname()
1381 return path
1382 except (File.Error, ValueError), (error, str):
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001383 if error <> -120:
1384 raise
1385 dir, file = os.path.split(path)
1386 return os.path.join(resolvealiases(dir), file)
1387
1388searchengine = SearchEngine()
1389tracebackwindow = Wtraceback.TraceBack()