mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 13:41:24 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			1300 lines
		
	
	
	
		
			36 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			1300 lines
		
	
	
	
		
			36 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| """A (less & less) simple Python editor"""
 | |
| 
 | |
| import W
 | |
| import Wtraceback
 | |
| from Wkeys import *
 | |
| 
 | |
| import macfs
 | |
| import MacOS
 | |
| import Win
 | |
| import Res
 | |
| import Evt
 | |
| import os
 | |
| import imp
 | |
| import sys
 | |
| import string
 | |
| import marshal
 | |
| import regex
 | |
| 
 | |
| try:
 | |
| 	import Wthreading
 | |
| except ImportError:
 | |
| 	haveThreading = 0
 | |
| else:
 | |
| 	haveThreading = Wthreading.haveThreading
 | |
| 
 | |
| _scriptuntitledcounter = 1
 | |
| _wordchars = string.letters + string.digits + "_"
 | |
| 
 | |
| 
 | |
| runButtonLabels = ["Run all", "Stop!"]
 | |
| runSelButtonLabels = ["Run selection", "Pause!", "Resume"]
 | |
| 
 | |
| 
 | |
| class Editor(W.Window):
 | |
| 	
 | |
| 	def __init__(self, path = "", title = ""):
 | |
| 		defaultfontsettings, defaulttabsettings, defaultwindowsize = geteditorprefs()
 | |
| 		global _scriptuntitledcounter
 | |
| 		if not path:
 | |
| 			if title:
 | |
| 				self.title = title
 | |
| 			else:
 | |
| 				self.title = "Untitled Script " + `_scriptuntitledcounter`
 | |
| 				_scriptuntitledcounter = _scriptuntitledcounter + 1
 | |
| 			text = ""
 | |
| 			self._creator = W._signature
 | |
| 		elif os.path.exists(path):
 | |
| 			path = resolvealiases(path)
 | |
| 			dir, name = os.path.split(path)
 | |
| 			self.title = name
 | |
| 			f = open(path, "rb")
 | |
| 			text = f.read()
 | |
| 			f.close()
 | |
| 			fss = macfs.FSSpec(path)
 | |
| 			self._creator, filetype = fss.GetCreatorType()
 | |
| 		else:
 | |
| 			raise IOError, "file '%s' does not exist" % path
 | |
| 		self.path = path
 | |
| 		
 | |
| 		if '\n' in text:
 | |
| 			import EasyDialogs
 | |
| 			if string.find(text, '\r\n') >= 0:
 | |
| 				sourceOS = 'DOS'
 | |
| 				searchString = '\r\n'
 | |
| 			else:
 | |
| 				sourceOS = 'UNIX'
 | |
| 				searchString = '\n'
 | |
| 			change = EasyDialogs.AskYesNoCancel('³%s² contains %s-style line feeds. '
 | |
| 					'Change them to MacOS carriage returns?' % (self.title, sourceOS), 1)
 | |
| 			# bug: Cancel is treated as No
 | |
| 			if change > 0:
 | |
| 				text = string.replace(text, searchString, '\r')
 | |
| 		else:
 | |
| 			change = 0
 | |
| 		
 | |
| 		self.settings = {}
 | |
| 		if self.path:
 | |
| 			self.readwindowsettings()
 | |
| 		if self.settings.has_key("windowbounds"):
 | |
| 			bounds = self.settings["windowbounds"]
 | |
| 		else:
 | |
| 			bounds = defaultwindowsize
 | |
| 		if self.settings.has_key("fontsettings"):
 | |
| 			self.fontsettings = self.settings["fontsettings"]
 | |
| 		else:
 | |
| 			self.fontsettings = defaultfontsettings
 | |
| 		if self.settings.has_key("tabsize"):
 | |
| 			try:
 | |
| 				self.tabsettings = (tabsize, tabmode) = self.settings["tabsize"]
 | |
| 			except:
 | |
| 				self.tabsettings = defaulttabsettings
 | |
| 		else:
 | |
| 			self.tabsettings = defaulttabsettings
 | |
| 		
 | |
| 		W.Window.__init__(self, bounds, self.title, minsize = (330, 120), tabbable = 0)
 | |
| 		self.setupwidgets(text)
 | |
| 		if change > 0:
 | |
| 			self.editgroup.editor.changed = 1
 | |
| 		
 | |
| 		if self.settings.has_key("selection"):
 | |
| 			selstart, selend = self.settings["selection"]
 | |
| 			self.setselection(selstart, selend)
 | |
| 		self.open()
 | |
| 		self.setinfotext()
 | |
| 		self.globals = {}
 | |
| 		self._buf = ""  # for write method
 | |
| 		self.debugging = 0
 | |
| 		self.profiling = 0
 | |
| 		if self.settings.has_key("run_as_main"):
 | |
| 			self.run_as_main = self.settings["run_as_main"]
 | |
| 		else:
 | |
| 			self.run_as_main = 0
 | |
| 		if self.settings.has_key("run_with_interpreter"):
 | |
| 			self.run_with_interpreter = self.settings["run_with_interpreter"]
 | |
| 		else:
 | |
| 			self.run_with_interpreter = 0
 | |
| 		self._threadstate = (0, 0)
 | |
| 		self._thread = None
 | |
| 	
 | |
| 	def readwindowsettings(self):
 | |
| 		try:
 | |
| 			resref = Res.FSpOpenResFile(self.path, 1)
 | |
| 		except Res.Error:
 | |
| 			return
 | |
| 		try:
 | |
| 			Res.UseResFile(resref)
 | |
| 			data = Res.Get1Resource('PyWS', 128)
 | |
| 			self.settings = marshal.loads(data.data)
 | |
| 		except:
 | |
| 			pass
 | |
| 		Res.CloseResFile(resref)
 | |
| 		
 | |
| 	def writewindowsettings(self):
 | |
| 		try:
 | |
| 			resref = Res.FSpOpenResFile(self.path, 3)
 | |
| 		except Res.Error:
 | |
| 			Res.CreateResFile(self.path)
 | |
| 			resref = Res.FSpOpenResFile(self.path, 3)
 | |
| 		try:
 | |
| 			data = Res.Resource(marshal.dumps(self.settings))
 | |
| 			Res.UseResFile(resref)
 | |
| 			try:
 | |
| 				temp = Res.Get1Resource('PyWS', 128)
 | |
| 				temp.RemoveResource()
 | |
| 			except Res.Error:
 | |
| 				pass
 | |
| 			data.AddResource('PyWS', 128, "window settings")
 | |
| 		finally:
 | |
| 			Res.UpdateResFile(resref)
 | |
| 			Res.CloseResFile(resref)
 | |
| 	
 | |
| 	def getsettings(self):
 | |
| 		self.settings = {}
 | |
| 		self.settings["windowbounds"] = self.getbounds()
 | |
| 		self.settings["selection"] = self.getselection()
 | |
| 		self.settings["fontsettings"] = self.editgroup.editor.getfontsettings()
 | |
| 		self.settings["tabsize"] = self.editgroup.editor.gettabsettings()
 | |
| 		self.settings["run_as_main"] = self.run_as_main
 | |
| 		self.settings["run_with_interpreter"] = self.run_with_interpreter
 | |
| 	
 | |
| 	def get(self):
 | |
| 		return self.editgroup.editor.get()
 | |
| 	
 | |
| 	def getselection(self):
 | |
| 		return self.editgroup.editor.ted.WEGetSelection()
 | |
| 	
 | |
| 	def setselection(self, selstart, selend):
 | |
| 		self.editgroup.editor.setselection(selstart, selend)
 | |
| 	
 | |
| 	def getfilename(self):
 | |
| 		if self.path:
 | |
| 			return self.path
 | |
| 		return '<%s>' % self.title
 | |
| 	
 | |
| 	def setupwidgets(self, text):
 | |
| 		topbarheight = 24
 | |
| 		popfieldwidth = 80
 | |
| 		self.lastlineno = None
 | |
| 		
 | |
| 		# make an editor
 | |
| 		self.editgroup = W.Group((0, topbarheight + 1, 0, 0))
 | |
| 		editor = W.PyEditor((0, 0, -15,-15), text, 
 | |
| 				fontsettings = self.fontsettings, 
 | |
| 				tabsettings = self.tabsettings,
 | |
| 				file = self.getfilename())
 | |
| 		
 | |
| 		# make the widgets
 | |
| 		self.popfield = ClassFinder((popfieldwidth - 17, -15, 16, 16), [], self.popselectline)
 | |
| 		self.linefield = W.EditText((-1, -15, popfieldwidth - 15, 16), inset = (6, 1))
 | |
| 		self.editgroup._barx = W.Scrollbar((popfieldwidth - 2, -15, -14, 16), editor.hscroll, max = 32767)
 | |
| 		self.editgroup._bary = W.Scrollbar((-15, 14, 16, -14), editor.vscroll, max = 32767)
 | |
| 		self.editgroup.editor = editor	# add editor *after* scrollbars
 | |
| 		
 | |
| 		self.editgroup.optionsmenu = W.PopupMenu((-15, -1, 16, 16), [])
 | |
| 		self.editgroup.optionsmenu.bind('<click>', self.makeoptionsmenu)
 | |
| 		
 | |
| 		self.bevelbox = W.BevelBox((0, 0, 0, topbarheight))
 | |
| 		self.hline = W.HorizontalLine((0, topbarheight, 0, 0))
 | |
| 		self.infotext = W.TextBox((175, 6, -4, 14), backgroundcolor = (0xe000, 0xe000, 0xe000))
 | |
| 		self.runbutton = W.Button((5, 4, 80, 16), runButtonLabels[0], self.run)
 | |
| 		self.runselbutton = W.Button((90, 4, 80, 16), runSelButtonLabels[0], self.runselection)
 | |
| 		
 | |
| 		# bind some keys
 | |
| 		editor.bind("cmdr", self.runbutton.push)
 | |
| 		editor.bind("enter", self.runselbutton.push)
 | |
| 		editor.bind("cmdj", self.domenu_gotoline)
 | |
| 		editor.bind("cmdd", self.domenu_toggledebugger)
 | |
| 		editor.bind("<idle>", self.updateselection)
 | |
| 		
 | |
| 		editor.bind("cmde", searchengine.setfindstring)
 | |
| 		editor.bind("cmdf", searchengine.show)
 | |
| 		editor.bind("cmdg", searchengine.findnext)
 | |
| 		editor.bind("cmdshiftr", searchengine.replace)
 | |
| 		editor.bind("cmdt", searchengine.replacefind)
 | |
| 		
 | |
| 		self.linefield.bind("return", self.dolinefield)
 | |
| 		self.linefield.bind("enter", self.dolinefield)
 | |
| 		self.linefield.bind("tab", self.dolinefield)
 | |
| 		
 | |
| 		# intercept clicks
 | |
| 		editor.bind("<click>", self.clickeditor)
 | |
| 		self.linefield.bind("<click>", self.clicklinefield)
 | |
| 	
 | |
| 	def makeoptionsmenu(self):
 | |
| 		menuitems = [('Font settingsŠ', self.domenu_fontsettings), 
 | |
| 				("Save optionsŠ", self.domenu_options),
 | |
| 				'-',
 | |
| 				('\0' + chr(self.run_as_main) + 'Run as __main__', self.domenu_toggle_run_as_main), 
 | |
| 				#('\0' + chr(self.run_with_interpreter) + 'Run with Interpreter', self.domenu_toggle_run_with_interpreter), 
 | |
| 				#'-',
 | |
| 				('Modularize', self.domenu_modularize),
 | |
| 				('Browse namespaceŠ', self.domenu_browsenamespace), 
 | |
| 				'-']
 | |
| 		if self.profiling:
 | |
| 			menuitems = menuitems + [('Disable profiler', self.domenu_toggleprofiler)]
 | |
| 		else:
 | |
| 			menuitems = menuitems + [('Enable profiler', self.domenu_toggleprofiler)]
 | |
| 		if self.editgroup.editor._debugger:
 | |
| 			menuitems = menuitems + [('Disable debugger', self.domenu_toggledebugger),
 | |
| 				('Clear breakpoints', self.domenu_clearbreakpoints),
 | |
| 				('Edit breakpointsŠ', self.domenu_editbreakpoints)]
 | |
| 		else:
 | |
| 			menuitems = menuitems + [('Enable debugger', self.domenu_toggledebugger)]
 | |
| 		self.editgroup.optionsmenu.set(menuitems)
 | |
| 	
 | |
| 	def domenu_toggle_run_as_main(self):
 | |
| 		self.run_as_main = not self.run_as_main
 | |
| 		self.run_with_interpreter = 0
 | |
| 		self.editgroup.editor.selchanged = 1
 | |
| 	
 | |
| 	def domenu_toggle_run_with_interpreter(self):
 | |
| 		self.run_with_interpreter = not self.run_with_interpreter
 | |
| 		self.run_as_main = 0
 | |
| 		self.editgroup.editor.selchanged = 1
 | |
| 	
 | |
| 	def showbreakpoints(self, onoff):
 | |
| 		self.editgroup.editor.showbreakpoints(onoff)
 | |
| 		self.debugging = onoff
 | |
| 	
 | |
| 	def domenu_clearbreakpoints(self, *args):
 | |
| 		self.editgroup.editor.clearbreakpoints()
 | |
| 	
 | |
| 	def domenu_editbreakpoints(self, *args):
 | |
| 		self.editgroup.editor.editbreakpoints()
 | |
| 	
 | |
| 	def domenu_toggledebugger(self, *args):
 | |
| 		if not self.debugging:
 | |
| 			W.SetCursor('watch')
 | |
| 		self.debugging = not self.debugging
 | |
| 		self.editgroup.editor.togglebreakpoints()
 | |
| 		
 | |
| 	def domenu_toggleprofiler(self, *args):
 | |
| 		self.profiling = not self.profiling
 | |
| 	
 | |
| 	def domenu_browsenamespace(self, *args):
 | |
| 		import PyBrowser, W
 | |
| 		W.SetCursor('watch')
 | |
| 		globals, file, modname = self.getenvironment()
 | |
| 		if not modname:
 | |
| 			modname = self.title
 | |
| 		PyBrowser.Browser(globals, "Object browser: " + modname)
 | |
| 	
 | |
| 	def domenu_modularize(self, *args):
 | |
| 		modname = _filename_as_modname(self.title)
 | |
| 		if not modname:
 | |
| 			raise W.AlertError, 'Can¹t modularize ³%s²' % self.title
 | |
| 		run_as_main = self.run_as_main
 | |
| 		self.run_as_main = 0
 | |
| 		self.run()
 | |
| 		self.run_as_main = run_as_main
 | |
| 		if self.path:
 | |
| 			file = self.path
 | |
| 		else:
 | |
| 			file = self.title
 | |
| 		
 | |
| 		if self.globals and not sys.modules.has_key(modname):
 | |
| 			module = imp.new_module(modname)
 | |
| 			for attr in self.globals.keys():
 | |
| 				setattr(module,attr,self.globals[attr])
 | |
| 			sys.modules[modname] = module
 | |
| 			self.globals = {}
 | |
| 	
 | |
| 	def domenu_fontsettings(self, *args):
 | |
| 		import FontSettings
 | |
| 		fontsettings = self.editgroup.editor.getfontsettings()
 | |
| 		tabsettings = self.editgroup.editor.gettabsettings()
 | |
| 		settings = FontSettings.FontDialog(fontsettings, tabsettings)
 | |
| 		if settings:
 | |
| 			fontsettings, tabsettings = settings
 | |
| 			self.editgroup.editor.setfontsettings(fontsettings)
 | |
| 			self.editgroup.editor.settabsettings(tabsettings)
 | |
| 	
 | |
| 	def domenu_options(self, *args):
 | |
| 		rv = SaveOptions(self._creator)
 | |
| 		if rv:
 | |
| 			self.editgroup.editor.selchanged = 1 # ouch...
 | |
| 			self._creator = rv
 | |
| 	
 | |
| 	def clicklinefield(self):
 | |
| 		if self._currentwidget <> self.linefield:
 | |
| 			self.linefield.select(1)
 | |
| 			self.linefield.selectall()
 | |
| 			return 1
 | |
| 	
 | |
| 	def clickeditor(self):
 | |
| 		if self._currentwidget <> self.editgroup.editor:
 | |
| 			self.dolinefield()
 | |
| 			return 1
 | |
| 	
 | |
| 	def updateselection(self, force = 0):
 | |
| 		sel = min(self.editgroup.editor.getselection())
 | |
| 		lineno = self.editgroup.editor.offsettoline(sel)
 | |
| 		if lineno <> self.lastlineno or force:
 | |
| 			self.lastlineno = lineno
 | |
| 			self.linefield.set(str(lineno + 1))
 | |
| 			self.linefield.selview()
 | |
| 	
 | |
| 	def dolinefield(self):
 | |
| 		try:
 | |
| 			lineno = string.atoi(self.linefield.get()) - 1
 | |
| 			if lineno <> self.lastlineno:
 | |
| 				self.editgroup.editor.selectline(lineno)
 | |
| 				self.updateselection(1)
 | |
| 		except:
 | |
| 			self.updateselection(1)
 | |
| 		self.editgroup.editor.select(1)
 | |
| 	
 | |
| 	def setinfotext(self):
 | |
| 		if not hasattr(self, 'infotext'):
 | |
| 			return
 | |
| 		if self.path:
 | |
| 			self.infotext.set(self.path)
 | |
| 		else:
 | |
| 			self.infotext.set("")
 | |
| 	
 | |
| 	def close(self):
 | |
| 		if self.editgroup.editor.changed:
 | |
| 			import EasyDialogs
 | |
| 			import Qd
 | |
| 			Qd.InitCursor() # XXX should be done by dialog
 | |
| 			save = EasyDialogs.AskYesNoCancel('Save window ³%s² before closing?' % self.title, 1)
 | |
| 			if save > 0:
 | |
| 				if self.domenu_save():
 | |
| 					return 1
 | |
| 			elif save < 0:
 | |
| 				return 1
 | |
| 		self.globals = None	    # XXX doesn't help... all globals leak :-(
 | |
| 		W.Window.close(self)
 | |
| 	
 | |
| 	def domenu_close(self, *args):
 | |
| 		return self.close()
 | |
| 	
 | |
| 	def domenu_save(self, *args):
 | |
| 		if not self.path:
 | |
| 			# Will call us recursively
 | |
| 			return self.domenu_save_as()
 | |
| 		data = self.editgroup.editor.get()
 | |
| 		fp = open(self.path, 'wb')  # open file in binary mode, data has '\r' line-endings
 | |
| 		fp.write(data)
 | |
| 		fp.close()
 | |
| 		fss = macfs.FSSpec(self.path)
 | |
| 		fss.SetCreatorType(self._creator, 'TEXT')
 | |
| 		self.getsettings()
 | |
| 		self.writewindowsettings()
 | |
| 		self.editgroup.editor.changed = 0
 | |
| 		self.editgroup.editor.selchanged = 0
 | |
| 		import linecache
 | |
| 		if linecache.cache.has_key(self.path):
 | |
| 			del linecache.cache[self.path]
 | |
| 		import macostools
 | |
| 		macostools.touched(self.path)
 | |
| 	
 | |
| 	def can_save(self, menuitem):
 | |
| 		return self.editgroup.editor.changed or self.editgroup.editor.selchanged
 | |
| 	
 | |
| 	def domenu_save_as(self, *args):
 | |
| 		fss, ok = macfs.StandardPutFile('Save as:', self.title)
 | |
| 		if not ok: 
 | |
| 			return 1
 | |
| 		self.showbreakpoints(0)
 | |
| 		self.path = fss.as_pathname()
 | |
| 		self.setinfotext()
 | |
| 		self.title = os.path.split(self.path)[-1]
 | |
| 		self.wid.SetWTitle(self.title)
 | |
| 		self.domenu_save()
 | |
| 		self.editgroup.editor.setfile(self.getfilename())
 | |
| 		app = W.getapplication()
 | |
| 		app.makeopenwindowsmenu()
 | |
| 		if hasattr(app, 'makescriptsmenu'):
 | |
| 			app = W.getapplication()
 | |
| 			fss, fss_changed = app.scriptsfolder.Resolve()
 | |
| 			path = fss.as_pathname()
 | |
| 			if path == self.path[:len(path)]:
 | |
| 				W.getapplication().makescriptsmenu()
 | |
| 	
 | |
| 	def domenu_save_as_applet(self, *args):
 | |
| 		try:
 | |
| 			import buildtools
 | |
| 		except ImportError:
 | |
| 			# only have buildtools in Python >= 1.5.2
 | |
| 			raise W.AlertError, "³Save as Applet² is only supported in\rPython 1.5.2 and up."
 | |
| 		
 | |
| 		buildtools.DEBUG = 0	# ouch.
 | |
| 		
 | |
| 		if self.title[-3:] == ".py":
 | |
| 			destname = self.title[:-3]
 | |
| 		else:
 | |
| 			destname = self.title + ".applet"
 | |
| 		fss, ok = macfs.StandardPutFile('Save as Applet:', destname)
 | |
| 		if not ok: 
 | |
| 			return 1
 | |
| 		W.SetCursor("watch")
 | |
| 		destname = fss.as_pathname()
 | |
| 		if self.path:
 | |
| 			filename = self.path
 | |
| 			if filename[-3:] == ".py":
 | |
| 				rsrcname = filename[:-3] + '.rsrc'
 | |
| 			else:
 | |
| 				rsrcname = filename + '.rsrc'
 | |
| 		else:
 | |
| 			filename = self.title
 | |
| 			rsrcname = ""
 | |
| 		
 | |
| 		pytext = self.editgroup.editor.get()
 | |
| 		pytext = string.split(pytext, '\r')
 | |
| 		pytext = string.join(pytext, '\n') + '\n'
 | |
| 		try:
 | |
| 			code = compile(pytext, filename, "exec")
 | |
| 		except (SyntaxError, EOFError):
 | |
| 			raise buildtools.BuildError, "Syntax error in script %s" % `filename`
 | |
| 		
 | |
| 		# Try removing the output file
 | |
| 		try:
 | |
| 			os.remove(destname)
 | |
| 		except os.error:
 | |
| 			pass
 | |
| 		template = buildtools.findtemplate()
 | |
| 		buildtools.process_common(template, None, code, rsrcname, destname, 0, 1)
 | |
| 	
 | |
| 	def domenu_gotoline(self, *args):
 | |
| 		self.linefield.selectall()
 | |
| 		self.linefield.select(1)
 | |
| 		self.linefield.selectall()
 | |
| 	
 | |
| 	def domenu_selectline(self, *args):
 | |
| 		self.editgroup.editor.expandselection()
 | |
| 	
 | |
| 	def domenu_find(self, *args):
 | |
| 		searchengine.show()
 | |
| 	
 | |
| 	def domenu_entersearchstring(self, *args):
 | |
| 		searchengine.setfindstring()
 | |
| 	
 | |
| 	def domenu_replace(self, *args):
 | |
| 		searchengine.replace()
 | |
| 	
 | |
| 	def domenu_findnext(self, *args):
 | |
| 		searchengine.findnext()
 | |
| 	
 | |
| 	def domenu_replacefind(self, *args):
 | |
| 		searchengine.replacefind()
 | |
| 	
 | |
| 	def domenu_run(self, *args):
 | |
| 		self.runbutton.push()
 | |
| 	
 | |
| 	def domenu_runselection(self, *args):
 | |
| 		self.runselbutton.push()
 | |
| 	
 | |
| 	def run(self):
 | |
| 		if self._threadstate == (0, 0):
 | |
| 			self._run()
 | |
| 		else:
 | |
| 			lock = Wthreading.Lock()
 | |
| 			lock.acquire()
 | |
| 			self._thread.postException(KeyboardInterrupt)
 | |
| 			if self._thread.isBlocked():
 | |
| 				self._thread.start()
 | |
| 			lock.release()
 | |
| 	
 | |
| 	def _run(self):
 | |
| 		if self.run_with_interpreter:
 | |
| 			if self.editgroup.editor.changed:
 | |
| 				import EasyDialogs
 | |
| 				import Qd; Qd.InitCursor()
 | |
| 				save = EasyDialogs.AskYesNoCancel('Save ³%s² before running?' % self.title, 1)
 | |
| 				if save > 0:
 | |
| 					if self.domenu_save():
 | |
| 						return
 | |
| 				elif save < 0:
 | |
| 					return
 | |
| 			if not self.path:
 | |
| 				raise W.AlertError, "Can't run unsaved file"
 | |
| 			self._run_with_interpreter()
 | |
| 		else:
 | |
| 			pytext = self.editgroup.editor.get()
 | |
| 			globals, file, modname = self.getenvironment()
 | |
| 			self.execstring(pytext, globals, globals, file, modname)
 | |
| 	
 | |
| 	def _run_with_interpreter(self):
 | |
| 		interp_path = os.path.join(sys.exec_prefix, "PythonInterpreter")
 | |
| 		if not os.path.exists(interp_path):
 | |
| 			raise W.AlertError, "Can't find interpreter"
 | |
| 		import findertools
 | |
| 		XXX
 | |
| 	
 | |
| 	def runselection(self):
 | |
| 		if self._threadstate == (0, 0):
 | |
| 			self._runselection()
 | |
| 		elif self._threadstate == (1, 1):
 | |
| 			self._thread.block()
 | |
| 			self.setthreadstate((1, 2))
 | |
| 		elif self._threadstate == (1, 2):
 | |
| 			self._thread.start()
 | |
| 			self.setthreadstate((1, 1))
 | |
| 	
 | |
| 	def _runselection(self):
 | |
| 		if self.run_with_interpreter:
 | |
| 			raise W.AlertError, "Can't run selection with Interpreter"
 | |
| 		globals, file, modname = self.getenvironment()
 | |
| 		locals = globals
 | |
| 		# select whole lines
 | |
| 		self.editgroup.editor.expandselection()
 | |
| 		
 | |
| 		# get lineno of first selected line
 | |
| 		selstart, selend = self.editgroup.editor.getselection()
 | |
| 		selstart, selend = min(selstart, selend), max(selstart, selend)
 | |
| 		selfirstline = self.editgroup.editor.offsettoline(selstart)
 | |
| 		alltext = self.editgroup.editor.get()
 | |
| 		pytext = alltext[selstart:selend]
 | |
| 		lines = string.split(pytext, '\r')
 | |
| 		indent = getminindent(lines)
 | |
| 		if indent == 1:
 | |
| 			classname = ''
 | |
| 			alllines = string.split(alltext, '\r')
 | |
| 			identifieRE_match = _identifieRE.match
 | |
| 			for i in range(selfirstline - 1, -1, -1):
 | |
| 				line = alllines[i]
 | |
| 				if line[:6] == 'class ':
 | |
| 					classname = string.split(string.strip(line[6:]))[0]
 | |
| 					classend = identifieRE_match(classname)
 | |
| 					if classend < 1:
 | |
| 						raise W.AlertError, 'Can¹t find a class.'
 | |
| 					classname = classname[:classend]
 | |
| 					break
 | |
| 				elif line and line[0] not in '\t#':
 | |
| 					raise W.AlertError, 'Can¹t find a class.'
 | |
| 			else:
 | |
| 				raise W.AlertError, 'Can¹t find a class.'
 | |
| 			if globals.has_key(classname):
 | |
| 				locals = globals[classname].__dict__
 | |
| 			else:
 | |
| 				raise W.AlertError, 'Can¹t find class ³%s².' % classname
 | |
| 			# dedent to top level
 | |
| 			for i in range(len(lines)):
 | |
| 				lines[i] = lines[i][1:]
 | |
| 			pytext = string.join(lines, '\r')
 | |
| 		elif indent > 0:
 | |
| 			raise W.AlertError, 'Can¹t run indented code.'
 | |
| 		
 | |
| 		# add "newlines" to fool compile/exec: 
 | |
| 		# now a traceback will give the right line number
 | |
| 		pytext = selfirstline * '\r' + pytext
 | |
| 		self.execstring(pytext, globals, locals, file, modname)
 | |
| 	
 | |
| 	def setthreadstate(self, state):
 | |
| 		oldstate = self._threadstate
 | |
| 		if oldstate[0] <> state[0]:
 | |
| 			self.runbutton.settitle(runButtonLabels[state[0]])
 | |
| 		if oldstate[1] <> state[1]:
 | |
| 			self.runselbutton.settitle(runSelButtonLabels[state[1]])
 | |
| 		self._threadstate = state
 | |
| 	
 | |
| 	def _exec_threadwrapper(self, *args, **kwargs):
 | |
| 		apply(execstring, args, kwargs)
 | |
| 		self.setthreadstate((0, 0))
 | |
| 		self._thread = None
 | |
| 	
 | |
| 	def execstring(self, pytext, globals, locals, file, modname):
 | |
| 		tracebackwindow.hide()
 | |
| 		# update windows
 | |
| 		W.getapplication().refreshwindows()
 | |
| 		if self.run_as_main:
 | |
| 			modname = "__main__"
 | |
| 		if self.path:
 | |
| 			dir = os.path.dirname(self.path)
 | |
| 			savedir = os.getcwd()
 | |
| 			os.chdir(dir)
 | |
| 			sys.path.insert(0, dir)
 | |
| 		else:
 | |
| 			cwdindex = None
 | |
| 		try:
 | |
| 			if haveThreading:
 | |
| 				self._thread = Wthreading.Thread(os.path.basename(file), 
 | |
| 							self._exec_threadwrapper, pytext, globals, locals, file, self.debugging, 
 | |
| 							modname, self.profiling)
 | |
| 				self.setthreadstate((1, 1))
 | |
| 				self._thread.start()
 | |
| 			else:
 | |
| 				execstring(pytext, globals, locals, file, self.debugging, 
 | |
| 							modname, self.profiling)
 | |
| 		finally:
 | |
| 			if self.path:
 | |
| 				os.chdir(savedir)
 | |
| 				del sys.path[0]
 | |
| 	
 | |
| 	def getenvironment(self):
 | |
| 		if self.path:
 | |
| 			file = self.path
 | |
| 			dir = os.path.dirname(file)
 | |
| 			# check if we're part of a package
 | |
| 			modname = ""
 | |
| 			while os.path.exists(os.path.join(dir, "__init__.py")):
 | |
| 				dir, dirname = os.path.split(dir)
 | |
| 				modname = dirname + '.' + modname
 | |
| 			subname = _filename_as_modname(self.title)
 | |
| 			if modname:
 | |
| 				if subname == "__init__":
 | |
| 					# strip trailing period
 | |
| 					modname = modname[:-1]
 | |
| 				else:
 | |
| 					modname = modname + subname
 | |
| 			else:
 | |
| 				modname = subname
 | |
| 			if sys.modules.has_key(modname):
 | |
| 				globals = sys.modules[modname].__dict__
 | |
| 				self.globals = {}
 | |
| 			else:
 | |
| 				globals = self.globals
 | |
| 				modname = subname
 | |
| 		else:
 | |
| 			file = '<%s>' % self.title
 | |
| 			globals = self.globals
 | |
| 			modname = file
 | |
| 		return globals, file, modname
 | |
| 	
 | |
| 	def write(self, stuff):
 | |
| 		"""for use as stdout"""
 | |
| 		self._buf = self._buf + stuff
 | |
| 		if '\n' in self._buf:
 | |
| 			self.flush()
 | |
| 	
 | |
| 	def flush(self):
 | |
| 		stuff = string.split(self._buf, '\n')
 | |
| 		stuff = string.join(stuff, '\r')
 | |
| 		end = self.editgroup.editor.ted.WEGetTextLength()
 | |
| 		self.editgroup.editor.ted.WESetSelection(end, end)
 | |
| 		self.editgroup.editor.ted.WEInsert(stuff, None, None)
 | |
| 		self.editgroup.editor.updatescrollbars()
 | |
| 		self._buf = ""
 | |
| 		# ? optional:
 | |
| 		#self.wid.SelectWindow()
 | |
| 	
 | |
| 	def getclasslist(self):
 | |
| 		from string import find, strip
 | |
| 		import re
 | |
| 		methodRE = re.compile(r"\r[ \t]+def ")
 | |
| 		findMethod = methodRE.search
 | |
| 		editor = self.editgroup.editor
 | |
| 		text = editor.get()
 | |
| 		list = []
 | |
| 		append = list.append
 | |
| 		functag = "func"
 | |
| 		classtag = "class"
 | |
| 		methodtag = "method"
 | |
| 		pos = -1
 | |
| 		if text[:4] == 'def ':
 | |
| 			append((pos + 4, functag))
 | |
| 			pos = 4
 | |
| 		while 1:
 | |
| 			pos = find(text, '\rdef ', pos + 1)
 | |
| 			if pos < 0:
 | |
| 				break
 | |
| 			append((pos + 5, functag))
 | |
| 		pos = -1
 | |
| 		if text[:6] == 'class ':
 | |
| 			append((pos + 6, classtag))
 | |
| 			pos = 6
 | |
| 		while 1:
 | |
| 			pos = find(text, '\rclass ', pos + 1)
 | |
| 			if pos < 0:
 | |
| 				break
 | |
| 			append((pos + 7, classtag))
 | |
| 		pos = 0
 | |
| 		while 1:
 | |
| 			m = findMethod(text, pos + 1)
 | |
| 			if m is None:
 | |
| 				break
 | |
| 			pos = m.regs[0][0]
 | |
| 			#pos = find(text, '\r\tdef ', pos + 1)
 | |
| 			append((m.regs[0][1], methodtag))
 | |
| 		list.sort()
 | |
| 		classlist = []
 | |
| 		methodlistappend = None
 | |
| 		offsetToLine = editor.ted.WEOffsetToLine
 | |
| 		getLineRange = editor.ted.WEGetLineRange
 | |
| 		append = classlist.append
 | |
| 		identifieRE_match = _identifieRE.match
 | |
| 		for pos, tag in list:
 | |
| 			lineno = offsetToLine(pos)
 | |
| 			lineStart, lineEnd = getLineRange(lineno)
 | |
| 			line = strip(text[pos:lineEnd])
 | |
| 			line = line[:identifieRE_match(line)]
 | |
| 			if tag is functag:
 | |
| 				append(("def " + line, lineno + 1))
 | |
| 				methodlistappend = None
 | |
| 			elif tag is classtag:
 | |
| 				append(["class " + line])
 | |
| 				methodlistappend = classlist[-1].append
 | |
| 			elif methodlistappend and tag is methodtag:
 | |
| 				methodlistappend(("def " + line, lineno + 1))
 | |
| 		return classlist
 | |
| 	
 | |
| 	def popselectline(self, lineno):
 | |
| 		self.editgroup.editor.selectline(lineno - 1)
 | |
| 	
 | |
| 	def selectline(self, lineno, charoffset = 0):
 | |
| 		self.editgroup.editor.selectline(lineno - 1, charoffset)
 | |
| 
 | |
| class _saveoptions:
 | |
| 	
 | |
| 	def __init__(self, creator):
 | |
| 		self.rv = None
 | |
| 		self.w = w = W.ModalDialog((240, 140), 'Save options')
 | |
| 		radiobuttons = []
 | |
| 		w.label = W.TextBox((8, 8, 80, 18), "File creator:")
 | |
| 		w.ide_radio = W.RadioButton((8, 22, 160, 18), "This application", radiobuttons, self.ide_hit)
 | |
| 		w.interp_radio = W.RadioButton((8, 42, 160, 18), "Python Interpreter", radiobuttons, self.interp_hit)
 | |
| 		w.other_radio = W.RadioButton((8, 62, 50, 18), "Other:", radiobuttons)
 | |
| 		w.other_creator = W.EditText((62, 62, 40, 20), creator, self.otherselect)
 | |
| 		w.cancelbutton = W.Button((-180, -30, 80, 16), "Cancel", self.cancelbuttonhit)
 | |
| 		w.okbutton = W.Button((-90, -30, 80, 16), "Done", self.okbuttonhit)
 | |
| 		w.setdefaultbutton(w.okbutton)
 | |
| 		if creator == 'Pyth':
 | |
| 			w.interp_radio.set(1)
 | |
| 		elif creator == W._signature:
 | |
| 			w.ide_radio.set(1)
 | |
| 		else:
 | |
| 			w.other_radio.set(1)
 | |
| 		w.bind("cmd.", w.cancelbutton.push)
 | |
| 		w.open()
 | |
| 	
 | |
| 	def ide_hit(self):
 | |
| 		self.w.other_creator.set(W._signature)
 | |
| 	
 | |
| 	def interp_hit(self):
 | |
| 		self.w.other_creator.set("Pyth")
 | |
| 	
 | |
| 	def otherselect(self, *args):
 | |
| 		sel_from, sel_to = self.w.other_creator.getselection()
 | |
| 		creator = self.w.other_creator.get()[:4]
 | |
| 		creator = creator + " " * (4 - len(creator))
 | |
| 		self.w.other_creator.set(creator)
 | |
| 		self.w.other_creator.setselection(sel_from, sel_to)
 | |
| 		self.w.other_radio.set(1)
 | |
| 	
 | |
| 	def cancelbuttonhit(self):
 | |
| 		self.w.close()
 | |
| 	
 | |
| 	def okbuttonhit(self):
 | |
| 		self.rv = self.w.other_creator.get()[:4]
 | |
| 		self.w.close()
 | |
| 
 | |
| 
 | |
| def SaveOptions(creator):
 | |
| 	s = _saveoptions(creator)
 | |
| 	return s.rv
 | |
| 
 | |
| 
 | |
| def _escape(where, what) : 
 | |
| 	return string.join(string.split(where, what), '\\' + what)
 | |
| 
 | |
| def _makewholewordpattern(word):
 | |
| 	# first, escape special regex chars
 | |
| 	for esc in "\\[].*^+$?":
 | |
| 		word = _escape(word, esc)
 | |
| 	import regex
 | |
| 	notwordcharspat = '[^' + _wordchars + ']'
 | |
| 	pattern = '\(' + word + '\)'
 | |
| 	if word[0] in _wordchars:
 | |
| 		pattern = notwordcharspat + pattern
 | |
| 	if word[-1] in _wordchars:
 | |
| 		pattern = pattern + notwordcharspat
 | |
| 	return regex.compile(pattern)
 | |
| 
 | |
| class SearchEngine:
 | |
| 	
 | |
| 	def __init__(self):
 | |
| 		self.visible = 0
 | |
| 		self.w = None
 | |
| 		self.parms = {  "find": "",
 | |
| 					"replace": "",
 | |
| 					"wrap": 1,
 | |
| 					"casesens": 1,
 | |
| 					"wholeword": 1
 | |
| 				}
 | |
| 		import MacPrefs
 | |
| 		prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath)
 | |
| 		if prefs.searchengine:
 | |
| 			self.parms["casesens"] = prefs.searchengine.casesens
 | |
| 			self.parms["wrap"] = prefs.searchengine.wrap
 | |
| 			self.parms["wholeword"] = prefs.searchengine.wholeword
 | |
| 	
 | |
| 	def show(self):
 | |
| 		self.visible = 1
 | |
| 		if self.w:
 | |
| 			self.w.wid.ShowWindow()
 | |
| 			self.w.wid.SelectWindow()
 | |
| 			self.w.find.edit.select(1)
 | |
| 			self.w.find.edit.selectall()
 | |
| 			return
 | |
| 		self.w = W.Dialog((420, 150), "Find")
 | |
| 		
 | |
| 		self.w.find = TitledEditText((10, 4, 300, 36), "Search for:")
 | |
| 		self.w.replace = TitledEditText((10, 100, 300, 36), "Replace with:")
 | |
| 		
 | |
| 		self.w.boxes = W.Group((10, 50, 300, 40))
 | |
| 		self.w.boxes.casesens = W.CheckBox((0, 0, 100, 16), "Case sensitive")
 | |
| 		self.w.boxes.wholeword = W.CheckBox((0, 20, 100, 16), "Whole word")
 | |
| 		self.w.boxes.wrap = W.CheckBox((110, 0, 100, 16), "Wrap around")
 | |
| 		
 | |
| 		self.buttons = [	("Find",		"cmdf",	 self.find), 
 | |
| 					("Replace",	     "cmdr",	 self.replace), 
 | |
| 					("Replace all",	 None,   self.replaceall), 
 | |
| 					("Don¹t find",  "cmdd",	 self.dont), 
 | |
| 					("Cancel",	      "cmd.",	 self.cancel)
 | |
| 				]
 | |
| 		for i in range(len(self.buttons)):
 | |
| 			bounds = -90, 22 + i * 24, 80, 16
 | |
| 			title, shortcut, callback = self.buttons[i]
 | |
| 			self.w[title] = W.Button(bounds, title, callback)
 | |
| 			if shortcut:
 | |
| 				self.w.bind(shortcut, self.w[title].push)
 | |
| 		self.w.setdefaultbutton(self.w["Don¹t find"])
 | |
| 		self.w.find.edit.bind("<key>", self.key)
 | |
| 		self.w.bind("<activate>", self.activate)
 | |
| 		self.w.bind("<close>", self.close)
 | |
| 		self.w.open()
 | |
| 		self.setparms()
 | |
| 		self.w.find.edit.select(1)
 | |
| 		self.w.find.edit.selectall()
 | |
| 		self.checkbuttons()
 | |
| 	
 | |
| 	def close(self):
 | |
| 		self.hide()
 | |
| 		return -1
 | |
| 	
 | |
| 	def key(self, char, modifiers):
 | |
| 		self.w.find.edit.key(char, modifiers)
 | |
| 		self.checkbuttons()
 | |
| 		return 1
 | |
| 	
 | |
| 	def activate(self, onoff):
 | |
| 		if onoff:
 | |
| 			self.checkbuttons()
 | |
| 	
 | |
| 	def checkbuttons(self):
 | |
| 		editor = findeditor(self)
 | |
| 		if editor:
 | |
| 			if self.w.find.get():
 | |
| 				for title, cmd, call in self.buttons[:-2]:
 | |
| 					self.w[title].enable(1)
 | |
| 				self.w.setdefaultbutton(self.w["Find"])
 | |
| 			else:
 | |
| 				for title, cmd, call in self.buttons[:-2]:
 | |
| 					self.w[title].enable(0)
 | |
| 				self.w.setdefaultbutton(self.w["Don¹t find"])
 | |
| 		else:
 | |
| 			for title, cmd, call in self.buttons[:-2]:
 | |
| 				self.w[title].enable(0)
 | |
| 			self.w.setdefaultbutton(self.w["Don¹t find"])
 | |
| 	
 | |
| 	def find(self):
 | |
| 		self.getparmsfromwindow()
 | |
| 		if self.findnext():
 | |
| 			self.hide()
 | |
| 	
 | |
| 	def replace(self):
 | |
| 		editor = findeditor(self)
 | |
| 		if not editor:
 | |
| 			return
 | |
| 		if self.visible:
 | |
| 			self.getparmsfromwindow()
 | |
| 		text = editor.getselectedtext()
 | |
| 		find = self.parms["find"]
 | |
| 		if not self.parms["casesens"]:
 | |
| 			find = string.lower(find)
 | |
| 			text = string.lower(text)
 | |
| 		if text == find:
 | |
| 			self.hide()
 | |
| 			editor.insert(self.parms["replace"])
 | |
| 	
 | |
| 	def replaceall(self):
 | |
| 		editor = findeditor(self)
 | |
| 		if not editor:
 | |
| 			return
 | |
| 		if self.visible:
 | |
| 			self.getparmsfromwindow()
 | |
| 		W.SetCursor("watch")
 | |
| 		find = self.parms["find"]
 | |
| 		if not find:
 | |
| 			return
 | |
| 		findlen = len(find)
 | |
| 		replace = self.parms["replace"]
 | |
| 		replacelen = len(replace)
 | |
| 		Text = editor.get()
 | |
| 		if not self.parms["casesens"]:
 | |
| 			find = string.lower(find)
 | |
| 			text = string.lower(Text)
 | |
| 		else:
 | |
| 			text = Text
 | |
| 		newtext = ""
 | |
| 		pos = 0
 | |
| 		counter = 0
 | |
| 		while 1:
 | |
| 			if self.parms["wholeword"]:
 | |
| 				wholewordRE = _makewholewordpattern(find)
 | |
| 				wholewordRE.search(text, pos)
 | |
| 				if wholewordRE.regs:
 | |
| 					pos = wholewordRE.regs[1][0]
 | |
| 				else:
 | |
| 					pos = -1
 | |
| 			else:
 | |
| 				pos = string.find(text, find, pos)
 | |
| 			if pos < 0:
 | |
| 				break
 | |
| 			counter = counter + 1
 | |
| 			text = text[:pos] + replace + text[pos + findlen:]
 | |
| 			Text = Text[:pos] + replace + Text[pos + findlen:]
 | |
| 			pos = pos + replacelen
 | |
| 		W.SetCursor("arrow")
 | |
| 		if counter:
 | |
| 			self.hide()
 | |
| 			import EasyDialogs
 | |
| 			import Res
 | |
| 			editor.changed = 1
 | |
| 			editor.selchanged = 1
 | |
| 			editor.ted.WEUseText(Res.Resource(Text))
 | |
| 			editor.ted.WECalText()
 | |
| 			editor.SetPort()
 | |
| 			Win.InvalRect(editor._bounds)
 | |
| 			#editor.ted.WEUpdate(self.w.wid.GetWindowPort().visRgn)
 | |
| 			EasyDialogs.Message("Replaced %d occurrences" % counter)
 | |
| 	
 | |
| 	def dont(self):
 | |
| 		self.getparmsfromwindow()
 | |
| 		self.hide()
 | |
| 	
 | |
| 	def replacefind(self):
 | |
| 		self.replace()
 | |
| 		self.findnext()
 | |
| 	
 | |
| 	def setfindstring(self):
 | |
| 		editor = findeditor(self)
 | |
| 		if not editor:
 | |
| 			return
 | |
| 		find = editor.getselectedtext()
 | |
| 		if not find:
 | |
| 			return
 | |
| 		self.parms["find"] = find
 | |
| 		if self.w:
 | |
| 			self.w.find.edit.set(self.parms["find"])
 | |
| 			self.w.find.edit.selectall()
 | |
| 	
 | |
| 	def findnext(self):
 | |
| 		editor = findeditor(self)
 | |
| 		if not editor:
 | |
| 			return
 | |
| 		find = self.parms["find"]
 | |
| 		if not find:
 | |
| 			return
 | |
| 		text = editor.get()
 | |
| 		if not self.parms["casesens"]:
 | |
| 			find = string.lower(find)
 | |
| 			text = string.lower(text)
 | |
| 		selstart, selend = editor.getselection()
 | |
| 		selstart, selend = min(selstart, selend), max(selstart, selend)
 | |
| 		if self.parms["wholeword"]:
 | |
| 			wholewordRE = _makewholewordpattern(find)
 | |
| 			wholewordRE.search(text, selend)
 | |
| 			if wholewordRE.regs:
 | |
| 				pos = wholewordRE.regs[1][0]
 | |
| 			else:
 | |
| 				pos = -1
 | |
| 		else:
 | |
| 			pos = string.find(text, find, selend)
 | |
| 		if pos >= 0:
 | |
| 			editor.setselection(pos, pos + len(find))
 | |
| 			return 1
 | |
| 		elif self.parms["wrap"]:
 | |
| 			if self.parms["wholeword"]:
 | |
| 				wholewordRE.search(text, 0)
 | |
| 				if wholewordRE.regs:
 | |
| 					pos = wholewordRE.regs[1][0]
 | |
| 				else:
 | |
| 					pos = -1
 | |
| 			else:
 | |
| 				pos = string.find(text, find)
 | |
| 			if selstart > pos >= 0:
 | |
| 				editor.setselection(pos, pos + len(find))
 | |
| 				return 1
 | |
| 	
 | |
| 	def setparms(self):
 | |
| 		for key, value in self.parms.items():
 | |
| 			try:
 | |
| 				self.w[key].set(value)
 | |
| 			except KeyError:
 | |
| 				self.w.boxes[key].set(value)
 | |
| 	
 | |
| 	def getparmsfromwindow(self):
 | |
| 		if not self.w:
 | |
| 			return
 | |
| 		for key, value in self.parms.items():
 | |
| 			try:
 | |
| 				value = self.w[key].get()
 | |
| 			except KeyError:
 | |
| 				value = self.w.boxes[key].get()
 | |
| 			self.parms[key] = value
 | |
| 	
 | |
| 	def cancel(self):
 | |
| 		self.hide()
 | |
| 		self.setparms()
 | |
| 	
 | |
| 	def hide(self):
 | |
| 		if self.w:
 | |
| 			self.w.wid.HideWindow()
 | |
| 			self.visible = 0
 | |
| 	
 | |
| 	def writeprefs(self):
 | |
| 		import MacPrefs
 | |
| 		self.getparmsfromwindow()
 | |
| 		prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath)
 | |
| 		prefs.searchengine.casesens = self.parms["casesens"]
 | |
| 		prefs.searchengine.wrap = self.parms["wrap"]
 | |
| 		prefs.searchengine.wholeword = self.parms["wholeword"]
 | |
| 		prefs.save()
 | |
| 	
 | |
| 
 | |
| class TitledEditText(W.Group):
 | |
| 	
 | |
| 	def __init__(self, possize, title, text = ""):
 | |
| 		W.Group.__init__(self, possize)
 | |
| 		self.title = W.TextBox((0, 0, 0, 16), title)
 | |
| 		self.edit = W.EditText((0, 16, 0, 0), text)
 | |
| 	
 | |
| 	def set(self, value):
 | |
| 		self.edit.set(value)
 | |
| 	
 | |
| 	def get(self):
 | |
| 		return self.edit.get()
 | |
| 
 | |
| 
 | |
| class ClassFinder(W.PopupWidget):
 | |
| 	
 | |
| 	def click(self, point, modifiers):
 | |
| 		W.SetCursor("watch")
 | |
| 		self.set(self._parentwindow.getclasslist())
 | |
| 		W.PopupWidget.click(self, point, modifiers)
 | |
| 
 | |
| 
 | |
| def getminindent(lines):
 | |
| 	indent = -1
 | |
| 	for line in lines:
 | |
| 		stripped = string.strip(line)
 | |
| 		if not stripped or stripped[0] == '#':
 | |
| 			continue
 | |
| 		if indent < 0 or line[:indent] <> indent * '\t':
 | |
| 			indent = 0
 | |
| 			for c in line:
 | |
| 				if c <> '\t':
 | |
| 					break
 | |
| 				indent = indent + 1
 | |
| 	return indent
 | |
| 
 | |
| 
 | |
| def getoptionkey():
 | |
| 	return not not ord(Evt.GetKeys()[7]) & 0x04
 | |
| 
 | |
| 
 | |
| def execstring(pytext, globals, locals, filename="<string>", debugging=0, 
 | |
| 			modname="__main__", profiling=0):
 | |
| 	if debugging:
 | |
| 		import PyDebugger, bdb
 | |
| 		BdbQuit = bdb.BdbQuit
 | |
| 	else:
 | |
| 		BdbQuit = 'BdbQuitDummyException'
 | |
| 	pytext = string.split(pytext, '\r')
 | |
| 	pytext = string.join(pytext, '\n') + '\n'
 | |
| 	W.SetCursor("watch")
 | |
| 	globals['__name__'] = modname
 | |
| 	globals['__file__'] = filename
 | |
| 	sys.argv = [filename]
 | |
| 	try:
 | |
| 		code = compile(pytext, filename, "exec")
 | |
| 	except:
 | |
| 		# XXXX BAAAADDD.... We let tracebackwindow decide to treat SyntaxError 
 | |
| 		# special. That's wrong because THIS case is special (could be literal 
 | |
| 		# overflow!) and SyntaxError could mean we need a traceback (syntax error 
 | |
| 		# in imported module!!!
 | |
| 		tracebackwindow.traceback(1, filename)
 | |
| 		return
 | |
| 	try:
 | |
| 		if debugging:
 | |
| 			if haveThreading:
 | |
| 				lock = Wthreading.Lock()
 | |
| 				lock.acquire()
 | |
| 				PyDebugger.startfromhere()
 | |
| 				lock.release()
 | |
| 			else:
 | |
| 				PyDebugger.startfromhere()
 | |
| 		elif not haveThreading:
 | |
| 			MacOS.EnableAppswitch(0)
 | |
| 		try:
 | |
| 			if profiling:
 | |
| 				import profile, ProfileBrowser
 | |
| 				p = profile.Profile()
 | |
| 				p.set_cmd(filename)
 | |
| 				try:
 | |
| 					p.runctx(code, globals, locals)
 | |
| 				finally:
 | |
| 					import pstats
 | |
| 					
 | |
| 					stats = pstats.Stats(p)
 | |
| 					ProfileBrowser.ProfileBrowser(stats)
 | |
| 			else:
 | |
| 				exec code in globals, locals
 | |
| 		finally:
 | |
| 			if not haveThreading:
 | |
| 				MacOS.EnableAppswitch(-1)
 | |
| 	except W.AlertError, detail:
 | |
| 		raise W.AlertError, detail
 | |
| 	except (KeyboardInterrupt, BdbQuit):
 | |
| 		pass
 | |
| 	except:
 | |
| 		if haveThreading:
 | |
| 			import continuation
 | |
| 			lock = Wthreading.Lock()
 | |
| 			lock.acquire()
 | |
| 		if debugging:
 | |
| 			sys.settrace(None)
 | |
| 			PyDebugger.postmortem(sys.exc_type, sys.exc_value, sys.exc_traceback)
 | |
| 			return
 | |
| 		else:
 | |
| 			tracebackwindow.traceback(1, filename)
 | |
| 		if haveThreading:
 | |
| 			lock.release()
 | |
| 	if debugging:
 | |
| 		sys.settrace(None)
 | |
| 		PyDebugger.stop()
 | |
| 
 | |
| 
 | |
| _identifieRE = regex.compile("[A-Za-z_][A-Za-z_0-9]*")
 | |
| 
 | |
| def _filename_as_modname(fname):
 | |
| 	if fname[-3:] == '.py':
 | |
| 		modname = fname[:-3]
 | |
| 		if _identifieRE.match(modname) == len(modname):
 | |
| 			return string.join(string.split(modname, '.'), '_')
 | |
| 
 | |
| def findeditor(topwindow, fromtop = 0):
 | |
| 	wid = Win.FrontWindow()
 | |
| 	if not fromtop:
 | |
| 		if topwindow.w and wid == topwindow.w.wid:
 | |
| 			wid = topwindow.w.wid.GetNextWindow()
 | |
| 	if not wid:
 | |
| 		return
 | |
| 	app = W.getapplication()
 | |
| 	if app._windows.has_key(wid): # KeyError otherwise can happen in RoboFog :-(
 | |
| 		window = W.getapplication()._windows[wid]
 | |
| 	else:
 | |
| 		return
 | |
| 	if not isinstance(window, Editor):
 | |
| 		return
 | |
| 	return window.editgroup.editor
 | |
| 
 | |
| 
 | |
| class _EditorDefaultSettings:
 | |
| 	
 | |
| 	def __init__(self):
 | |
| 		self.template = "%s, %d point"
 | |
| 		self.fontsettings, self.tabsettings, self.windowsize = geteditorprefs()
 | |
| 		self.w = W.Dialog((328, 120), "Editor default settings")
 | |
| 		self.w.setfontbutton = W.Button((8, 8, 80, 16), "Set fontŠ", self.dofont)
 | |
| 		self.w.fonttext = W.TextBox((98, 10, -8, 14), self.template % (self.fontsettings[0], self.fontsettings[2]))
 | |
| 		
 | |
| 		self.w.picksizebutton = W.Button((8, 50, 80, 16), "Front window", self.picksize)
 | |
| 		self.w.xsizelabel = W.TextBox((98, 32, 40, 14), "Width:")
 | |
| 		self.w.ysizelabel = W.TextBox((148, 32, 40, 14), "Height:")
 | |
| 		self.w.xsize = W.EditText((98, 48, 40, 20), `self.windowsize[0]`)
 | |
| 		self.w.ysize = W.EditText((148, 48, 40, 20), `self.windowsize[1]`)
 | |
| 		
 | |
| 		self.w.cancelbutton = W.Button((-180, -26, 80, 16), "Cancel", self.cancel)
 | |
| 		self.w.okbutton = W.Button((-90, -26, 80, 16), "Done", self.ok)
 | |
| 		self.w.setdefaultbutton(self.w.okbutton)
 | |
| 		self.w.bind('cmd.', self.w.cancelbutton.push)
 | |
| 		self.w.open()
 | |
| 	
 | |
| 	def picksize(self):
 | |
| 		app = W.getapplication()
 | |
| 		editor = findeditor(self)
 | |
| 		if editor is not None:
 | |
| 			width, height = editor._parentwindow._bounds[2:]
 | |
| 			self.w.xsize.set(`width`)
 | |
| 			self.w.ysize.set(`height`)
 | |
| 		else:
 | |
| 			raise W.AlertError, "No edit window found"
 | |
| 	
 | |
| 	def dofont(self):
 | |
| 		import FontSettings
 | |
| 		settings = FontSettings.FontDialog(self.fontsettings, self.tabsettings)
 | |
| 		if settings:
 | |
| 			self.fontsettings, self.tabsettings = settings
 | |
| 			sys.exc_traceback = None
 | |
| 			self.w.fonttext.set(self.template % (self.fontsettings[0], self.fontsettings[2]))
 | |
| 	
 | |
| 	def close(self):
 | |
| 		self.w.close()
 | |
| 		del self.w
 | |
| 	
 | |
| 	def cancel(self):
 | |
| 		self.close()
 | |
| 	
 | |
| 	def ok(self):
 | |
| 		try:
 | |
| 			width = string.atoi(self.w.xsize.get())
 | |
| 		except:
 | |
| 			self.w.xsize.select(1)
 | |
| 			self.w.xsize.selectall()
 | |
| 			raise W.AlertError, "Bad number for window width"
 | |
| 		try:
 | |
| 			height = string.atoi(self.w.ysize.get())
 | |
| 		except:
 | |
| 			self.w.ysize.select(1)
 | |
| 			self.w.ysize.selectall()
 | |
| 			raise W.AlertError, "Bad number for window height"
 | |
| 		self.windowsize = width, height
 | |
| 		seteditorprefs(self.fontsettings, self.tabsettings, self.windowsize)
 | |
| 		self.close()
 | |
| 
 | |
| def geteditorprefs():
 | |
| 	import MacPrefs
 | |
| 	prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath)
 | |
| 	try:
 | |
| 		fontsettings = prefs.pyedit.fontsettings
 | |
| 		tabsettings = prefs.pyedit.tabsettings
 | |
| 		windowsize = prefs.pyedit.windowsize
 | |
| 	except:
 | |
| 		fontsettings = prefs.pyedit.fontsettings = ("Python-Sans", 0, 9, (0, 0, 0))
 | |
| 		tabsettings = prefs.pyedit.tabsettings = (8, 1)
 | |
| 		windowsize = prefs.pyedit.windowsize = (500, 250)
 | |
| 		sys.exc_traceback = None
 | |
| 	return fontsettings, tabsettings, windowsize
 | |
| 
 | |
| def seteditorprefs(fontsettings, tabsettings, windowsize):
 | |
| 	import MacPrefs
 | |
| 	prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath)
 | |
| 	prefs.pyedit.fontsettings = fontsettings
 | |
| 	prefs.pyedit.tabsettings = tabsettings
 | |
| 	prefs.pyedit.windowsize = windowsize
 | |
| 	prefs.save()
 | |
| 
 | |
| _defaultSettingsEditor = None
 | |
| 
 | |
| def EditorDefaultSettings():
 | |
| 	global _defaultSettingsEditor
 | |
| 	if _defaultSettingsEditor is None or not hasattr(_defaultSettingsEditor, "w"):
 | |
| 		_defaultSettingsEditor = _EditorDefaultSettings()
 | |
| 	else:
 | |
| 		_defaultSettingsEditor.w.select()
 | |
| 
 | |
| def resolvealiases(path):
 | |
| 	try:
 | |
| 		return macfs.ResolveAliasFile(path)[0].as_pathname()
 | |
| 	except (macfs.error, ValueError), (error, str):
 | |
| 		if error <> -120:
 | |
| 			raise
 | |
| 		dir, file = os.path.split(path)
 | |
| 		return os.path.join(resolvealiases(dir), file)
 | |
| 
 | |
| searchengine = SearchEngine()
 | |
| tracebackwindow = Wtraceback.TraceBack()
 | 
