diff options
Diffstat (limited to 'Mac/Tools/IDE/PyConsole.py')
-rw-r--r-- | Mac/Tools/IDE/PyConsole.py | 380 |
1 files changed, 380 insertions, 0 deletions
diff --git a/Mac/Tools/IDE/PyConsole.py b/Mac/Tools/IDE/PyConsole.py new file mode 100644 index 0000000..ad71982 --- /dev/null +++ b/Mac/Tools/IDE/PyConsole.py @@ -0,0 +1,380 @@ +import W +import Wkeys +import Fm +import WASTEconst +from types import * +import Events +import string +import sys +import traceback +import MacOS +import MacPrefs +import Qd +import PyInteractive + +if not hasattr(sys, 'ps1'): + sys.ps1 = '>>> ' +if not hasattr(sys, 'ps2'): + sys.ps2 = '... ' + +def inspect(foo): # JJS 1/25/99 + "Launch the browser on the given object. This is a general built-in function." + import PyBrowser + PyBrowser.Browser(foo) + +class ConsoleTextWidget(W.EditText): + + def __init__(self, *args, **kwargs): + apply(W.EditText.__init__, (self,) + args, kwargs) + self._inputstart = 0 + self._buf = '' + self.pyinteractive = PyInteractive.PyInteractive() + + import __main__ + self._namespace = __main__.__dict__ + self._namespace['inspect'] = inspect # JJS 1/25/99 + + def insert(self, text): + self.checkselection() + self.ted.WEInsert(text, None, None) + self.changed = 1 + self.selchanged = 1 + + def set_namespace(self, dict): + if type(dict) <> DictionaryType: + raise TypeError, "The namespace needs to be a dictionary" + if 'inspect' not in dict.keys(): dict['inspect'] = inspect # JJS 1/25/99 + self._namespace = dict + + def open(self): + W.EditText.open(self) + self.write('Python ' + sys.version + '\n' + sys.copyright + '\n') + self.write(sys.ps1) + self.flush() + + def key(self, char, event): + (what, message, when, where, modifiers) = event + if self._enabled and not modifiers & Events.cmdKey or char in Wkeys.arrowkeys: + if char not in Wkeys.navigationkeys: + self.checkselection() + if char == Wkeys.enterkey: + char = Wkeys.returnkey + selstart, selend = self.getselection() + if char == Wkeys.backspacekey: + if selstart <= (self._inputstart - (selstart <> selend)): + return + self.ted.WEKey(ord(char), modifiers) + if char not in Wkeys.navigationkeys: + self.changed = 1 + if char not in Wkeys.scrollkeys: + self.selchanged = 1 + self.updatescrollbars() + if char == Wkeys.returnkey: + text = self.get()[self._inputstart:selstart] + text = string.join(string.split(text, "\r"), "\n") + saveyield = MacOS.EnableAppswitch(0) + self.pyinteractive.executeline(text, self, self._namespace) + MacOS.EnableAppswitch(saveyield) + selstart, selend = self.getselection() + self._inputstart = selstart + + def domenu_save_as(self, *args): + import macfs + fss, ok = macfs.StandardPutFile('Save console text as:', 'console.txt') + if not ok: + return + f = open(fss.as_pathname(), 'wb') + f.write(self.get()) + f.close() + fss.SetCreatorType(W._signature, 'TEXT') + + def write(self, text): + self._buf = self._buf + text + if '\n' in self._buf: + self.flush() + + def flush(self): + stuff = string.split(self._buf, '\n') + stuff = string.join(stuff, '\r') + self.setselection_at_end() + self.ted.WEInsert(stuff, None, None) + selstart, selend = self.getselection() + self._inputstart = selstart + self._buf = "" + self.ted.WEClearUndo() + self.updatescrollbars() + + def selection_ok(self): + selstart, selend = self.getselection() + return not (selstart < self._inputstart or selend < self._inputstart) + + def checkselection(self): + if not self.selection_ok(): + self.setselection_at_end() + + def setselection_at_end(self): + end = self.ted.WEGetTextLength() + self.setselection(end, end) + self.updatescrollbars() + + def domenu_cut(self, *args): + if not self.selection_ok(): + return + W.EditText.domenu_cut(self) + + def domenu_paste(self, *args): + if not self.selection_ok(): + self.setselection_at_end() + W.EditText.domenu_paste(self) + + def domenu_clear(self, *args): + if not self.selection_ok(): + return + W.EditText.domenu_clear(self) + + +class PyConsole(W.Window): + + def __init__(self, bounds, show = 1, fontsettings = ("Monaco", 0, 9, (0, 0, 0)), + tabsettings = (32, 0), unclosable = 0): + W.Window.__init__(self, + bounds, + "Python Interactive", + minsize = (200, 100), + tabbable = 0, + show = show) + + self._unclosable = unclosable + consoletext = ConsoleTextWidget((-1, -1, -14, 1), inset = (6, 5), + fontsettings = fontsettings, tabsettings = tabsettings) + self._bary = W.Scrollbar((-15, 14, 16, -14), consoletext.vscroll, max = 32767) + self.consoletext = consoletext + self.namespacemenu = W.PopupMenu((-15, -1, 16, 16), [], self.consoletext.set_namespace) + self.namespacemenu.bind('<click>', self.makenamespacemenu) + self.open() + + def makenamespacemenu(self, *args): + W.SetCursor('watch') + namespacelist = self.getnamespacelist() + self.namespacemenu.set([("Clear window", self.clearbuffer), ("Font settingsÉ", self.dofontsettings), + ["Namespace"] + namespacelist, ("Browse namespaceÉ", self.browsenamespace)]) + currentname = self.consoletext._namespace["__name__"] + for i in range(len(namespacelist)): + if namespacelist[i][0] == currentname: + break + else: + return + # XXX this functionality should be generally available in Wmenus + submenuid = self.namespacemenu.menu.menu.GetItemMark(3) + menu = self.namespacemenu.menu.bar.menus[submenuid] + menu.menu.CheckItem(i + 1, 1) + + def browsenamespace(self): + import PyBrowser, W + W.SetCursor('watch') + PyBrowser.Browser(self.consoletext._namespace, self.consoletext._namespace["__name__"]) + + def clearbuffer(self): + import Res + self.consoletext.ted.WEUseText(Res.Resource('')) + self.consoletext.write(sys.ps1) + self.consoletext.flush() + + def getnamespacelist(self): + import os + import __main__ + editors = filter(lambda x: x.__class__.__name__ == "Editor", self.parent._windows.values()) + + namespaces = [ ("__main__",__main__.__dict__) ] + for ed in editors: + modname = os.path.splitext(ed.title)[0] + if sys.modules.has_key(modname): + module = sys.modules[modname] + namespaces.append((modname, module.__dict__)) + else: + if ed.title[-3:] == '.py': + modname = ed.title[:-3] + else: + modname = ed.title + ed.globals["__name__"] = modname + namespaces.append((modname, ed.globals)) + return namespaces + + def dofontsettings(self): + import FontSettings + settings = FontSettings.FontDialog(self.consoletext.getfontsettings(), + self.consoletext.gettabsettings()) + if settings: + fontsettings, tabsettings = settings + self.consoletext.setfontsettings(fontsettings) + self.consoletext.settabsettings(tabsettings) + + def show(self, onoff = 1): + W.Window.show(self, onoff) + if onoff: + self.select() + + def close(self): + if self._unclosable: + self.show(0) + return -1 + W.Window.close(self) + + def writeprefs(self): + prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath) + prefs.console.show = self.isvisible() + prefs.console.windowbounds = self.getbounds() + prefs.console.fontsettings = self.consoletext.getfontsettings() + prefs.console.tabsettings = self.consoletext.gettabsettings() + prefs.save() + + +class OutputTextWidget(W.EditText): + + def domenu_save_as(self, *args): + title = self._parentwindow.gettitle() + import macfs + fss, ok = macfs.StandardPutFile('Save %s text as:' % title, title + '.txt') + if not ok: + return + f = open(fss.as_pathname(), 'wb') + f.write(self.get()) + f.close() + fss.SetCreatorType(W._signature, 'TEXT') + + +class PyOutput: + + def __init__(self, bounds, show = 1, fontsettings = ("Monaco", 0, 9, (0, 0, 0)), tabsettings = (32, 0)): + self.bounds = bounds + self.fontsettings = fontsettings + self.tabsettings = tabsettings + self.w = None + self.closed = 1 + self._buf = '' + # should be able to set this + self.savestdout, self.savestderr = sys.stdout, sys.stderr + sys.stderr = sys.stdout = self + if show: + self.show() + + def setupwidgets(self): + self.w = W.Window(self.bounds, "Output", + minsize = (200, 100), + tabbable = 0) + self.w.outputtext = OutputTextWidget((-1, -1, -14, 1), inset = (6, 5), + fontsettings = self.fontsettings, tabsettings = self.tabsettings, readonly = 1) + menuitems = [("Clear window", self.clearbuffer), ("Font settingsÉ", self.dofontsettings)] + self.w.popupmenu = W.PopupMenu((-15, -1, 16, 16), menuitems) + + self.w._bary = W.Scrollbar((-15, 14, 16, -14), self.w.outputtext.vscroll, max = 32767) + self.w.bind("<close>", self.close) + self.w.bind("<activate>", self.activate) + + def write(self, text): + oldyield = MacOS.EnableAppswitch(-1) + try: + self._buf = self._buf + text + if '\n' in self._buf: + self.flush() + finally: + MacOS.EnableAppswitch(oldyield) + + def flush(self): + self.show() + stuff = string.split(self._buf, '\n') + stuff = string.join(stuff, '\r') + end = self.w.outputtext.ted.WEGetTextLength() + self.w.outputtext.setselection(end, end) + self.w.outputtext.ted.WEFeatureFlag(WASTEconst.weFReadOnly, 0) + self.w.outputtext.ted.WEInsert(stuff, None, None) + self._buf = "" + self.w.outputtext.updatescrollbars() + self.w.outputtext.ted.WEFeatureFlag(WASTEconst.weFReadOnly, 1) + + def show(self): + if self.closed: + if not self.w: + self.setupwidgets() + self.w.open() + self.w.outputtext.updatescrollbars() + self.closed = 0 + else: + self.w.show(1) + self.closed = 0 + self.w.select() + + def writeprefs(self): + if self.w is not None: + prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath) + prefs.output.show = self.w.isvisible() + prefs.output.windowbounds = self.w.getbounds() + prefs.output.fontsettings = self.w.outputtext.getfontsettings() + prefs.output.tabsettings = self.w.outputtext.gettabsettings() + prefs.save() + + def dofontsettings(self): + import FontSettings + settings = FontSettings.FontDialog(self.w.outputtext.getfontsettings(), + self.w.outputtext.gettabsettings()) + if settings: + fontsettings, tabsettings = settings + self.w.outputtext.setfontsettings(fontsettings) + self.w.outputtext.settabsettings(tabsettings) + + def clearbuffer(self): + import Res + self.w.outputtext.set('') + + def activate(self, onoff): + if onoff: + self.closed = 0 + + def close(self): + self.w.show(0) + self.closed = 1 + return -1 + + +class SimpleStdin: + + def readline(self): + import EasyDialogs + sys.stdout.flush() + rv = EasyDialogs.AskString("") + if rv is None: + return "" + return rv + '\n' + + +def installconsole(defaultshow = 1): + global console + prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath) + if not prefs.console or not hasattr(prefs.console, 'show'): + prefs.console.show = defaultshow + if not hasattr(prefs.console, "windowbounds"): + prefs.console.windowbounds = (450, 250) + if not hasattr(prefs.console, "fontsettings"): + prefs.console.fontsettings = ("Monaco", 0, 9, (0, 0, 0)) + if not hasattr(prefs.console, "tabsettings"): + prefs.console.tabsettings = (32, 0) + console = PyConsole(prefs.console.windowbounds, prefs.console.show, + prefs.console.fontsettings, prefs.console.tabsettings, 1) + +def installoutput(defaultshow = 0, OutPutWindow = PyOutput): + global output + + # quick 'n' dirty std in emulation + sys.stdin = SimpleStdin() + + prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath) + if not prefs.output or not hasattr(prefs.output, 'show'): + prefs.output.show = defaultshow + if not hasattr(prefs.output, "windowbounds"): + prefs.output.windowbounds = (450, 250) + if not hasattr(prefs.output, "fontsettings"): + prefs.output.fontsettings = ("Monaco", 0, 9, (0, 0, 0)) + if not hasattr(prefs.output, "tabsettings"): + prefs.output.tabsettings = (32, 0) + output = OutPutWindow(prefs.output.windowbounds, prefs.output.show, + prefs.output.fontsettings, prefs.output.tabsettings) |