mirror of
https://github.com/python/cpython.git
synced 2025-07-27 13:14:41 +00:00

Added a -D flag (can really only be specified on OSX commandline) to not revector sys.stderr, for debugging the IDE itself. Not sure whether this should stay.
283 lines
9.1 KiB
Python
283 lines
9.1 KiB
Python
# copyright 1997-2001 Just van Rossum, Letterror. just@letterror.com
|
|
|
|
import Splash
|
|
|
|
import FrameWork
|
|
import Wapplication
|
|
import W
|
|
import os
|
|
import sys
|
|
import macfs
|
|
import MacOS
|
|
|
|
if MacOS.runtimemodel == 'macho':
|
|
ELIPSES = '...'
|
|
else:
|
|
ELIPSES = '\xc9'
|
|
|
|
def runningOnOSX():
|
|
from gestalt import gestalt
|
|
gestaltMenuMgrAquaLayoutBit = 1 # menus have the Aqua 1.0 layout
|
|
gestaltMenuMgrAquaLayoutMask = (1L << gestaltMenuMgrAquaLayoutBit)
|
|
value = gestalt("menu") & gestaltMenuMgrAquaLayoutMask
|
|
return not not value
|
|
|
|
|
|
class PythonIDE(Wapplication.Application):
|
|
|
|
def __init__(self):
|
|
self.preffilepath = ":Python:PythonIDE preferences"
|
|
Wapplication.Application.__init__(self, 'Pide')
|
|
from Carbon import AE
|
|
from Carbon import AppleEvents
|
|
|
|
AE.AEInstallEventHandler(AppleEvents.kCoreEventClass, AppleEvents.kAEOpenApplication,
|
|
self.ignoreevent)
|
|
AE.AEInstallEventHandler(AppleEvents.kCoreEventClass, AppleEvents.kAEReopenApplication,
|
|
self.ignoreevent)
|
|
AE.AEInstallEventHandler(AppleEvents.kCoreEventClass, AppleEvents.kAEPrintDocuments,
|
|
self.ignoreevent)
|
|
AE.AEInstallEventHandler(AppleEvents.kCoreEventClass, AppleEvents.kAEOpenDocuments,
|
|
self.opendocsevent)
|
|
AE.AEInstallEventHandler(AppleEvents.kCoreEventClass, AppleEvents.kAEQuitApplication,
|
|
self.quitevent)
|
|
import PyConsole, PyEdit
|
|
Splash.wait()
|
|
# With -D option (OSX command line only) keep stderr, for debugging the IDE
|
|
# itself.
|
|
debug_stderr = None
|
|
if sys.argv[1] == '-D':
|
|
debug_stderr = sys.stderr
|
|
del sys.argv[1]
|
|
PyConsole.installoutput()
|
|
PyConsole.installconsole()
|
|
if debug_stderr:
|
|
sys.stderr = debug_stderr
|
|
for path in sys.argv[1:]:
|
|
self.opendoc(path)
|
|
try:
|
|
import Wthreading
|
|
except ImportError:
|
|
self.mainloop()
|
|
else:
|
|
if Wthreading.haveThreading:
|
|
self.mainthread = Wthreading.Thread("IDE event loop", self.mainloop)
|
|
self.mainthread.start()
|
|
#self.mainthread.setResistant(1)
|
|
Wthreading.run()
|
|
else:
|
|
self.mainloop()
|
|
|
|
def makeusermenus(self):
|
|
m = Wapplication.Menu(self.menubar, "File")
|
|
newitem = FrameWork.MenuItem(m, "New", "N", 'new')
|
|
openitem = FrameWork.MenuItem(m, "Open"+ELIPSES, "O", 'open')
|
|
FrameWork.Separator(m)
|
|
closeitem = FrameWork.MenuItem(m, "Close", "W", 'close')
|
|
saveitem = FrameWork.MenuItem(m, "Save", "S", 'save')
|
|
saveasitem = FrameWork.MenuItem(m, "Save as"+ELIPSES, None, 'save_as')
|
|
FrameWork.Separator(m)
|
|
saveasappletitem = FrameWork.MenuItem(m, "Save as Applet"+ELIPSES, None, 'save_as_applet')
|
|
if not runningOnOSX():
|
|
# On OSX there's a special "magic" quit menu, so we shouldn't add
|
|
# it to the File menu.
|
|
FrameWork.Separator(m)
|
|
quititem = FrameWork.MenuItem(m, "Quit", "Q", 'quit')
|
|
|
|
m = Wapplication.Menu(self.menubar, "Edit")
|
|
undoitem = FrameWork.MenuItem(m, "Undo", 'Z', "undo")
|
|
FrameWork.Separator(m)
|
|
cutitem = FrameWork.MenuItem(m, "Cut", 'X', "cut")
|
|
copyitem = FrameWork.MenuItem(m, "Copy", "C", "copy")
|
|
pasteitem = FrameWork.MenuItem(m, "Paste", "V", "paste")
|
|
FrameWork.MenuItem(m, "Clear", None, "clear")
|
|
FrameWork.Separator(m)
|
|
selallitem = FrameWork.MenuItem(m, "Select all", "A", "selectall")
|
|
sellineitem = FrameWork.MenuItem(m, "Select line", "L", "selectline")
|
|
FrameWork.Separator(m)
|
|
finditem = FrameWork.MenuItem(m, "Find"+ELIPSES, "F", "find")
|
|
findagainitem = FrameWork.MenuItem(m, "Find again", 'G', "findnext")
|
|
enterselitem = FrameWork.MenuItem(m, "Enter search string", "E", "entersearchstring")
|
|
replaceitem = FrameWork.MenuItem(m, "Replace", None, "replace")
|
|
replacefinditem = FrameWork.MenuItem(m, "Replace & find again", 'T', "replacefind")
|
|
FrameWork.Separator(m)
|
|
shiftleftitem = FrameWork.MenuItem(m, "Shift left", "[", "shiftleft")
|
|
shiftrightitem = FrameWork.MenuItem(m, "Shift right", "]", "shiftright")
|
|
|
|
m = Wapplication.Menu(self.menubar, "Python")
|
|
runitem = FrameWork.MenuItem(m, "Run window", "R", 'run')
|
|
runselitem = FrameWork.MenuItem(m, "Run selection", None, 'runselection')
|
|
FrameWork.Separator(m)
|
|
moditem = FrameWork.MenuItem(m, "Module browser"+ELIPSES, "M", self.domenu_modulebrowser)
|
|
FrameWork.Separator(m)
|
|
mm = FrameWork.SubMenu(m, "Preferences")
|
|
FrameWork.MenuItem(mm, "Set Scripts folder"+ELIPSES, None, self.do_setscriptsfolder)
|
|
FrameWork.MenuItem(mm, "Editor default settings"+ELIPSES, None, self.do_editorprefs)
|
|
FrameWork.MenuItem(mm, "Set default window font"+ELIPSES, None, self.do_setwindowfont)
|
|
|
|
self.openwindowsmenu = Wapplication.Menu(self.menubar, 'Windows')
|
|
self.makeopenwindowsmenu()
|
|
self._menustocheck = [closeitem, saveitem, saveasitem, saveasappletitem,
|
|
undoitem, cutitem, copyitem, pasteitem,
|
|
selallitem, sellineitem,
|
|
finditem, findagainitem, enterselitem, replaceitem, replacefinditem,
|
|
shiftleftitem, shiftrightitem,
|
|
runitem, runselitem]
|
|
|
|
prefs = self.getprefs()
|
|
try:
|
|
fss, fss_changed = macfs.RawAlias(prefs.scriptsfolder).Resolve()
|
|
self.scriptsfolder = fss.NewAlias()
|
|
except:
|
|
path = os.path.join(os.getcwd(), ":Mac:IDE scripts")
|
|
if not os.path.exists(path):
|
|
path = os.path.join(os.getcwd(), "Scripts")
|
|
if not os.path.exists(path):
|
|
os.mkdir(path)
|
|
f = open(os.path.join(path, "Place your scripts here"+ELIPSES), "w")
|
|
f.close()
|
|
fss = macfs.FSSpec(path)
|
|
self.scriptsfolder = fss.NewAlias()
|
|
self.scriptsfoldermodtime = fss.GetDates()[1]
|
|
else:
|
|
self.scriptsfoldermodtime = fss.GetDates()[1]
|
|
prefs.scriptsfolder = self.scriptsfolder.data
|
|
self._scripts = {}
|
|
self.scriptsmenu = None
|
|
self.makescriptsmenu()
|
|
|
|
def quitevent(self, theAppleEvent, theReply):
|
|
from Carbon import AE
|
|
AE.AEInteractWithUser(50000000)
|
|
self._quit()
|
|
|
|
def suspendresume(self, onoff):
|
|
if onoff:
|
|
fss, fss_changed = self.scriptsfolder.Resolve()
|
|
modtime = fss.GetDates()[1]
|
|
if self.scriptsfoldermodtime <> modtime or fss_changed:
|
|
self.scriptsfoldermodtime = modtime
|
|
W.SetCursor('watch')
|
|
self.makescriptsmenu()
|
|
|
|
def ignoreevent(self, theAppleEvent, theReply):
|
|
pass
|
|
|
|
def opendocsevent(self, theAppleEvent, theReply):
|
|
W.SetCursor('watch')
|
|
import aetools
|
|
parameters, args = aetools.unpackevent(theAppleEvent)
|
|
docs = parameters['----']
|
|
if type(docs) <> type([]):
|
|
docs = [docs]
|
|
for doc in docs:
|
|
fss, a = doc.Resolve()
|
|
path = fss.as_pathname()
|
|
self.opendoc(path)
|
|
|
|
def opendoc(self, path):
|
|
fcreator, ftype = macfs.FSSpec(path).GetCreatorType()
|
|
if ftype == 'TEXT':
|
|
self.openscript(path)
|
|
elif ftype == '\0\0\0\0' and path[-3:] == '.py':
|
|
self.openscript(path)
|
|
else:
|
|
W.Message("Can't open file of type '%s'." % ftype)
|
|
|
|
def getabouttext(self):
|
|
return "About Python IDE"+ELIPSES
|
|
|
|
def do_about(self, id, item, window, event):
|
|
Splash.about()
|
|
|
|
def do_setscriptsfolder(self, *args):
|
|
fss, ok = macfs.GetDirectory("Select Scripts Folder")
|
|
if ok:
|
|
prefs = self.getprefs()
|
|
alis = fss.NewAlias()
|
|
prefs.scriptsfolder = alis.data
|
|
self.scriptsfolder = alis
|
|
self.makescriptsmenu()
|
|
prefs.save()
|
|
|
|
def domenu_modulebrowser(self, *args):
|
|
W.SetCursor('watch')
|
|
import ModuleBrowser
|
|
ModuleBrowser.ModuleBrowser()
|
|
|
|
def domenu_open(self, *args):
|
|
fss, ok = macfs.StandardGetFile("TEXT")
|
|
if ok:
|
|
self.openscript(fss.as_pathname())
|
|
|
|
def domenu_new(self, *args):
|
|
W.SetCursor('watch')
|
|
import PyEdit
|
|
return PyEdit.Editor()
|
|
|
|
def makescriptsmenu(self):
|
|
W.SetCursor('watch')
|
|
if self._scripts:
|
|
for id, item in self._scripts.keys():
|
|
if self.menubar.menus.has_key(id):
|
|
m = self.menubar.menus[id]
|
|
m.delete()
|
|
self._scripts = {}
|
|
if self.scriptsmenu:
|
|
if hasattr(self.scriptsmenu, 'id') and self.menubar.menus.has_key(self.scriptsmenu.id):
|
|
self.scriptsmenu.delete()
|
|
self.scriptsmenu = FrameWork.Menu(self.menubar, "Scripts")
|
|
#FrameWork.MenuItem(self.scriptsmenu, "New script", None, self.domenu_new)
|
|
#self.scriptsmenu.addseparator()
|
|
fss, fss_changed = self.scriptsfolder.Resolve()
|
|
self.scriptswalk(fss.as_pathname(), self.scriptsmenu)
|
|
|
|
def makeopenwindowsmenu(self):
|
|
for i in range(len(self.openwindowsmenu.items)):
|
|
self.openwindowsmenu.menu.DeleteMenuItem(1)
|
|
self.openwindowsmenu.items = []
|
|
windows = []
|
|
self._openwindows = {}
|
|
for window in self._windows.keys():
|
|
title = window.GetWTitle()
|
|
if not title:
|
|
title = "<no title>"
|
|
windows.append((title, window))
|
|
windows.sort()
|
|
for title, window in windows:
|
|
if title == "Python Interactive": # ugly but useful hack by Joe Strout
|
|
shortcut = '0'
|
|
else:
|
|
shortcut = None
|
|
item = FrameWork.MenuItem(self.openwindowsmenu, title, shortcut, callback = self.domenu_openwindows)
|
|
self._openwindows[item.item] = window
|
|
self._openwindowscheckmark = 0
|
|
self.checkopenwindowsmenu()
|
|
|
|
def domenu_openwindows(self, id, item, window, event):
|
|
w = self._openwindows[item]
|
|
w.ShowWindow()
|
|
w.SelectWindow()
|
|
|
|
def domenu_quit(self):
|
|
self._quit()
|
|
|
|
def domenu_save(self, *args):
|
|
print "Save"
|
|
|
|
def _quit(self):
|
|
import PyConsole, PyEdit
|
|
PyConsole.console.writeprefs()
|
|
PyConsole.output.writeprefs()
|
|
PyEdit.searchengine.writeprefs()
|
|
for window in self._windows.values():
|
|
try:
|
|
rv = window.close() # ignore any errors while quitting
|
|
except:
|
|
rv = 0 # (otherwise, we can get stuck!)
|
|
if rv and rv > 0:
|
|
return
|
|
self.quitting = 1
|
|
|
|
PythonIDE()
|
|
|