blob: 502f7c45bbbc9b2b36361a8dac83f03b5005bcd4 [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:
46 self.title = "Untitled Script " + `_scriptuntitledcounter`
47 _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 Rossum40f9b7b1999-01-30 22:39:17 +000060 else:
61 raise IOError, "file '%s' does not exist" % path
62 self.path = path
63
Just van Rossumc7ba0801999-05-21 21:42:27 +000064 if '\n' in text:
Just van Rossumc7ba0801999-05-21 21:42:27 +000065 if string.find(text, '\r\n') >= 0:
Jack Jansen9a389472002-03-29 21:26:04 +000066 self._eoln = '\r\n'
Just van Rossumc7ba0801999-05-21 21:42:27 +000067 else:
Jack Jansen9a389472002-03-29 21:26:04 +000068 self._eoln = '\n'
69 text = string.replace(text, self._eoln, '\r')
70 change = 0
Just van Rossumc7ba0801999-05-21 21:42:27 +000071 else:
72 change = 0
Jack Jansen9a389472002-03-29 21:26:04 +000073 self._eoln = '\r'
Just van Rossumc7ba0801999-05-21 21:42:27 +000074
Just van Rossum40f9b7b1999-01-30 22:39:17 +000075 self.settings = {}
76 if self.path:
77 self.readwindowsettings()
78 if self.settings.has_key("windowbounds"):
79 bounds = self.settings["windowbounds"]
80 else:
81 bounds = defaultwindowsize
82 if self.settings.has_key("fontsettings"):
83 self.fontsettings = self.settings["fontsettings"]
84 else:
85 self.fontsettings = defaultfontsettings
86 if self.settings.has_key("tabsize"):
87 try:
88 self.tabsettings = (tabsize, tabmode) = self.settings["tabsize"]
89 except:
90 self.tabsettings = defaulttabsettings
91 else:
92 self.tabsettings = defaulttabsettings
Just van Rossum40f9b7b1999-01-30 22:39:17 +000093
Just van Rossumc7ba0801999-05-21 21:42:27 +000094 W.Window.__init__(self, bounds, self.title, minsize = (330, 120), tabbable = 0)
Just van Rossum40f9b7b1999-01-30 22:39:17 +000095 self.setupwidgets(text)
Just van Rossumc7ba0801999-05-21 21:42:27 +000096 if change > 0:
Just van Rossumf7f93882001-11-02 19:24:41 +000097 self.editgroup.editor.textchanged()
Just van Rossumc7ba0801999-05-21 21:42:27 +000098
Just van Rossum40f9b7b1999-01-30 22:39:17 +000099 if self.settings.has_key("selection"):
100 selstart, selend = self.settings["selection"]
101 self.setselection(selstart, selend)
102 self.open()
103 self.setinfotext()
104 self.globals = {}
105 self._buf = "" # for write method
106 self.debugging = 0
107 self.profiling = 0
Jack Jansenff773eb2002-03-31 22:01:33 +0000108 self.run_as_main = self.settings.get("run_as_main", 0)
109 self.run_with_interpreter = self.settings.get("run_with_interpreter", 0)
110 self.run_with_cl_interpreter = self.settings.get("run_with_cl_interpreter", 0)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000111
112 def readwindowsettings(self):
113 try:
Jack Jansend13c3852000-06-20 21:59:25 +0000114 resref = Res.FSpOpenResFile(self.path, 1)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000115 except Res.Error:
116 return
117 try:
118 Res.UseResFile(resref)
119 data = Res.Get1Resource('PyWS', 128)
120 self.settings = marshal.loads(data.data)
121 except:
122 pass
123 Res.CloseResFile(resref)
124
125 def writewindowsettings(self):
126 try:
Jack Jansend13c3852000-06-20 21:59:25 +0000127 resref = Res.FSpOpenResFile(self.path, 3)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000128 except Res.Error:
Jack Jansene7ee17c2003-02-06 22:32:35 +0000129 Res.FSpCreateResFile(self.path, self._creator, 'TEXT', smAllScripts)
Jack Jansend13c3852000-06-20 21:59:25 +0000130 resref = Res.FSpOpenResFile(self.path, 3)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000131 try:
132 data = Res.Resource(marshal.dumps(self.settings))
133 Res.UseResFile(resref)
134 try:
135 temp = Res.Get1Resource('PyWS', 128)
136 temp.RemoveResource()
137 except Res.Error:
138 pass
139 data.AddResource('PyWS', 128, "window settings")
140 finally:
141 Res.UpdateResFile(resref)
142 Res.CloseResFile(resref)
143
144 def getsettings(self):
145 self.settings = {}
146 self.settings["windowbounds"] = self.getbounds()
147 self.settings["selection"] = self.getselection()
148 self.settings["fontsettings"] = self.editgroup.editor.getfontsettings()
149 self.settings["tabsize"] = self.editgroup.editor.gettabsettings()
150 self.settings["run_as_main"] = self.run_as_main
Just van Rossum0f2fd162000-10-20 06:36:30 +0000151 self.settings["run_with_interpreter"] = self.run_with_interpreter
Jack Jansenff773eb2002-03-31 22:01:33 +0000152 self.settings["run_with_cl_interpreter"] = self.run_with_cl_interpreter
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000153
154 def get(self):
155 return self.editgroup.editor.get()
156
157 def getselection(self):
158 return self.editgroup.editor.ted.WEGetSelection()
159
160 def setselection(self, selstart, selend):
161 self.editgroup.editor.setselection(selstart, selend)
Jack Jansen9a791822003-05-06 14:28:31 +0000162
163 def getselectedtext(self):
164 return self.editgroup.editor.getselectedtext()
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000165
166 def getfilename(self):
167 if self.path:
168 return self.path
169 return '<%s>' % self.title
170
171 def setupwidgets(self, text):
Just van Rossumf376ef02001-11-18 14:12:43 +0000172 topbarheight = 24
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000173 popfieldwidth = 80
174 self.lastlineno = None
175
176 # make an editor
177 self.editgroup = W.Group((0, topbarheight + 1, 0, 0))
178 editor = W.PyEditor((0, 0, -15,-15), text,
179 fontsettings = self.fontsettings,
180 tabsettings = self.tabsettings,
181 file = self.getfilename())
182
183 # make the widgets
184 self.popfield = ClassFinder((popfieldwidth - 17, -15, 16, 16), [], self.popselectline)
185 self.linefield = W.EditText((-1, -15, popfieldwidth - 15, 16), inset = (6, 1))
186 self.editgroup._barx = W.Scrollbar((popfieldwidth - 2, -15, -14, 16), editor.hscroll, max = 32767)
187 self.editgroup._bary = W.Scrollbar((-15, 14, 16, -14), editor.vscroll, max = 32767)
188 self.editgroup.editor = editor # add editor *after* scrollbars
189
190 self.editgroup.optionsmenu = W.PopupMenu((-15, -1, 16, 16), [])
191 self.editgroup.optionsmenu.bind('<click>', self.makeoptionsmenu)
192
193 self.bevelbox = W.BevelBox((0, 0, 0, topbarheight))
194 self.hline = W.HorizontalLine((0, topbarheight, 0, 0))
Just van Rossumf376ef02001-11-18 14:12:43 +0000195 self.infotext = W.TextBox((175, 6, -4, 14), backgroundcolor = (0xe000, 0xe000, 0xe000))
196 self.runbutton = W.BevelButton((6, 4, 80, 16), runButtonLabels[0], self.run)
197 self.runselbutton = W.BevelButton((90, 4, 80, 16), runSelButtonLabels[0], self.runselection)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000198
199 # bind some keys
200 editor.bind("cmdr", self.runbutton.push)
201 editor.bind("enter", self.runselbutton.push)
202 editor.bind("cmdj", self.domenu_gotoline)
203 editor.bind("cmdd", self.domenu_toggledebugger)
204 editor.bind("<idle>", self.updateselection)
205
206 editor.bind("cmde", searchengine.setfindstring)
207 editor.bind("cmdf", searchengine.show)
208 editor.bind("cmdg", searchengine.findnext)
209 editor.bind("cmdshiftr", searchengine.replace)
210 editor.bind("cmdt", searchengine.replacefind)
211
212 self.linefield.bind("return", self.dolinefield)
213 self.linefield.bind("enter", self.dolinefield)
214 self.linefield.bind("tab", self.dolinefield)
215
216 # intercept clicks
217 editor.bind("<click>", self.clickeditor)
218 self.linefield.bind("<click>", self.clicklinefield)
219
220 def makeoptionsmenu(self):
Just van Rossumdc3c6172001-06-19 21:37:33 +0000221 menuitems = [('Font settings\xc9', self.domenu_fontsettings),
222 ("Save options\xc9", self.domenu_options),
Just van Rossum12710051999-02-27 17:18:30 +0000223 '-',
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000224 ('\0' + chr(self.run_as_main) + 'Run as __main__', self.domenu_toggle_run_as_main),
Jack Jansenff773eb2002-03-31 22:01:33 +0000225 #('\0' + chr(self.run_with_interpreter) + 'Run with Interpreter', self.domenu_dtoggle_run_with_interpreter),
226 ('\0' + chr(self.run_with_cl_interpreter) + 'Run with commandline Python', self.domenu_toggle_run_with_cl_interpreter),
227 '-',
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000228 ('Modularize', self.domenu_modularize),
Just van Rossumdc3c6172001-06-19 21:37:33 +0000229 ('Browse namespace\xc9', self.domenu_browsenamespace),
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000230 '-']
231 if self.profiling:
232 menuitems = menuitems + [('Disable profiler', self.domenu_toggleprofiler)]
233 else:
234 menuitems = menuitems + [('Enable profiler', self.domenu_toggleprofiler)]
235 if self.editgroup.editor._debugger:
236 menuitems = menuitems + [('Disable debugger', self.domenu_toggledebugger),
237 ('Clear breakpoints', self.domenu_clearbreakpoints),
Just van Rossumdc3c6172001-06-19 21:37:33 +0000238 ('Edit breakpoints\xc9', self.domenu_editbreakpoints)]
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000239 else:
240 menuitems = menuitems + [('Enable debugger', self.domenu_toggledebugger)]
241 self.editgroup.optionsmenu.set(menuitems)
242
243 def domenu_toggle_run_as_main(self):
244 self.run_as_main = not self.run_as_main
Just van Rossum0f2fd162000-10-20 06:36:30 +0000245 self.run_with_interpreter = 0
Jack Jansenff773eb2002-03-31 22:01:33 +0000246 self.run_with_cl_interpreter = 0
Just van Rossumf7f93882001-11-02 19:24:41 +0000247 self.editgroup.editor.selectionchanged()
Just van Rossum0f2fd162000-10-20 06:36:30 +0000248
Jack Jansenff773eb2002-03-31 22:01:33 +0000249 def XXdomenu_toggle_run_with_interpreter(self):
Just van Rossum0f2fd162000-10-20 06:36:30 +0000250 self.run_with_interpreter = not self.run_with_interpreter
251 self.run_as_main = 0
Jack Jansenff773eb2002-03-31 22:01:33 +0000252 self.run_with_cl_interpreter = 0
253 self.editgroup.editor.selectionchanged()
254
255 def domenu_toggle_run_with_cl_interpreter(self):
256 self.run_with_cl_interpreter = not self.run_with_cl_interpreter
257 self.run_as_main = 0
258 self.run_with_interpreter = 0
Just van Rossumf7f93882001-11-02 19:24:41 +0000259 self.editgroup.editor.selectionchanged()
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000260
261 def showbreakpoints(self, onoff):
262 self.editgroup.editor.showbreakpoints(onoff)
263 self.debugging = onoff
264
265 def domenu_clearbreakpoints(self, *args):
266 self.editgroup.editor.clearbreakpoints()
267
268 def domenu_editbreakpoints(self, *args):
269 self.editgroup.editor.editbreakpoints()
270
271 def domenu_toggledebugger(self, *args):
272 if not self.debugging:
273 W.SetCursor('watch')
274 self.debugging = not self.debugging
275 self.editgroup.editor.togglebreakpoints()
276
277 def domenu_toggleprofiler(self, *args):
278 self.profiling = not self.profiling
279
280 def domenu_browsenamespace(self, *args):
281 import PyBrowser, W
282 W.SetCursor('watch')
283 globals, file, modname = self.getenvironment()
284 if not modname:
285 modname = self.title
286 PyBrowser.Browser(globals, "Object browser: " + modname)
287
288 def domenu_modularize(self, *args):
289 modname = _filename_as_modname(self.title)
290 if not modname:
Just van Rossumdc3c6172001-06-19 21:37:33 +0000291 raise W.AlertError, "Can't modularize \"%s\"" % self.title
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000292 run_as_main = self.run_as_main
293 self.run_as_main = 0
294 self.run()
295 self.run_as_main = run_as_main
296 if self.path:
297 file = self.path
298 else:
299 file = self.title
300
301 if self.globals and not sys.modules.has_key(modname):
302 module = imp.new_module(modname)
303 for attr in self.globals.keys():
304 setattr(module,attr,self.globals[attr])
305 sys.modules[modname] = module
306 self.globals = {}
307
308 def domenu_fontsettings(self, *args):
309 import FontSettings
310 fontsettings = self.editgroup.editor.getfontsettings()
311 tabsettings = self.editgroup.editor.gettabsettings()
312 settings = FontSettings.FontDialog(fontsettings, tabsettings)
313 if settings:
314 fontsettings, tabsettings = settings
315 self.editgroup.editor.setfontsettings(fontsettings)
316 self.editgroup.editor.settabsettings(tabsettings)
317
Just van Rossum12710051999-02-27 17:18:30 +0000318 def domenu_options(self, *args):
Just van Rossumca3d3072002-03-29 21:48:42 +0000319 rv = SaveOptions(self._creator, self._eoln)
320 if rv:
Just van Rossumf7f93882001-11-02 19:24:41 +0000321 self.editgroup.editor.selectionchanged() # ouch...
Just van Rossumca3d3072002-03-29 21:48:42 +0000322 self._creator, self._eoln = rv
Just van Rossum12710051999-02-27 17:18:30 +0000323
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000324 def clicklinefield(self):
325 if self._currentwidget <> self.linefield:
326 self.linefield.select(1)
327 self.linefield.selectall()
328 return 1
329
330 def clickeditor(self):
331 if self._currentwidget <> self.editgroup.editor:
332 self.dolinefield()
333 return 1
334
335 def updateselection(self, force = 0):
336 sel = min(self.editgroup.editor.getselection())
337 lineno = self.editgroup.editor.offsettoline(sel)
338 if lineno <> self.lastlineno or force:
339 self.lastlineno = lineno
340 self.linefield.set(str(lineno + 1))
341 self.linefield.selview()
342
343 def dolinefield(self):
344 try:
345 lineno = string.atoi(self.linefield.get()) - 1
346 if lineno <> self.lastlineno:
347 self.editgroup.editor.selectline(lineno)
348 self.updateselection(1)
349 except:
350 self.updateselection(1)
351 self.editgroup.editor.select(1)
352
353 def setinfotext(self):
354 if not hasattr(self, 'infotext'):
355 return
356 if self.path:
357 self.infotext.set(self.path)
358 else:
359 self.infotext.set("")
360
361 def close(self):
362 if self.editgroup.editor.changed:
Just van Rossum25ddc632001-07-05 07:06:26 +0000363 Qd.InitCursor()
364 save = EasyDialogs.AskYesNoCancel('Save window "%s" before closing?' % self.title,
365 default=1, no="Don\xd5t save")
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000366 if save > 0:
367 if self.domenu_save():
368 return 1
369 elif save < 0:
370 return 1
Just van Rossum25ddc632001-07-05 07:06:26 +0000371 self.globals = None
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000372 W.Window.close(self)
373
374 def domenu_close(self, *args):
375 return self.close()
376
377 def domenu_save(self, *args):
378 if not self.path:
379 # Will call us recursively
380 return self.domenu_save_as()
381 data = self.editgroup.editor.get()
Jack Jansen9a389472002-03-29 21:26:04 +0000382 if self._eoln != '\r':
383 data = string.replace(data, '\r', self._eoln)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000384 fp = open(self.path, 'wb') # open file in binary mode, data has '\r' line-endings
385 fp.write(data)
386 fp.close()
Jack Jansene7ee17c2003-02-06 22:32:35 +0000387 MacOS.SetCreatorAndType(self.path, self._creator, 'TEXT')
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000388 self.getsettings()
389 self.writewindowsettings()
390 self.editgroup.editor.changed = 0
391 self.editgroup.editor.selchanged = 0
392 import linecache
393 if linecache.cache.has_key(self.path):
394 del linecache.cache[self.path]
395 import macostools
396 macostools.touched(self.path)
Jack Jansenc00b6d72003-02-25 15:08:02 +0000397 self.addrecentfile(self.path)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000398
399 def can_save(self, menuitem):
400 return self.editgroup.editor.changed or self.editgroup.editor.selchanged
401
402 def domenu_save_as(self, *args):
Jack Jansenfd0b00e2003-01-26 22:15:48 +0000403 path = EasyDialogs.AskFileForSave(message='Save as:', savedFileName=self.title)
404 if not path:
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000405 return 1
406 self.showbreakpoints(0)
Jack Jansenfd0b00e2003-01-26 22:15:48 +0000407 self.path = path
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000408 self.setinfotext()
409 self.title = os.path.split(self.path)[-1]
410 self.wid.SetWTitle(self.title)
411 self.domenu_save()
412 self.editgroup.editor.setfile(self.getfilename())
413 app = W.getapplication()
414 app.makeopenwindowsmenu()
415 if hasattr(app, 'makescriptsmenu'):
416 app = W.getapplication()
Jack Jansene7ee17c2003-02-06 22:32:35 +0000417 fsr, changed = app.scriptsfolder.FSResolveAlias(None)
418 path = fsr.as_pathname()
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000419 if path == self.path[:len(path)]:
420 W.getapplication().makescriptsmenu()
421
422 def domenu_save_as_applet(self, *args):
Just van Rossumdc3c6172001-06-19 21:37:33 +0000423 import buildtools
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000424
425 buildtools.DEBUG = 0 # ouch.
426
427 if self.title[-3:] == ".py":
428 destname = self.title[:-3]
429 else:
430 destname = self.title + ".applet"
Jack Jansenfd0b00e2003-01-26 22:15:48 +0000431 destname = EasyDialogs.AskFileForSave(message='Save as Applet:',
432 savedFileName=destname)
433 if not destname:
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000434 return 1
435 W.SetCursor("watch")
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000436 if self.path:
437 filename = self.path
438 if filename[-3:] == ".py":
439 rsrcname = filename[:-3] + '.rsrc'
440 else:
441 rsrcname = filename + '.rsrc'
442 else:
443 filename = self.title
444 rsrcname = ""
445
446 pytext = self.editgroup.editor.get()
447 pytext = string.split(pytext, '\r')
448 pytext = string.join(pytext, '\n') + '\n'
449 try:
450 code = compile(pytext, filename, "exec")
451 except (SyntaxError, EOFError):
452 raise buildtools.BuildError, "Syntax error in script %s" % `filename`
Jack Jansenc0452da2003-02-12 15:38:37 +0000453
454 import tempfile
455 tmpdir = tempfile.mkdtemp()
456
457 if filename[-3:] != ".py":
458 filename = filename + ".py"
459 filename = os.path.join(tmpdir, os.path.split(filename)[1])
460 fp = open(filename, "w")
461 fp.write(pytext)
462 fp.close()
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000463
464 # Try removing the output file
465 try:
466 os.remove(destname)
467 except os.error:
468 pass
469 template = buildtools.findtemplate()
Jack Jansen5bb97e62003-02-21 22:33:55 +0000470 buildtools.process(template, filename, destname, 1, rsrcname=rsrcname, progress=None)
Jack Jansenfd3e54c2003-02-16 21:28:51 +0000471 try:
472 os.remove(filename)
473 os.rmdir(tmpdir)
474 except os.error:
475 pass
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000476
477 def domenu_gotoline(self, *args):
478 self.linefield.selectall()
479 self.linefield.select(1)
480 self.linefield.selectall()
481
482 def domenu_selectline(self, *args):
483 self.editgroup.editor.expandselection()
484
485 def domenu_find(self, *args):
486 searchengine.show()
487
488 def domenu_entersearchstring(self, *args):
489 searchengine.setfindstring()
490
491 def domenu_replace(self, *args):
492 searchengine.replace()
493
494 def domenu_findnext(self, *args):
495 searchengine.findnext()
496
497 def domenu_replacefind(self, *args):
498 searchengine.replacefind()
499
500 def domenu_run(self, *args):
501 self.runbutton.push()
502
503 def domenu_runselection(self, *args):
504 self.runselbutton.push()
505
506 def run(self):
Just van Rossum476736e2003-05-09 08:33:58 +0000507 self._run()
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000508
509 def _run(self):
Just van Rossum0f2fd162000-10-20 06:36:30 +0000510 if self.run_with_interpreter:
511 if self.editgroup.editor.changed:
Just van Rossum2ad94192002-07-12 12:06:17 +0000512 Qd.InitCursor()
Just van Rossumdc3c6172001-06-19 21:37:33 +0000513 save = EasyDialogs.AskYesNoCancel('Save "%s" before running?' % self.title, 1)
Just van Rossum0f2fd162000-10-20 06:36:30 +0000514 if save > 0:
515 if self.domenu_save():
516 return
517 elif save < 0:
518 return
519 if not self.path:
520 raise W.AlertError, "Can't run unsaved file"
521 self._run_with_interpreter()
Jack Jansenff773eb2002-03-31 22:01:33 +0000522 elif self.run_with_cl_interpreter:
Jack Jansenff773eb2002-03-31 22:01:33 +0000523 if self.editgroup.editor.changed:
Just van Rossum2ad94192002-07-12 12:06:17 +0000524 Qd.InitCursor()
Jack Jansenff773eb2002-03-31 22:01:33 +0000525 save = EasyDialogs.AskYesNoCancel('Save "%s" before running?' % self.title, 1)
526 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_cl_interpreter()
Just van Rossum0f2fd162000-10-20 06:36:30 +0000534 else:
535 pytext = self.editgroup.editor.get()
536 globals, file, modname = self.getenvironment()
537 self.execstring(pytext, globals, globals, file, modname)
538
539 def _run_with_interpreter(self):
540 interp_path = os.path.join(sys.exec_prefix, "PythonInterpreter")
541 if not os.path.exists(interp_path):
542 raise W.AlertError, "Can't find interpreter"
543 import findertools
544 XXX
Jack Jansenff773eb2002-03-31 22:01:33 +0000545
546 def _run_with_cl_interpreter(self):
547 import Terminal
548 interp_path = os.path.join(sys.exec_prefix, "bin", "python")
549 file_path = self.path
550 if not os.path.exists(interp_path):
Jack Jansene7ee17c2003-02-06 22:32:35 +0000551 # This "can happen" if we are running IDE under MacPython-OS9.
552 raise W.AlertError, "Can't find command-line Python"
Jack Jansenff773eb2002-03-31 22:01:33 +0000553 cmd = '"%s" "%s" ; exit' % (interp_path, file_path)
554 t = Terminal.Terminal()
555 t.do_script(with_command=cmd)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000556
557 def runselection(self):
Just van Rossum476736e2003-05-09 08:33:58 +0000558 self._runselection()
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000559
560 def _runselection(self):
Jack Jansenff773eb2002-03-31 22:01:33 +0000561 if self.run_with_interpreter or self.run_with_cl_interpreter:
Just van Rossum0f2fd162000-10-20 06:36:30 +0000562 raise W.AlertError, "Can't run selection with Interpreter"
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000563 globals, file, modname = self.getenvironment()
564 locals = globals
565 # select whole lines
566 self.editgroup.editor.expandselection()
567
568 # get lineno of first selected line
569 selstart, selend = self.editgroup.editor.getselection()
570 selstart, selend = min(selstart, selend), max(selstart, selend)
571 selfirstline = self.editgroup.editor.offsettoline(selstart)
572 alltext = self.editgroup.editor.get()
573 pytext = alltext[selstart:selend]
574 lines = string.split(pytext, '\r')
575 indent = getminindent(lines)
576 if indent == 1:
577 classname = ''
578 alllines = string.split(alltext, '\r')
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000579 for i in range(selfirstline - 1, -1, -1):
580 line = alllines[i]
581 if line[:6] == 'class ':
582 classname = string.split(string.strip(line[6:]))[0]
583 classend = identifieRE_match(classname)
584 if classend < 1:
Just van Rossumdc3c6172001-06-19 21:37:33 +0000585 raise W.AlertError, "Can't find a class."
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000586 classname = classname[:classend]
587 break
588 elif line and line[0] not in '\t#':
Just van Rossumdc3c6172001-06-19 21:37:33 +0000589 raise W.AlertError, "Can't find a class."
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000590 else:
Just van Rossumdc3c6172001-06-19 21:37:33 +0000591 raise W.AlertError, "Can't find a class."
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000592 if globals.has_key(classname):
Just van Rossum25ddc632001-07-05 07:06:26 +0000593 klass = globals[classname]
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000594 else:
Just van Rossumdc3c6172001-06-19 21:37:33 +0000595 raise W.AlertError, "Can't find class \"%s\"." % classname
Just van Rossum25ddc632001-07-05 07:06:26 +0000596 # add class def
597 pytext = ("class %s:\n" % classname) + pytext
598 selfirstline = selfirstline - 1
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000599 elif indent > 0:
Just van Rossumdc3c6172001-06-19 21:37:33 +0000600 raise W.AlertError, "Can't run indented code."
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000601
602 # add "newlines" to fool compile/exec:
603 # now a traceback will give the right line number
604 pytext = selfirstline * '\r' + pytext
605 self.execstring(pytext, globals, locals, file, modname)
Just van Rossum25ddc632001-07-05 07:06:26 +0000606 if indent == 1 and globals[classname] is not klass:
607 # update the class in place
608 klass.__dict__.update(globals[classname].__dict__)
609 globals[classname] = klass
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000610
611 def execstring(self, pytext, globals, locals, file, modname):
612 tracebackwindow.hide()
613 # update windows
614 W.getapplication().refreshwindows()
615 if self.run_as_main:
616 modname = "__main__"
617 if self.path:
618 dir = os.path.dirname(self.path)
619 savedir = os.getcwd()
620 os.chdir(dir)
Just van Rossuma61f4ac1999-02-01 16:34:08 +0000621 sys.path.insert(0, dir)
Just van Rossumeb64af92003-05-09 08:58:02 +0000622 self._scriptDone = False
623 if sys.platform == "darwin":
624 # On MacOSX, MacPython doesn't poll for command-period
625 # (cancel), so to enable the user to cancel a running
626 # script, we have to spawn a thread which does the
627 # polling. It will send a SIGINT to the main thread
628 # (in which the script is running) when the user types
629 # command-period.
630 from threading import Thread
631 t = Thread(target=self._userCancelledMonitor,
632 name="UserCancelledMonitor")
633 t.start()
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000634 try:
Just van Rossum5ef0e7c2003-05-09 08:27:33 +0000635 execstring(pytext, globals, locals, file, self.debugging,
636 modname, self.profiling)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000637 finally:
Just van Rossumeb64af92003-05-09 08:58:02 +0000638 self._scriptDone = True
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000639 if self.path:
640 os.chdir(savedir)
Just van Rossuma61f4ac1999-02-01 16:34:08 +0000641 del sys.path[0]
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000642
Just van Rossumeb64af92003-05-09 08:58:02 +0000643 def _userCancelledMonitor(self):
644 import time
645 from signal import SIGINT
646 while not self._scriptDone:
647 if Evt.CheckEventQueueForUserCancel():
648 # Send a SIGINT signal to ourselves.
649 # This gets delivered to the main thread,
650 # cancelling the running script.
651 os.kill(os.getpid(), SIGINT)
652 break
653 time.sleep(0.25)
654
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000655 def getenvironment(self):
656 if self.path:
657 file = self.path
658 dir = os.path.dirname(file)
659 # check if we're part of a package
660 modname = ""
661 while os.path.exists(os.path.join(dir, "__init__.py")):
662 dir, dirname = os.path.split(dir)
Just van Rossum2aaeb521999-02-05 21:58:25 +0000663 modname = dirname + '.' + modname
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000664 subname = _filename_as_modname(self.title)
Just van Rossumf7f93882001-11-02 19:24:41 +0000665 if subname is None:
666 return self.globals, file, None
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000667 if modname:
668 if subname == "__init__":
Just van Rossum2aaeb521999-02-05 21:58:25 +0000669 # strip trailing period
670 modname = modname[:-1]
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000671 else:
Just van Rossum2aaeb521999-02-05 21:58:25 +0000672 modname = modname + subname
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000673 else:
674 modname = subname
675 if sys.modules.has_key(modname):
676 globals = sys.modules[modname].__dict__
677 self.globals = {}
678 else:
679 globals = self.globals
Just van Rossum73efed22000-04-09 19:45:22 +0000680 modname = subname
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000681 else:
682 file = '<%s>' % self.title
683 globals = self.globals
684 modname = file
685 return globals, file, modname
686
687 def write(self, stuff):
688 """for use as stdout"""
689 self._buf = self._buf + stuff
690 if '\n' in self._buf:
691 self.flush()
692
693 def flush(self):
694 stuff = string.split(self._buf, '\n')
695 stuff = string.join(stuff, '\r')
696 end = self.editgroup.editor.ted.WEGetTextLength()
697 self.editgroup.editor.ted.WESetSelection(end, end)
698 self.editgroup.editor.ted.WEInsert(stuff, None, None)
699 self.editgroup.editor.updatescrollbars()
700 self._buf = ""
701 # ? optional:
702 #self.wid.SelectWindow()
703
704 def getclasslist(self):
705 from string import find, strip
Just van Rossum24073ea1999-12-23 15:46:57 +0000706 methodRE = re.compile(r"\r[ \t]+def ")
707 findMethod = methodRE.search
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000708 editor = self.editgroup.editor
709 text = editor.get()
710 list = []
711 append = list.append
712 functag = "func"
713 classtag = "class"
714 methodtag = "method"
715 pos = -1
716 if text[:4] == 'def ':
717 append((pos + 4, functag))
718 pos = 4
719 while 1:
720 pos = find(text, '\rdef ', pos + 1)
721 if pos < 0:
722 break
723 append((pos + 5, functag))
724 pos = -1
725 if text[:6] == 'class ':
726 append((pos + 6, classtag))
727 pos = 6
728 while 1:
729 pos = find(text, '\rclass ', pos + 1)
730 if pos < 0:
731 break
732 append((pos + 7, classtag))
733 pos = 0
734 while 1:
Just van Rossum24073ea1999-12-23 15:46:57 +0000735 m = findMethod(text, pos + 1)
736 if m is None:
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000737 break
Just van Rossum24073ea1999-12-23 15:46:57 +0000738 pos = m.regs[0][0]
739 #pos = find(text, '\r\tdef ', pos + 1)
740 append((m.regs[0][1], methodtag))
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000741 list.sort()
742 classlist = []
743 methodlistappend = None
744 offsetToLine = editor.ted.WEOffsetToLine
745 getLineRange = editor.ted.WEGetLineRange
746 append = classlist.append
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000747 for pos, tag in list:
748 lineno = offsetToLine(pos)
749 lineStart, lineEnd = getLineRange(lineno)
750 line = strip(text[pos:lineEnd])
751 line = line[:identifieRE_match(line)]
752 if tag is functag:
753 append(("def " + line, lineno + 1))
754 methodlistappend = None
755 elif tag is classtag:
756 append(["class " + line])
757 methodlistappend = classlist[-1].append
758 elif methodlistappend and tag is methodtag:
759 methodlistappend(("def " + line, lineno + 1))
760 return classlist
761
762 def popselectline(self, lineno):
763 self.editgroup.editor.selectline(lineno - 1)
764
765 def selectline(self, lineno, charoffset = 0):
766 self.editgroup.editor.selectline(lineno - 1, charoffset)
Jack Jansenc00b6d72003-02-25 15:08:02 +0000767
768 def addrecentfile(self, filename):
769 app = W.getapplication()
770 app.addrecentfile(filename)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000771
Just van Rossum12710051999-02-27 17:18:30 +0000772class _saveoptions:
773
Jack Jansen9a389472002-03-29 21:26:04 +0000774 def __init__(self, creator, eoln):
Just van Rossum12710051999-02-27 17:18:30 +0000775 self.rv = None
Jack Jansen9a389472002-03-29 21:26:04 +0000776 self.eoln = eoln
777 self.w = w = W.ModalDialog((260, 160), 'Save options')
Just van Rossum12710051999-02-27 17:18:30 +0000778 radiobuttons = []
779 w.label = W.TextBox((8, 8, 80, 18), "File creator:")
Just van Rossum3af507d1999-04-22 22:23:46 +0000780 w.ide_radio = W.RadioButton((8, 22, 160, 18), "This application", radiobuttons, self.ide_hit)
Jack Jansen9a389472002-03-29 21:26:04 +0000781 w.interp_radio = W.RadioButton((8, 42, 160, 18), "MacPython Interpreter", radiobuttons, self.interp_hit)
782 w.interpx_radio = W.RadioButton((8, 62, 160, 18), "OSX PythonW Interpreter", radiobuttons, self.interpx_hit)
783 w.other_radio = W.RadioButton((8, 82, 50, 18), "Other:", radiobuttons)
784 w.other_creator = W.EditText((62, 82, 40, 20), creator, self.otherselect)
785 w.none_radio = W.RadioButton((8, 102, 160, 18), "None", radiobuttons, self.none_hit)
Just van Rossum12710051999-02-27 17:18:30 +0000786 w.cancelbutton = W.Button((-180, -30, 80, 16), "Cancel", self.cancelbuttonhit)
787 w.okbutton = W.Button((-90, -30, 80, 16), "Done", self.okbuttonhit)
788 w.setdefaultbutton(w.okbutton)
789 if creator == 'Pyth':
790 w.interp_radio.set(1)
Just van Rossum3af507d1999-04-22 22:23:46 +0000791 elif creator == W._signature:
Just van Rossum12710051999-02-27 17:18:30 +0000792 w.ide_radio.set(1)
Jack Jansen9a389472002-03-29 21:26:04 +0000793 elif creator == 'PytX':
794 w.interpx_radio.set(1)
795 elif creator == '\0\0\0\0':
796 w.none_radio.set(1)
Just van Rossum12710051999-02-27 17:18:30 +0000797 else:
798 w.other_radio.set(1)
Jack Jansen9a389472002-03-29 21:26:04 +0000799
800 w.eolnlabel = W.TextBox((168, 8, 80, 18), "Newline style:")
801 radiobuttons = []
802 w.unix_radio = W.RadioButton((168, 22, 80, 18), "Unix", radiobuttons, self.unix_hit)
803 w.mac_radio = W.RadioButton((168, 42, 80, 18), "Macintosh", radiobuttons, self.mac_hit)
804 w.win_radio = W.RadioButton((168, 62, 80, 18), "Windows", radiobuttons, self.win_hit)
805 if self.eoln == '\n':
806 w.unix_radio.set(1)
807 elif self.eoln == '\r\n':
808 w.win_radio.set(1)
809 else:
810 w.mac_radio.set(1)
811
Just van Rossum12710051999-02-27 17:18:30 +0000812 w.bind("cmd.", w.cancelbutton.push)
813 w.open()
814
815 def ide_hit(self):
Just van Rossum3af507d1999-04-22 22:23:46 +0000816 self.w.other_creator.set(W._signature)
Just van Rossum12710051999-02-27 17:18:30 +0000817
818 def interp_hit(self):
819 self.w.other_creator.set("Pyth")
820
Jack Jansen9a389472002-03-29 21:26:04 +0000821 def interpx_hit(self):
822 self.w.other_creator.set("PytX")
823
824 def none_hit(self):
825 self.w.other_creator.set("\0\0\0\0")
826
Just van Rossum12710051999-02-27 17:18:30 +0000827 def otherselect(self, *args):
828 sel_from, sel_to = self.w.other_creator.getselection()
829 creator = self.w.other_creator.get()[:4]
830 creator = creator + " " * (4 - len(creator))
831 self.w.other_creator.set(creator)
832 self.w.other_creator.setselection(sel_from, sel_to)
833 self.w.other_radio.set(1)
834
Jack Jansen9a389472002-03-29 21:26:04 +0000835 def mac_hit(self):
836 self.eoln = '\r'
837
838 def unix_hit(self):
839 self.eoln = '\n'
840
841 def win_hit(self):
842 self.eoln = '\r\n'
843
Just van Rossum12710051999-02-27 17:18:30 +0000844 def cancelbuttonhit(self):
845 self.w.close()
846
847 def okbuttonhit(self):
Jack Jansen9a389472002-03-29 21:26:04 +0000848 self.rv = (self.w.other_creator.get()[:4], self.eoln)
Just van Rossum12710051999-02-27 17:18:30 +0000849 self.w.close()
850
851
Jack Jansen9a389472002-03-29 21:26:04 +0000852def SaveOptions(creator, eoln):
853 s = _saveoptions(creator, eoln)
Just van Rossum12710051999-02-27 17:18:30 +0000854 return s.rv
855
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000856
857def _escape(where, what) :
858 return string.join(string.split(where, what), '\\' + what)
859
860def _makewholewordpattern(word):
861 # first, escape special regex chars
Just van Rossum3eec7622001-07-10 19:25:40 +0000862 for esc in "\\[]()|.*^+$?":
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000863 word = _escape(word, esc)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000864 notwordcharspat = '[^' + _wordchars + ']'
Jack Jansen9ad27522001-02-21 13:54:31 +0000865 pattern = '(' + word + ')'
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000866 if word[0] in _wordchars:
867 pattern = notwordcharspat + pattern
868 if word[-1] in _wordchars:
869 pattern = pattern + notwordcharspat
Jack Jansen9ad27522001-02-21 13:54:31 +0000870 return re.compile(pattern)
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000871
Just van Rossumf376ef02001-11-18 14:12:43 +0000872
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000873class SearchEngine:
874
875 def __init__(self):
876 self.visible = 0
877 self.w = None
878 self.parms = { "find": "",
879 "replace": "",
880 "wrap": 1,
881 "casesens": 1,
882 "wholeword": 1
883 }
884 import MacPrefs
885 prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath)
886 if prefs.searchengine:
887 self.parms["casesens"] = prefs.searchengine.casesens
888 self.parms["wrap"] = prefs.searchengine.wrap
889 self.parms["wholeword"] = prefs.searchengine.wholeword
890
891 def show(self):
892 self.visible = 1
893 if self.w:
894 self.w.wid.ShowWindow()
895 self.w.wid.SelectWindow()
896 self.w.find.edit.select(1)
897 self.w.find.edit.selectall()
898 return
899 self.w = W.Dialog((420, 150), "Find")
900
901 self.w.find = TitledEditText((10, 4, 300, 36), "Search for:")
902 self.w.replace = TitledEditText((10, 100, 300, 36), "Replace with:")
903
904 self.w.boxes = W.Group((10, 50, 300, 40))
905 self.w.boxes.casesens = W.CheckBox((0, 0, 100, 16), "Case sensitive")
906 self.w.boxes.wholeword = W.CheckBox((0, 20, 100, 16), "Whole word")
907 self.w.boxes.wrap = W.CheckBox((110, 0, 100, 16), "Wrap around")
908
909 self.buttons = [ ("Find", "cmdf", self.find),
910 ("Replace", "cmdr", self.replace),
911 ("Replace all", None, self.replaceall),
Just van Rossumdc3c6172001-06-19 21:37:33 +0000912 ("Don't find", "cmdd", self.dont),
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000913 ("Cancel", "cmd.", self.cancel)
914 ]
915 for i in range(len(self.buttons)):
916 bounds = -90, 22 + i * 24, 80, 16
917 title, shortcut, callback = self.buttons[i]
918 self.w[title] = W.Button(bounds, title, callback)
919 if shortcut:
920 self.w.bind(shortcut, self.w[title].push)
Just van Rossumdc3c6172001-06-19 21:37:33 +0000921 self.w.setdefaultbutton(self.w["Don't find"])
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000922 self.w.find.edit.bind("<key>", self.key)
923 self.w.bind("<activate>", self.activate)
924 self.w.bind("<close>", self.close)
925 self.w.open()
926 self.setparms()
927 self.w.find.edit.select(1)
928 self.w.find.edit.selectall()
929 self.checkbuttons()
930
931 def close(self):
932 self.hide()
933 return -1
934
935 def key(self, char, modifiers):
936 self.w.find.edit.key(char, modifiers)
937 self.checkbuttons()
938 return 1
939
940 def activate(self, onoff):
941 if onoff:
942 self.checkbuttons()
943
944 def checkbuttons(self):
945 editor = findeditor(self)
946 if editor:
947 if self.w.find.get():
948 for title, cmd, call in self.buttons[:-2]:
949 self.w[title].enable(1)
950 self.w.setdefaultbutton(self.w["Find"])
951 else:
952 for title, cmd, call in self.buttons[:-2]:
953 self.w[title].enable(0)
Just van Rossumdc3c6172001-06-19 21:37:33 +0000954 self.w.setdefaultbutton(self.w["Don't find"])
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000955 else:
956 for title, cmd, call in self.buttons[:-2]:
957 self.w[title].enable(0)
Just van Rossumdc3c6172001-06-19 21:37:33 +0000958 self.w.setdefaultbutton(self.w["Don't find"])
Just van Rossum40f9b7b1999-01-30 22:39:17 +0000959
960 def find(self):
961 self.getparmsfromwindow()
962 if self.findnext():
963 self.hide()
964
965 def replace(self):
966 editor = findeditor(self)
967 if not editor:
968 return
969 if self.visible:
970 self.getparmsfromwindow()
971 text = editor.getselectedtext()
972 find = self.parms["find"]
973 if not self.parms["casesens"]:
974 find = string.lower(find)
975 text = string.lower(text)
976 if text == find:
977 self.hide()
978 editor.insert(self.parms["replace"])
979
980 def replaceall(self):
981 editor = findeditor(self)
982 if not editor:
983 return
984 if self.visible:
985 self.getparmsfromwindow()
986 W.SetCursor("watch")
987 find = self.parms["find"]
988 if not find:
989 return
990 findlen = len(find)
991 replace = self.parms["replace"]
992 replacelen = len(replace)
993 Text = editor.get()
994 if not self.parms["casesens"]:
995 find = string.lower(find)
996 text = string.lower(Text)
997 else:
998 text = Text
999 newtext = ""
1000 pos = 0
1001 counter = 0
1002 while 1:
1003 if self.parms["wholeword"]:
1004 wholewordRE = _makewholewordpattern(find)
Jack Jansen9ad27522001-02-21 13:54:31 +00001005 match = wholewordRE.search(text, pos)
1006 if match:
1007 pos = match.start(1)
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001008 else:
1009 pos = -1
1010 else:
1011 pos = string.find(text, find, pos)
1012 if pos < 0:
1013 break
1014 counter = counter + 1
1015 text = text[:pos] + replace + text[pos + findlen:]
1016 Text = Text[:pos] + replace + Text[pos + findlen:]
1017 pos = pos + replacelen
1018 W.SetCursor("arrow")
1019 if counter:
1020 self.hide()
Jack Jansen5a6fdcd2001-08-25 12:15:04 +00001021 from Carbon import Res
Just van Rossumf7f93882001-11-02 19:24:41 +00001022 editor.textchanged()
1023 editor.selectionchanged()
Just van Rossum7b025512002-10-24 20:03:29 +00001024 editor.set(Text)
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001025 EasyDialogs.Message("Replaced %d occurrences" % counter)
1026
1027 def dont(self):
1028 self.getparmsfromwindow()
1029 self.hide()
1030
1031 def replacefind(self):
1032 self.replace()
1033 self.findnext()
1034
1035 def setfindstring(self):
1036 editor = findeditor(self)
1037 if not editor:
1038 return
1039 find = editor.getselectedtext()
1040 if not find:
1041 return
1042 self.parms["find"] = find
1043 if self.w:
1044 self.w.find.edit.set(self.parms["find"])
1045 self.w.find.edit.selectall()
1046
1047 def findnext(self):
1048 editor = findeditor(self)
1049 if not editor:
1050 return
1051 find = self.parms["find"]
1052 if not find:
1053 return
1054 text = editor.get()
1055 if not self.parms["casesens"]:
1056 find = string.lower(find)
1057 text = string.lower(text)
1058 selstart, selend = editor.getselection()
1059 selstart, selend = min(selstart, selend), max(selstart, selend)
1060 if self.parms["wholeword"]:
1061 wholewordRE = _makewholewordpattern(find)
Jack Jansen9ad27522001-02-21 13:54:31 +00001062 match = wholewordRE.search(text, selend)
1063 if match:
1064 pos = match.start(1)
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001065 else:
1066 pos = -1
1067 else:
1068 pos = string.find(text, find, selend)
1069 if pos >= 0:
1070 editor.setselection(pos, pos + len(find))
1071 return 1
1072 elif self.parms["wrap"]:
1073 if self.parms["wholeword"]:
Jack Jansen9ad27522001-02-21 13:54:31 +00001074 match = wholewordRE.search(text, 0)
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)
1081 if selstart > pos >= 0:
1082 editor.setselection(pos, pos + len(find))
1083 return 1
1084
1085 def setparms(self):
1086 for key, value in self.parms.items():
1087 try:
1088 self.w[key].set(value)
1089 except KeyError:
1090 self.w.boxes[key].set(value)
1091
1092 def getparmsfromwindow(self):
1093 if not self.w:
1094 return
1095 for key, value in self.parms.items():
1096 try:
1097 value = self.w[key].get()
1098 except KeyError:
1099 value = self.w.boxes[key].get()
1100 self.parms[key] = value
1101
1102 def cancel(self):
1103 self.hide()
1104 self.setparms()
1105
1106 def hide(self):
1107 if self.w:
1108 self.w.wid.HideWindow()
1109 self.visible = 0
1110
1111 def writeprefs(self):
1112 import MacPrefs
1113 self.getparmsfromwindow()
1114 prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath)
1115 prefs.searchengine.casesens = self.parms["casesens"]
1116 prefs.searchengine.wrap = self.parms["wrap"]
1117 prefs.searchengine.wholeword = self.parms["wholeword"]
1118 prefs.save()
1119
1120
1121class TitledEditText(W.Group):
1122
1123 def __init__(self, possize, title, text = ""):
1124 W.Group.__init__(self, possize)
1125 self.title = W.TextBox((0, 0, 0, 16), title)
1126 self.edit = W.EditText((0, 16, 0, 0), text)
1127
1128 def set(self, value):
1129 self.edit.set(value)
1130
1131 def get(self):
1132 return self.edit.get()
1133
1134
1135class ClassFinder(W.PopupWidget):
1136
1137 def click(self, point, modifiers):
1138 W.SetCursor("watch")
1139 self.set(self._parentwindow.getclasslist())
1140 W.PopupWidget.click(self, point, modifiers)
1141
1142
1143def getminindent(lines):
1144 indent = -1
1145 for line in lines:
1146 stripped = string.strip(line)
1147 if not stripped or stripped[0] == '#':
1148 continue
1149 if indent < 0 or line[:indent] <> indent * '\t':
1150 indent = 0
1151 for c in line:
1152 if c <> '\t':
1153 break
1154 indent = indent + 1
1155 return indent
1156
1157
1158def getoptionkey():
1159 return not not ord(Evt.GetKeys()[7]) & 0x04
1160
1161
1162def execstring(pytext, globals, locals, filename="<string>", debugging=0,
1163 modname="__main__", profiling=0):
1164 if debugging:
1165 import PyDebugger, bdb
1166 BdbQuit = bdb.BdbQuit
1167 else:
1168 BdbQuit = 'BdbQuitDummyException'
1169 pytext = string.split(pytext, '\r')
1170 pytext = string.join(pytext, '\n') + '\n'
1171 W.SetCursor("watch")
1172 globals['__name__'] = modname
1173 globals['__file__'] = filename
1174 sys.argv = [filename]
1175 try:
1176 code = compile(pytext, filename, "exec")
1177 except:
1178 # XXXX BAAAADDD.... We let tracebackwindow decide to treat SyntaxError
1179 # special. That's wrong because THIS case is special (could be literal
1180 # overflow!) and SyntaxError could mean we need a traceback (syntax error
1181 # in imported module!!!
1182 tracebackwindow.traceback(1, filename)
1183 return
1184 try:
1185 if debugging:
Just van Rossum5ef0e7c2003-05-09 08:27:33 +00001186 PyDebugger.startfromhere()
1187 else:
Jack Jansen815d2bf2002-01-21 23:00:52 +00001188 if hasattr(MacOS, 'EnableAppswitch'):
1189 MacOS.EnableAppswitch(0)
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001190 try:
1191 if profiling:
1192 import profile, ProfileBrowser
1193 p = profile.Profile()
1194 p.set_cmd(filename)
1195 try:
1196 p.runctx(code, globals, locals)
1197 finally:
1198 import pstats
1199
1200 stats = pstats.Stats(p)
1201 ProfileBrowser.ProfileBrowser(stats)
1202 else:
1203 exec code in globals, locals
1204 finally:
Just van Rossum5ef0e7c2003-05-09 08:27:33 +00001205 if hasattr(MacOS, 'EnableAppswitch'):
1206 MacOS.EnableAppswitch(-1)
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001207 except W.AlertError, detail:
1208 raise W.AlertError, detail
1209 except (KeyboardInterrupt, BdbQuit):
1210 pass
Just van Rossumf7f93882001-11-02 19:24:41 +00001211 except SystemExit, arg:
1212 if arg.code:
1213 sys.stderr.write("Script exited with status code: %s\n" % repr(arg.code))
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001214 except:
1215 if debugging:
1216 sys.settrace(None)
1217 PyDebugger.postmortem(sys.exc_type, sys.exc_value, sys.exc_traceback)
1218 return
1219 else:
1220 tracebackwindow.traceback(1, filename)
1221 if debugging:
1222 sys.settrace(None)
1223 PyDebugger.stop()
1224
1225
Just van Rossum3eec7622001-07-10 19:25:40 +00001226_identifieRE = re.compile(r"[A-Za-z_][A-Za-z_0-9]*")
Jack Jansen9ad27522001-02-21 13:54:31 +00001227
1228def identifieRE_match(str):
1229 match = _identifieRE.match(str)
1230 if not match:
1231 return -1
1232 return match.end()
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001233
1234def _filename_as_modname(fname):
1235 if fname[-3:] == '.py':
1236 modname = fname[:-3]
Jack Jansen9ad27522001-02-21 13:54:31 +00001237 match = _identifieRE.match(modname)
1238 if match and match.start() == 0 and match.end() == len(modname):
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001239 return string.join(string.split(modname, '.'), '_')
1240
1241def findeditor(topwindow, fromtop = 0):
Just van Rossum40144012002-02-04 12:52:44 +00001242 wid = MyFrontWindow()
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001243 if not fromtop:
1244 if topwindow.w and wid == topwindow.w.wid:
1245 wid = topwindow.w.wid.GetNextWindow()
1246 if not wid:
1247 return
1248 app = W.getapplication()
1249 if app._windows.has_key(wid): # KeyError otherwise can happen in RoboFog :-(
1250 window = W.getapplication()._windows[wid]
1251 else:
1252 return
1253 if not isinstance(window, Editor):
1254 return
1255 return window.editgroup.editor
1256
1257
1258class _EditorDefaultSettings:
1259
1260 def __init__(self):
1261 self.template = "%s, %d point"
1262 self.fontsettings, self.tabsettings, self.windowsize = geteditorprefs()
1263 self.w = W.Dialog((328, 120), "Editor default settings")
Just van Rossumdc3c6172001-06-19 21:37:33 +00001264 self.w.setfontbutton = W.Button((8, 8, 80, 16), "Set font\xc9", self.dofont)
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001265 self.w.fonttext = W.TextBox((98, 10, -8, 14), self.template % (self.fontsettings[0], self.fontsettings[2]))
1266
1267 self.w.picksizebutton = W.Button((8, 50, 80, 16), "Front window", self.picksize)
1268 self.w.xsizelabel = W.TextBox((98, 32, 40, 14), "Width:")
1269 self.w.ysizelabel = W.TextBox((148, 32, 40, 14), "Height:")
1270 self.w.xsize = W.EditText((98, 48, 40, 20), `self.windowsize[0]`)
1271 self.w.ysize = W.EditText((148, 48, 40, 20), `self.windowsize[1]`)
1272
1273 self.w.cancelbutton = W.Button((-180, -26, 80, 16), "Cancel", self.cancel)
1274 self.w.okbutton = W.Button((-90, -26, 80, 16), "Done", self.ok)
1275 self.w.setdefaultbutton(self.w.okbutton)
1276 self.w.bind('cmd.', self.w.cancelbutton.push)
1277 self.w.open()
1278
1279 def picksize(self):
1280 app = W.getapplication()
1281 editor = findeditor(self)
1282 if editor is not None:
1283 width, height = editor._parentwindow._bounds[2:]
1284 self.w.xsize.set(`width`)
1285 self.w.ysize.set(`height`)
1286 else:
1287 raise W.AlertError, "No edit window found"
1288
1289 def dofont(self):
1290 import FontSettings
1291 settings = FontSettings.FontDialog(self.fontsettings, self.tabsettings)
1292 if settings:
1293 self.fontsettings, self.tabsettings = settings
1294 sys.exc_traceback = None
1295 self.w.fonttext.set(self.template % (self.fontsettings[0], self.fontsettings[2]))
1296
1297 def close(self):
1298 self.w.close()
1299 del self.w
1300
1301 def cancel(self):
1302 self.close()
1303
1304 def ok(self):
1305 try:
1306 width = string.atoi(self.w.xsize.get())
1307 except:
1308 self.w.xsize.select(1)
1309 self.w.xsize.selectall()
1310 raise W.AlertError, "Bad number for window width"
1311 try:
1312 height = string.atoi(self.w.ysize.get())
1313 except:
1314 self.w.ysize.select(1)
1315 self.w.ysize.selectall()
1316 raise W.AlertError, "Bad number for window height"
1317 self.windowsize = width, height
1318 seteditorprefs(self.fontsettings, self.tabsettings, self.windowsize)
1319 self.close()
1320
1321def geteditorprefs():
1322 import MacPrefs
1323 prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath)
1324 try:
1325 fontsettings = prefs.pyedit.fontsettings
1326 tabsettings = prefs.pyedit.tabsettings
1327 windowsize = prefs.pyedit.windowsize
1328 except:
Just van Rossumf7f93882001-11-02 19:24:41 +00001329 fontsettings = prefs.pyedit.fontsettings = ("Geneva", 0, 10, (0, 0, 0))
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001330 tabsettings = prefs.pyedit.tabsettings = (8, 1)
1331 windowsize = prefs.pyedit.windowsize = (500, 250)
1332 sys.exc_traceback = None
1333 return fontsettings, tabsettings, windowsize
1334
1335def seteditorprefs(fontsettings, tabsettings, windowsize):
1336 import MacPrefs
1337 prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath)
1338 prefs.pyedit.fontsettings = fontsettings
1339 prefs.pyedit.tabsettings = tabsettings
1340 prefs.pyedit.windowsize = windowsize
1341 prefs.save()
1342
1343_defaultSettingsEditor = None
1344
1345def EditorDefaultSettings():
1346 global _defaultSettingsEditor
1347 if _defaultSettingsEditor is None or not hasattr(_defaultSettingsEditor, "w"):
1348 _defaultSettingsEditor = _EditorDefaultSettings()
1349 else:
1350 _defaultSettingsEditor.w.select()
1351
1352def resolvealiases(path):
1353 try:
Jack Jansene7ee17c2003-02-06 22:32:35 +00001354 fsr, d1, d2 = File.FSResolveAliasFile(path, 1)
1355 path = fsr.as_pathname()
1356 return path
1357 except (File.Error, ValueError), (error, str):
Just van Rossum40f9b7b1999-01-30 22:39:17 +00001358 if error <> -120:
1359 raise
1360 dir, file = os.path.split(path)
1361 return os.path.join(resolvealiases(dir), file)
1362
1363searchengine = SearchEngine()
1364tracebackwindow = Wtraceback.TraceBack()