home *** CD-ROM | disk | FTP | other *** search
/ MacHack 2000 / MacHack 2000.toast / pc / The Hacks / MacHacksBug / Python 1.5.2c1 / Mac / Tools / IDE / PyConsole.py < prev    next >
Encoding:
Python Source  |  2000-06-23  |  11.0 KB  |  381 lines

  1. import W
  2. import Wkeys
  3. import Fm
  4. import WASTEconst
  5. from types import *
  6. import Events
  7. import string
  8. import sys
  9. import traceback
  10. import MacOS
  11. import MacPrefs
  12. import Qd
  13. import PyInteractive
  14.  
  15. if not hasattr(sys, 'ps1'):
  16.     sys.ps1 = '>>> '
  17. if not hasattr(sys, 'ps2'):
  18.     sys.ps2 = '... '
  19.  
  20. def inspect(foo):            # JJS 1/25/99
  21.     "Launch the browser on the given object.  This is a general built-in function."
  22.     import PyBrowser
  23.     PyBrowser.Browser(foo)
  24.  
  25. class ConsoleTextWidget(W.EditText):
  26.     
  27.     def __init__(self, *args, **kwargs):
  28.         apply(W.EditText.__init__, (self,) + args, kwargs)
  29.         self._inputstart = 0
  30.         self._buf = ''
  31.         self.pyinteractive = PyInteractive.PyInteractive()
  32.     
  33.         import __main__
  34.         self._namespace = __main__.__dict__
  35.         self._namespace['inspect'] = inspect            # JJS 1/25/99
  36.     
  37.     def insert(self, text):
  38.         self.checkselection()
  39.         self.ted.WEInsert(text, None, None)
  40.         self.changed = 1
  41.         self.selchanged = 1
  42.     
  43.     def set_namespace(self, dict):
  44.         if type(dict) <> DictionaryType:
  45.             raise TypeError, "The namespace needs to be a dictionary"
  46.         if 'inspect' not in dict.keys(): dict['inspect'] = inspect            # JJS 1/25/99
  47.         self._namespace = dict
  48.     
  49.     def open(self):
  50.         W.EditText.open(self)
  51.         self.write('Python ' + sys.version + '\n' + sys.copyright + '\n')
  52.         self.write(sys.ps1)
  53.         self.flush()
  54.     
  55.     def key(self, char, event):
  56.         (what, message, when, where, modifiers) = event
  57.         if self._enabled and not modifiers & Events.cmdKey or char in Wkeys.arrowkeys:
  58.             if char not in Wkeys.navigationkeys:
  59.                 self.checkselection()
  60.             if char == Wkeys.enterkey:
  61.                 char = Wkeys.returnkey
  62.             selstart, selend = self.getselection()
  63.             if char == Wkeys.backspacekey:
  64.                 if selstart <= (self._inputstart - (selstart <> selend)):
  65.                     return
  66.             self.ted.WEKey(ord(char), modifiers)
  67.             if char not in Wkeys.navigationkeys:
  68.                 self.changed = 1
  69.             if char not in Wkeys.scrollkeys:
  70.                 self.selchanged = 1
  71.             self.updatescrollbars()
  72.             if char == Wkeys.returnkey:
  73.                 text = self.get()[self._inputstart:selstart]
  74.                 text = string.join(string.split(text, "\r"), "\n")
  75.                 saveyield = MacOS.EnableAppswitch(0)
  76.                 self.pyinteractive.executeline(text, self, self._namespace)
  77.                 MacOS.EnableAppswitch(saveyield)
  78.                 selstart, selend = self.getselection()
  79.                 self._inputstart = selstart
  80.     
  81.     def domenu_save_as(self, *args):
  82.         import macfs
  83.         fss, ok = macfs.StandardPutFile('Save console text as:', 'console.txt')
  84.         if not ok:
  85.             return
  86.         f = open(fss.as_pathname(), 'wb')
  87.         f.write(self.get())
  88.         f.close()
  89.         fss.SetCreatorType(W._signature, 'TEXT')
  90.     
  91.     def write(self, text):
  92.         self._buf = self._buf + text
  93.         if '\n' in self._buf:
  94.             self.flush()
  95.     
  96.     def flush(self):
  97.         stuff = string.split(self._buf, '\n')
  98.         stuff = string.join(stuff, '\r')
  99.         self.setselection_at_end()
  100.         self.ted.WEInsert(stuff, None, None)
  101.         selstart, selend = self.getselection()
  102.         self._inputstart = selstart
  103.         self._buf = ""
  104.         self.ted.WEClearUndo()
  105.         self.updatescrollbars()
  106.     
  107.     def selection_ok(self):
  108.         selstart, selend = self.getselection()
  109.         return not (selstart < self._inputstart or selend < self._inputstart)
  110.     
  111.     def checkselection(self):
  112.         if not self.selection_ok():
  113.             self.setselection_at_end()
  114.     
  115.     def setselection_at_end(self):
  116.         end = self.ted.WEGetTextLength()
  117.         self.setselection(end, end)
  118.         self.updatescrollbars()
  119.         
  120.     def domenu_cut(self, *args):
  121.         if not self.selection_ok():
  122.             return
  123.         W.EditText.domenu_cut(self)
  124.     
  125.     def domenu_paste(self, *args):
  126.         if not self.selection_ok():
  127.             self.setselection_at_end()
  128.         W.EditText.domenu_paste(self)
  129.     
  130.     def domenu_clear(self, *args):
  131.         if not self.selection_ok():
  132.             return
  133.         W.EditText.domenu_clear(self)
  134.  
  135.  
  136. class PyConsole(W.Window):
  137.     
  138.     def __init__(self, bounds, show = 1, fontsettings = ("Monaco", 0, 9, (0, 0, 0)), 
  139.             tabsettings = (32, 0), unclosable = 0):
  140.         W.Window.__init__(self,
  141.                     bounds, 
  142.                     "Python Interactive", 
  143.                     minsize = (200, 100), 
  144.                     tabbable = 0, 
  145.                     show = show)
  146.         
  147.         self._unclosable = unclosable
  148.         consoletext = ConsoleTextWidget((-1, -1, -14, 1), inset = (6, 5), 
  149.                 fontsettings = fontsettings, tabsettings = tabsettings)
  150.         self._bary = W.Scrollbar((-15, 14, 16, -14), consoletext.vscroll, max = 32767)
  151.         self.consoletext = consoletext
  152.         self.namespacemenu = W.PopupMenu((-15, -1, 16, 16), [], self.consoletext.set_namespace)
  153.         self.namespacemenu.bind('<click>', self.makenamespacemenu)
  154.         self.open()
  155.     
  156.     def makenamespacemenu(self, *args):
  157.         W.SetCursor('watch')
  158.         namespacelist = self.getnamespacelist()
  159.         self.namespacemenu.set([("Clear window", self.clearbuffer), ("Font settings…", self.dofontsettings), 
  160.                 ["Namespace"] + namespacelist, ("Browse namespace…", self.browsenamespace)])
  161.         currentname = self.consoletext._namespace["__name__"]
  162.         for i in range(len(namespacelist)):
  163.             if namespacelist[i][0] == currentname:
  164.                 break
  165.         else:
  166.             return
  167.         # XXX this functionality should be generally available in Wmenus
  168.         submenuid = self.namespacemenu.menu.menu.GetItemMark(3)
  169.         menu = self.namespacemenu.menu.bar.menus[submenuid]
  170.         menu.menu.CheckItem(i + 1, 1)
  171.     
  172.     def browsenamespace(self):
  173.         import PyBrowser, W
  174.         W.SetCursor('watch')
  175.         PyBrowser.Browser(self.consoletext._namespace, self.consoletext._namespace["__name__"])
  176.     
  177.     def clearbuffer(self):
  178.         import Res
  179.         self.consoletext.ted.WEUseText(Res.Resource(''))
  180.         self.consoletext.write(sys.ps1)
  181.         self.consoletext.flush()
  182.     
  183.     def getnamespacelist(self):
  184.         import os
  185.         import __main__
  186.         editors = filter(lambda x: x.__class__.__name__ == "Editor", self.parent._windows.values())
  187.         
  188.         namespaces = [ ("__main__",__main__.__dict__) ]
  189.         for ed in editors:
  190.             modname = os.path.splitext(ed.title)[0]
  191.             if sys.modules.has_key(modname):
  192.                 module = sys.modules[modname] 
  193.                 namespaces.append((modname, module.__dict__))
  194.             else:
  195.                 if ed.title[-3:] == '.py':
  196.                     modname = ed.title[:-3]
  197.                 else:
  198.                     modname = ed.title
  199.                 ed.globals["__name__"] = modname
  200.                 namespaces.append((modname, ed.globals))
  201.         return namespaces
  202.     
  203.     def dofontsettings(self):
  204.         import FontSettings
  205.         settings = FontSettings.FontDialog(self.consoletext.getfontsettings(),
  206.                 self.consoletext.gettabsettings())
  207.         if settings:
  208.             fontsettings, tabsettings = settings
  209.             self.consoletext.setfontsettings(fontsettings)
  210.             self.consoletext.settabsettings(tabsettings)
  211.     
  212.     def show(self, onoff = 1):
  213.         W.Window.show(self, onoff)
  214.         if onoff:
  215.             self.select()
  216.     
  217.     def close(self):
  218.         if self._unclosable:
  219.             self.show(0)
  220.             return -1
  221.         W.Window.close(self)
  222.     
  223.     def writeprefs(self):
  224.         prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath)
  225.         prefs.console.show = self.isvisible()
  226.         prefs.console.windowbounds = self.getbounds()
  227.         prefs.console.fontsettings = self.consoletext.getfontsettings()
  228.         prefs.console.tabsettings = self.consoletext.gettabsettings()
  229.         prefs.save()
  230.  
  231.  
  232. class OutputTextWidget(W.EditText):
  233.     
  234.     def domenu_save_as(self, *args):
  235.         title = self._parentwindow.gettitle()
  236.         import macfs
  237.         fss, ok = macfs.StandardPutFile('Save %s text as:' % title, title + '.txt')
  238.         if not ok:
  239.             return
  240.         f = open(fss.as_pathname(), 'wb')
  241.         f.write(self.get())
  242.         f.close()
  243.         fss.SetCreatorType(W._signature, 'TEXT')
  244.     
  245.  
  246. class PyOutput:
  247.     
  248.     def __init__(self, bounds, show = 1, fontsettings = ("Monaco", 0, 9, (0, 0, 0)), tabsettings = (32, 0)):
  249.         self.bounds = bounds
  250.         self.fontsettings = fontsettings
  251.         self.tabsettings = tabsettings
  252.         self.w = None
  253.         self.closed = 1
  254.         self._buf = ''
  255.         # should be able to set this
  256.         self.savestdout, self.savestderr = sys.stdout, sys.stderr
  257.         sys.stderr = sys.stdout = self
  258.         if show:
  259.             self.show()
  260.     
  261.     def setupwidgets(self):
  262.         self.w = W.Window(self.bounds, "Output", 
  263.                 minsize = (200, 100), 
  264.                 tabbable = 0)
  265.         self.w.outputtext = OutputTextWidget((-1, -1, -14, 1), inset = (6, 5), 
  266.                 fontsettings = self.fontsettings, tabsettings = self.tabsettings, readonly = 1)
  267.         menuitems = [("Clear window", self.clearbuffer), ("Font settings…", self.dofontsettings)]
  268.         self.w.popupmenu = W.PopupMenu((-15, -1, 16, 16), menuitems)
  269.         
  270.         self.w._bary = W.Scrollbar((-15, 14, 16, -14), self.w.outputtext.vscroll, max = 32767)
  271.         self.w.bind("<close>", self.close)
  272.         self.w.bind("<activate>", self.activate)
  273.     
  274.     def write(self, text):
  275.         oldyield = MacOS.EnableAppswitch(-1)
  276.         try:
  277.             self._buf = self._buf + text
  278.             if '\n' in self._buf:
  279.                 self.flush()
  280.         finally:
  281.             MacOS.EnableAppswitch(oldyield)
  282.     
  283.     def flush(self):
  284.         self.show()
  285.         stuff = string.split(self._buf, '\n')
  286.         stuff = string.join(stuff, '\r')
  287.         end = self.w.outputtext.ted.WEGetTextLength()
  288.         self.w.outputtext.setselection(end, end)
  289.         self.w.outputtext.ted.WEFeatureFlag(WASTEconst.weFReadOnly, 0)
  290.         self.w.outputtext.ted.WEInsert(stuff, None, None)
  291.         self._buf = ""
  292.         self.w.outputtext.updatescrollbars()
  293.         self.w.outputtext.ted.WEFeatureFlag(WASTEconst.weFReadOnly, 1)
  294.     
  295.     def show(self):
  296.         if self.closed:
  297.             if not self.w:
  298.                 self.setupwidgets()
  299.                 self.w.open()
  300.                 self.w.outputtext.updatescrollbars()
  301.                 self.closed = 0
  302.             else:
  303.                 self.w.show(1)
  304.                 self.closed = 0
  305.                 self.w.select()
  306.     
  307.     def writeprefs(self):
  308.         if self.w is not None:
  309.             prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath)
  310.             prefs.output.show = self.w.isvisible()
  311.             prefs.output.windowbounds = self.w.getbounds()
  312.             prefs.output.fontsettings = self.w.outputtext.getfontsettings()
  313.             prefs.output.tabsettings = self.w.outputtext.gettabsettings()
  314.             prefs.save()
  315.     
  316.     def dofontsettings(self):
  317.         import FontSettings
  318.         settings = FontSettings.FontDialog(self.w.outputtext.getfontsettings(),
  319.                 self.w.outputtext.gettabsettings())
  320.         if settings:
  321.             fontsettings, tabsettings = settings
  322.             self.w.outputtext.setfontsettings(fontsettings)
  323.             self.w.outputtext.settabsettings(tabsettings)
  324.     
  325.     def clearbuffer(self):
  326.         import Res
  327.         self.w.outputtext.set('')
  328.     
  329.     def activate(self, onoff):
  330.         if onoff:
  331.             self.closed = 0
  332.     
  333.     def close(self):
  334.         self.w.show(0)
  335.         self.closed = 1
  336.         return -1
  337.  
  338.  
  339. class SimpleStdin:
  340.     
  341.     def readline(self):
  342.         import EasyDialogs
  343.         sys.stdout.flush()
  344.         rv = EasyDialogs.AskString("")
  345.         if rv is None:
  346.             return ""
  347.         return rv + '\n'
  348.  
  349.  
  350. def installconsole(defaultshow = 1):
  351.     global console
  352.     prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath)
  353.     if not prefs.console or not hasattr(prefs.console, 'show'):
  354.         prefs.console.show = defaultshow
  355.     if not hasattr(prefs.console, "windowbounds"):
  356.         prefs.console.windowbounds = (450, 250)
  357.     if not hasattr(prefs.console, "fontsettings"):
  358.         prefs.console.fontsettings = ("Monaco", 0, 9, (0, 0, 0))
  359.     if not hasattr(prefs.console, "tabsettings"):
  360.         prefs.console.tabsettings = (32, 0)
  361.     console = PyConsole(prefs.console.windowbounds, prefs.console.show, 
  362.             prefs.console.fontsettings, prefs.console.tabsettings, 1)
  363.  
  364. def installoutput(defaultshow = 0, OutPutWindow = PyOutput):
  365.     global output
  366.     
  367.     # quick 'n' dirty std in emulation
  368.     sys.stdin = SimpleStdin()
  369.     
  370.     prefs = MacPrefs.GetPrefs(W.getapplication().preffilepath)
  371.     if not prefs.output or not hasattr(prefs.output, 'show'):
  372.         prefs.output.show = defaultshow
  373.     if not hasattr(prefs.output, "windowbounds"):
  374.         prefs.output.windowbounds = (450, 250)
  375.     if not hasattr(prefs.output, "fontsettings"):
  376.         prefs.output.fontsettings = ("Monaco", 0, 9, (0, 0, 0))
  377.     if not hasattr(prefs.output, "tabsettings"):
  378.         prefs.output.tabsettings = (32, 0)
  379.     output = OutPutWindow(prefs.output.windowbounds, prefs.output.show, 
  380.             prefs.output.fontsettings, prefs.output.tabsettings)
  381.