Updated PyCrust
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/branches/WX_2_4_BRANCH@18266 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -4,20 +4,21 @@ __author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
|||||||
__cvsid__ = "$Id$"
|
__cvsid__ = "$Id$"
|
||||||
__revision__ = "$Revision$"[11:-2]
|
__revision__ = "$Revision$"[11:-2]
|
||||||
|
|
||||||
from wxPython.wx import *
|
from wxPython import wx
|
||||||
from crust import CrustFrame
|
from crust import CrustFrame
|
||||||
|
|
||||||
|
True, False = 1, 0
|
||||||
|
|
||||||
class App(wxApp):
|
|
||||||
|
class App(wx.wxApp):
|
||||||
"""PyCrust standalone application."""
|
"""PyCrust standalone application."""
|
||||||
|
|
||||||
def OnInit(self):
|
def OnInit(self):
|
||||||
wxInitAllImageHandlers()
|
wx.wxInitAllImageHandlers()
|
||||||
locals = {'__app__': 'PyCrust Standalone Application'}
|
locals = {'__app__': 'PyCrust Standalone Application'}
|
||||||
self.crustFrame = CrustFrame(locals=locals)
|
self.crustFrame = CrustFrame(locals=locals)
|
||||||
self.crustFrame.SetSize((750, 525))
|
self.crustFrame.SetSize((750, 525))
|
||||||
self.crustFrame.Show(true)
|
self.crustFrame.Show(True)
|
||||||
self.crustFrame.crust.shell.SetFocus()
|
|
||||||
self.SetTopWindow(self.crustFrame)
|
self.SetTopWindow(self.crustFrame)
|
||||||
# Add the application object to the sys module's namespace.
|
# Add the application object to the sys module's namespace.
|
||||||
# This allows a shell user to do:
|
# This allows a shell user to do:
|
||||||
@@ -25,11 +26,11 @@ class App(wxApp):
|
|||||||
# >>> sys.application.whatever
|
# >>> sys.application.whatever
|
||||||
import sys
|
import sys
|
||||||
sys.application = self
|
sys.application = self
|
||||||
return true
|
return True
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
application = App(1)
|
application = App(0)
|
||||||
application.MainLoop()
|
application.MainLoop()
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
@@ -4,32 +4,34 @@ __author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
|||||||
__cvsid__ = "$Id$"
|
__cvsid__ = "$Id$"
|
||||||
__revision__ = "$Revision$"[11:-2]
|
__revision__ = "$Revision$"[11:-2]
|
||||||
|
|
||||||
from wxPython.wx import *
|
from wxPython import wx
|
||||||
from shell import ShellFrame
|
from shell import ShellFrame
|
||||||
|
|
||||||
|
True, False = 1, 0
|
||||||
|
|
||||||
class App(wxApp):
|
|
||||||
|
class App(wx.wxApp):
|
||||||
"""PyShell standalone application."""
|
"""PyShell standalone application."""
|
||||||
|
|
||||||
def OnInit(self):
|
def OnInit(self):
|
||||||
wxInitAllImageHandlers()
|
wx.wxInitAllImageHandlers()
|
||||||
locals = {'__app__': 'PyShell Standalone Application'}
|
locals = {'__app__': 'PyShell Standalone Application'}
|
||||||
self.shellFrame = ShellFrame(locals=locals)
|
self.shellFrame = ShellFrame(locals=locals)
|
||||||
self.shellFrame.SetSize((750, 525))
|
self.shellFrame.SetSize((750, 525))
|
||||||
self.shellFrame.Show(true)
|
self.shellFrame.Show(True)
|
||||||
self.shellFrame.shell.SetFocus()
|
|
||||||
self.SetTopWindow(self.shellFrame)
|
self.SetTopWindow(self.shellFrame)
|
||||||
|
self.shellFrame.shell.SetFocus()
|
||||||
# Add the application object to the sys module's namespace.
|
# Add the application object to the sys module's namespace.
|
||||||
# This allows a shell user to do:
|
# This allows a shell user to do:
|
||||||
# >>> import sys
|
# >>> import sys
|
||||||
# >>> sys.application.whatever
|
# >>> sys.application.whatever
|
||||||
import sys
|
import sys
|
||||||
sys.application = self
|
sys.application = self
|
||||||
return true
|
return True
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
application = App(1)
|
application = App(0)
|
||||||
application.MainLoop()
|
application.MainLoop()
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
@@ -4,31 +4,32 @@ __author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
|||||||
__cvsid__ = "$Id$"
|
__cvsid__ = "$Id$"
|
||||||
__revision__ = "$Revision$"[11:-2]
|
__revision__ = "$Revision$"[11:-2]
|
||||||
|
|
||||||
from wxPython.wx import *
|
from wxPython import wx
|
||||||
from shell import Shell
|
|
||||||
from filling import Filling
|
from filling import Filling
|
||||||
from version import VERSION
|
|
||||||
import os
|
import os
|
||||||
|
from shell import Shell
|
||||||
|
from shellmenu import ShellMenu
|
||||||
|
from version import VERSION
|
||||||
|
|
||||||
|
|
||||||
class Crust(wxSplitterWindow):
|
class Crust(wx.wxSplitterWindow):
|
||||||
"""PyCrust Crust based on wxSplitterWindow."""
|
"""PyCrust Crust based on wxSplitterWindow."""
|
||||||
|
|
||||||
name = 'PyCrust Crust'
|
name = 'PyCrust Crust'
|
||||||
revision = __revision__
|
revision = __revision__
|
||||||
|
|
||||||
def __init__(self, parent, id=-1, pos=wxDefaultPosition, \
|
def __init__(self, parent, id=-1, pos=wx.wxDefaultPosition,
|
||||||
size=wxDefaultSize, style=wxSP_3D, name='Crust Window', \
|
size=wx.wxDefaultSize, style=wx.wxSP_3D, name='Crust Window',
|
||||||
rootObject=None, rootLabel=None, rootIsNamespace=1, \
|
rootObject=None, rootLabel=None, rootIsNamespace=1,
|
||||||
intro='', locals=None, \
|
intro='', locals=None,
|
||||||
InterpClass=None, *args, **kwds):
|
InterpClass=None, *args, **kwds):
|
||||||
"""Create a PyCrust Crust instance."""
|
"""Create a PyCrust Crust instance."""
|
||||||
wxSplitterWindow.__init__(self, parent, id, pos, size, style, name)
|
wx.wxSplitterWindow.__init__(self, parent, id, pos, size, style, name)
|
||||||
self.shell = Shell(parent=self, introText=intro, \
|
self.shell = Shell(parent=self, introText=intro,
|
||||||
locals=locals, InterpClass=InterpClass, \
|
locals=locals, InterpClass=InterpClass,
|
||||||
*args, **kwds)
|
*args, **kwds)
|
||||||
self.filling = Filling(parent=self, \
|
self.filling = Filling(parent=self,
|
||||||
rootObject=self.shell.interp.locals, \
|
rootObject=self.shell.interp.locals,
|
||||||
rootLabel=rootLabel, rootIsNamespace=1)
|
rootLabel=rootLabel, rootIsNamespace=1)
|
||||||
"""Add 'filling' to the interpreter's locals."""
|
"""Add 'filling' to the interpreter's locals."""
|
||||||
self.shell.interp.locals['filling'] = self.filling
|
self.shell.interp.locals['filling'] = self.filling
|
||||||
@@ -36,33 +37,30 @@ class Crust(wxSplitterWindow):
|
|||||||
self.SetMinimumPaneSize(1)
|
self.SetMinimumPaneSize(1)
|
||||||
|
|
||||||
|
|
||||||
# Temporary hack to share menus between PyCrust and PyShell.
|
class CrustFrame(wx.wxFrame, ShellMenu):
|
||||||
from shell import ShellMenu
|
|
||||||
|
|
||||||
class CrustFrame(wxFrame, ShellMenu):
|
|
||||||
"""Frame containing all the PyCrust components."""
|
"""Frame containing all the PyCrust components."""
|
||||||
|
|
||||||
name = 'PyCrust Frame'
|
name = 'PyCrust Frame'
|
||||||
revision = __revision__
|
revision = __revision__
|
||||||
|
|
||||||
def __init__(self, parent=None, id=-1, title='PyCrust', \
|
def __init__(self, parent=None, id=-1, title='PyCrust',
|
||||||
pos=wxDefaultPosition, size=wxDefaultSize, \
|
pos=wx.wxDefaultPosition, size=wx.wxDefaultSize,
|
||||||
style=wxDEFAULT_FRAME_STYLE, \
|
style=wx.wxDEFAULT_FRAME_STYLE,
|
||||||
rootObject=None, rootLabel=None, rootIsNamespace=1, \
|
rootObject=None, rootLabel=None, rootIsNamespace=1,
|
||||||
locals=None, InterpClass=None, *args, **kwds):
|
locals=None, InterpClass=None, *args, **kwds):
|
||||||
"""Create a PyCrust CrustFrame instance."""
|
"""Create a PyCrust CrustFrame instance."""
|
||||||
wxFrame.__init__(self, parent, id, title, pos, size, style)
|
wx.wxFrame.__init__(self, parent, id, title, pos, size, style)
|
||||||
intro = 'Welcome To PyCrust %s - The Flakiest Python Shell' % VERSION
|
intro = 'Welcome To PyCrust %s - The Flakiest Python Shell' % VERSION
|
||||||
intro += '\nSponsored by Orbtech - Your source for Python programming expertise.'
|
intro += '\nSponsored by Orbtech - Your source for Python programming expertise.'
|
||||||
self.CreateStatusBar()
|
self.CreateStatusBar()
|
||||||
self.SetStatusText(intro.replace('\n', ', '))
|
self.SetStatusText(intro.replace('\n', ', '))
|
||||||
import images
|
import images
|
||||||
self.SetIcon(images.getPyCrustIcon())
|
self.SetIcon(images.getPyCrustIcon())
|
||||||
self.crust = Crust(parent=self, intro=intro, \
|
self.crust = Crust(parent=self, intro=intro,
|
||||||
rootObject=rootObject, \
|
rootObject=rootObject,
|
||||||
rootLabel=rootLabel, \
|
rootLabel=rootLabel,
|
||||||
rootIsNamespace=rootIsNamespace, \
|
rootIsNamespace=rootIsNamespace,
|
||||||
locals=locals, \
|
locals=locals,
|
||||||
InterpClass=InterpClass, *args, **kwds)
|
InterpClass=InterpClass, *args, **kwds)
|
||||||
# Override the filling so that status messages go to the status bar.
|
# Override the filling so that status messages go to the status bar.
|
||||||
self.crust.filling.fillingTree.setStatusText = self.SetStatusText
|
self.crust.filling.fillingTree.setStatusText = self.SetStatusText
|
||||||
@@ -75,7 +73,7 @@ class CrustFrame(wxFrame, ShellMenu):
|
|||||||
# Temporary hack to share menus between PyCrust and PyShell.
|
# Temporary hack to share menus between PyCrust and PyShell.
|
||||||
self.shell = self.crust.shell
|
self.shell = self.crust.shell
|
||||||
self.createMenus()
|
self.createMenus()
|
||||||
EVT_CLOSE(self, self.OnCloseWindow)
|
wx.EVT_CLOSE(self, self.OnCloseWindow)
|
||||||
|
|
||||||
def OnCloseWindow(self, event):
|
def OnCloseWindow(self, event):
|
||||||
self.crust.shell.destroy()
|
self.crust.shell.destroy()
|
||||||
|
@@ -5,8 +5,8 @@ __author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
|||||||
__cvsid__ = "$Id$"
|
__cvsid__ = "$Id$"
|
||||||
__revision__ = "$Revision$"[11:-2]
|
__revision__ = "$Revision$"[11:-2]
|
||||||
|
|
||||||
from wxPython.wx import *
|
from wxPython import wx
|
||||||
from wxPython.stc import *
|
from wxPython import stc
|
||||||
from version import VERSION
|
from version import VERSION
|
||||||
import inspect
|
import inspect
|
||||||
import introspect
|
import introspect
|
||||||
@@ -14,6 +14,8 @@ import keyword
|
|||||||
import sys
|
import sys
|
||||||
import types
|
import types
|
||||||
|
|
||||||
|
True, False = 1, 0
|
||||||
|
|
||||||
COMMONTYPES = [getattr(types, t) for t in dir(types) \
|
COMMONTYPES = [getattr(types, t) for t in dir(types) \
|
||||||
if not t.startswith('_') \
|
if not t.startswith('_') \
|
||||||
and t not in ('ClassType', 'InstanceType', 'ModuleType')]
|
and t not in ('ClassType', 'InstanceType', 'ModuleType')]
|
||||||
@@ -23,40 +25,40 @@ except AttributeError:
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class FillingTree(wxTreeCtrl):
|
class FillingTree(wx.wxTreeCtrl):
|
||||||
"""PyCrust FillingTree based on wxTreeCtrl."""
|
"""PyCrust FillingTree based on wxTreeCtrl."""
|
||||||
|
|
||||||
name = 'PyCrust Filling Tree'
|
name = 'PyCrust Filling Tree'
|
||||||
revision = __revision__
|
revision = __revision__
|
||||||
|
|
||||||
def __init__(self, parent, id=-1, pos=wxDefaultPosition, \
|
def __init__(self, parent, id=-1, pos=wx.wxDefaultPosition,
|
||||||
size=wxDefaultSize, style=wxTR_HAS_BUTTONS, \
|
size=wx.wxDefaultSize, style=wx.wxTR_HAS_BUTTONS,
|
||||||
rootObject=None, rootLabel=None, rootIsNamespace=0):
|
rootObject=None, rootLabel=None, rootIsNamespace=0):
|
||||||
"""Create a PyCrust FillingTree instance."""
|
"""Create a PyCrust FillingTree instance."""
|
||||||
wxTreeCtrl.__init__(self, parent, id, pos, size)
|
wx.wxTreeCtrl.__init__(self, parent, id, pos, size)
|
||||||
self.rootIsNamespace = rootIsNamespace
|
self.rootIsNamespace = rootIsNamespace
|
||||||
if not rootObject:
|
if not rootObject:
|
||||||
import __main__
|
import __main__
|
||||||
rootObject = __main__
|
rootObject = __main__
|
||||||
self.rootIsNamespace = 1
|
self.rootIsNamespace = 1
|
||||||
if not rootLabel: rootLabel = 'Ingredients'
|
if not rootLabel: rootLabel = 'Ingredients'
|
||||||
rootData = wxTreeItemData(rootObject)
|
rootData = wx.wxTreeItemData(rootObject)
|
||||||
self.root = self.AddRoot(rootLabel, -1, -1, rootData)
|
self.root = self.AddRoot(rootLabel, -1, -1, rootData)
|
||||||
self.SetItemHasChildren(self.root, self.hasChildren(self.root))
|
self.SetItemHasChildren(self.root, self.hasChildren(self.root))
|
||||||
EVT_TREE_ITEM_EXPANDING(self, self.GetId(), self.OnItemExpanding)
|
wx.EVT_TREE_ITEM_EXPANDING(self, self.GetId(), self.OnItemExpanding)
|
||||||
EVT_TREE_ITEM_COLLAPSED(self, self.GetId(), self.OnItemCollapsed)
|
wx.EVT_TREE_ITEM_COLLAPSED(self, self.GetId(), self.OnItemCollapsed)
|
||||||
EVT_TREE_SEL_CHANGED(self, self.GetId(), self.OnSelChanged)
|
wx.EVT_TREE_SEL_CHANGED(self, self.GetId(), self.OnSelChanged)
|
||||||
|
|
||||||
def hasChildren(self, o):
|
def hasChildren(self, o):
|
||||||
"""Return true if object has children."""
|
"""Return true if object has children."""
|
||||||
if self.getChildren(o):
|
if self.getChildren(o):
|
||||||
return true
|
return True
|
||||||
else:
|
else:
|
||||||
return false
|
return False
|
||||||
|
|
||||||
def getChildren(self, o):
|
def getChildren(self, o):
|
||||||
"""Return a dictionary with the attributes or contents of object."""
|
"""Return a dictionary with the attributes or contents of object."""
|
||||||
busy = wxBusyCursor()
|
busy = wx.wxBusyCursor()
|
||||||
otype = type(o)
|
otype = type(o)
|
||||||
if (otype is types.DictType) \
|
if (otype is types.DictType) \
|
||||||
or str(otype)[17:23] == 'BTrees' and hasattr(o, 'keys'):
|
or str(otype)[17:23] == 'BTrees' and hasattr(o, 'keys'):
|
||||||
@@ -78,7 +80,7 @@ class FillingTree(wxTreeCtrl):
|
|||||||
return d
|
return d
|
||||||
|
|
||||||
def OnItemExpanding(self, event):
|
def OnItemExpanding(self, event):
|
||||||
busy = wxBusyCursor()
|
busy = wx.wxBusyCursor()
|
||||||
selection = event.GetItem()
|
selection = event.GetItem()
|
||||||
if self.IsExpanded(selection):
|
if self.IsExpanded(selection):
|
||||||
return
|
return
|
||||||
@@ -100,18 +102,18 @@ class FillingTree(wxTreeCtrl):
|
|||||||
and (selection != self.root \
|
and (selection != self.root \
|
||||||
or (selection == self.root and not self.rootIsNamespace)):
|
or (selection == self.root and not self.rootIsNamespace)):
|
||||||
itemtext = repr(item)
|
itemtext = repr(item)
|
||||||
child = self.AppendItem(selection, itemtext, -1, -1, \
|
child = self.AppendItem(selection, itemtext, -1, -1,
|
||||||
wxTreeItemData(children[item]))
|
wx.wxTreeItemData(children[item]))
|
||||||
self.SetItemHasChildren(child, self.hasChildren(children[item]))
|
self.SetItemHasChildren(child, self.hasChildren(children[item]))
|
||||||
|
|
||||||
def OnItemCollapsed(self, event):
|
def OnItemCollapsed(self, event):
|
||||||
"""Remove all children from the item."""
|
"""Remove all children from the item."""
|
||||||
busy = wxBusyCursor()
|
busy = wx.wxBusyCursor()
|
||||||
item = event.GetItem()
|
item = event.GetItem()
|
||||||
self.DeleteChildren(item)
|
self.DeleteChildren(item)
|
||||||
|
|
||||||
def OnSelChanged(self, event):
|
def OnSelChanged(self, event):
|
||||||
busy = wxBusyCursor()
|
busy = wx.wxBusyCursor()
|
||||||
item = event.GetItem()
|
item = event.GetItem()
|
||||||
if item == self.root:
|
if item == self.root:
|
||||||
self.setText('')
|
self.setText('')
|
||||||
@@ -189,7 +191,7 @@ class FillingTree(wxTreeCtrl):
|
|||||||
print text
|
print text
|
||||||
|
|
||||||
|
|
||||||
if wxPlatform == '__WXMSW__':
|
if wx.wxPlatform == '__WXMSW__':
|
||||||
faces = { 'times' : 'Times New Roman',
|
faces = { 'times' : 'Times New Roman',
|
||||||
'mono' : 'Courier New',
|
'mono' : 'Courier New',
|
||||||
'helv' : 'Lucida Console',
|
'helv' : 'Lucida Console',
|
||||||
@@ -201,8 +203,8 @@ if wxPlatform == '__WXMSW__':
|
|||||||
}
|
}
|
||||||
# Versions of wxPython prior to 2.3.2 had a sizing bug on Win platform.
|
# Versions of wxPython prior to 2.3.2 had a sizing bug on Win platform.
|
||||||
# The font was 2 points too large. So we need to reduce the font size.
|
# The font was 2 points too large. So we need to reduce the font size.
|
||||||
if ((wxMAJOR_VERSION, wxMINOR_VERSION) == (2, 3) and wxRELEASE_NUMBER < 2) \
|
if ((wx.wxMAJOR_VERSION, wx.wxMINOR_VERSION) == (2, 3) and wx.wxRELEASE_NUMBER < 2) \
|
||||||
or (wxMAJOR_VERSION <= 2 and wxMINOR_VERSION <= 2):
|
or (wx.wxMAJOR_VERSION <= 2 and wx.wxMINOR_VERSION <= 2):
|
||||||
faces['size'] -= 2
|
faces['size'] -= 2
|
||||||
faces['lnsize'] -= 2
|
faces['lnsize'] -= 2
|
||||||
else: # GTK
|
else: # GTK
|
||||||
@@ -216,16 +218,16 @@ else: # GTK
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class FillingText(wxStyledTextCtrl):
|
class FillingText(stc.wxStyledTextCtrl):
|
||||||
"""PyCrust FillingText based on wxStyledTextCtrl."""
|
"""PyCrust FillingText based on wxStyledTextCtrl."""
|
||||||
|
|
||||||
name = 'PyCrust Filling Text'
|
name = 'PyCrust Filling Text'
|
||||||
revision = __revision__
|
revision = __revision__
|
||||||
|
|
||||||
def __init__(self, parent, id=-1, pos=wxDefaultPosition, \
|
def __init__(self, parent, id=-1, pos=wx.wxDefaultPosition,
|
||||||
size=wxDefaultSize, style=wxCLIP_CHILDREN):
|
size=wx.wxDefaultSize, style=wx.wxCLIP_CHILDREN):
|
||||||
"""Create a PyCrust FillingText instance."""
|
"""Create a PyCrust FillingText instance."""
|
||||||
wxStyledTextCtrl.__init__(self, parent, id, pos, size, style)
|
stc.wxStyledTextCtrl.__init__(self, parent, id, pos, size, style)
|
||||||
# Configure various defaults and user preferences.
|
# Configure various defaults and user preferences.
|
||||||
self.config()
|
self.config()
|
||||||
|
|
||||||
@@ -233,7 +235,7 @@ class FillingText(wxStyledTextCtrl):
|
|||||||
"""Configure shell based on user preferences."""
|
"""Configure shell based on user preferences."""
|
||||||
self.SetMarginWidth(1, 0)
|
self.SetMarginWidth(1, 0)
|
||||||
|
|
||||||
self.SetLexer(wxSTC_LEX_PYTHON)
|
self.SetLexer(stc.wxSTC_LEX_PYTHON)
|
||||||
self.SetKeyWords(0, ' '.join(keyword.kwlist))
|
self.SetKeyWords(0, ' '.join(keyword.kwlist))
|
||||||
|
|
||||||
self.setStyles(faces)
|
self.setStyles(faces)
|
||||||
@@ -250,51 +252,51 @@ class FillingText(wxStyledTextCtrl):
|
|||||||
"""Configure font size, typeface and color for lexer."""
|
"""Configure font size, typeface and color for lexer."""
|
||||||
|
|
||||||
# Default style
|
# Default style
|
||||||
self.StyleSetSpec(wxSTC_STYLE_DEFAULT, "face:%(mono)s,size:%(size)d" % faces)
|
self.StyleSetSpec(stc.wxSTC_STYLE_DEFAULT, "face:%(mono)s,size:%(size)d" % faces)
|
||||||
|
|
||||||
self.StyleClearAll()
|
self.StyleClearAll()
|
||||||
|
|
||||||
# Built in styles
|
# Built in styles
|
||||||
self.StyleSetSpec(wxSTC_STYLE_LINENUMBER, "back:#C0C0C0,face:%(mono)s,size:%(lnsize)d" % faces)
|
self.StyleSetSpec(stc.wxSTC_STYLE_LINENUMBER, "back:#C0C0C0,face:%(mono)s,size:%(lnsize)d" % faces)
|
||||||
self.StyleSetSpec(wxSTC_STYLE_CONTROLCHAR, "face:%(mono)s" % faces)
|
self.StyleSetSpec(stc.wxSTC_STYLE_CONTROLCHAR, "face:%(mono)s" % faces)
|
||||||
self.StyleSetSpec(wxSTC_STYLE_BRACELIGHT, "fore:#0000FF,back:#FFFF88")
|
self.StyleSetSpec(stc.wxSTC_STYLE_BRACELIGHT, "fore:#0000FF,back:#FFFF88")
|
||||||
self.StyleSetSpec(wxSTC_STYLE_BRACEBAD, "fore:#FF0000,back:#FFFF88")
|
self.StyleSetSpec(stc.wxSTC_STYLE_BRACEBAD, "fore:#FF0000,back:#FFFF88")
|
||||||
|
|
||||||
# Python styles
|
# Python styles
|
||||||
self.StyleSetSpec(wxSTC_P_DEFAULT, "face:%(mono)s" % faces)
|
self.StyleSetSpec(stc.wxSTC_P_DEFAULT, "face:%(mono)s" % faces)
|
||||||
self.StyleSetSpec(wxSTC_P_COMMENTLINE, "fore:#007F00,face:%(mono)s" % faces)
|
self.StyleSetSpec(stc.wxSTC_P_COMMENTLINE, "fore:#007F00,face:%(mono)s" % faces)
|
||||||
self.StyleSetSpec(wxSTC_P_NUMBER, "")
|
self.StyleSetSpec(stc.wxSTC_P_NUMBER, "")
|
||||||
self.StyleSetSpec(wxSTC_P_STRING, "fore:#7F007F,face:%(mono)s" % faces)
|
self.StyleSetSpec(stc.wxSTC_P_STRING, "fore:#7F007F,face:%(mono)s" % faces)
|
||||||
self.StyleSetSpec(wxSTC_P_CHARACTER, "fore:#7F007F,face:%(mono)s" % faces)
|
self.StyleSetSpec(stc.wxSTC_P_CHARACTER, "fore:#7F007F,face:%(mono)s" % faces)
|
||||||
self.StyleSetSpec(wxSTC_P_WORD, "fore:#00007F,bold")
|
self.StyleSetSpec(stc.wxSTC_P_WORD, "fore:#00007F,bold")
|
||||||
self.StyleSetSpec(wxSTC_P_TRIPLE, "fore:#7F0000")
|
self.StyleSetSpec(stc.wxSTC_P_TRIPLE, "fore:#7F0000")
|
||||||
self.StyleSetSpec(wxSTC_P_TRIPLEDOUBLE, "fore:#000033,back:#FFFFE8")
|
self.StyleSetSpec(stc.wxSTC_P_TRIPLEDOUBLE, "fore:#000033,back:#FFFFE8")
|
||||||
self.StyleSetSpec(wxSTC_P_CLASSNAME, "fore:#0000FF,bold")
|
self.StyleSetSpec(stc.wxSTC_P_CLASSNAME, "fore:#0000FF,bold")
|
||||||
self.StyleSetSpec(wxSTC_P_DEFNAME, "fore:#007F7F,bold")
|
self.StyleSetSpec(stc.wxSTC_P_DEFNAME, "fore:#007F7F,bold")
|
||||||
self.StyleSetSpec(wxSTC_P_OPERATOR, "")
|
self.StyleSetSpec(stc.wxSTC_P_OPERATOR, "")
|
||||||
self.StyleSetSpec(wxSTC_P_IDENTIFIER, "")
|
self.StyleSetSpec(stc.wxSTC_P_IDENTIFIER, "")
|
||||||
self.StyleSetSpec(wxSTC_P_COMMENTBLOCK, "fore:#7F7F7F")
|
self.StyleSetSpec(stc.wxSTC_P_COMMENTBLOCK, "fore:#7F7F7F")
|
||||||
self.StyleSetSpec(wxSTC_P_STRINGEOL, "fore:#000000,face:%(mono)s,back:#E0C0E0,eolfilled" % faces)
|
self.StyleSetSpec(stc.wxSTC_P_STRINGEOL, "fore:#000000,face:%(mono)s,back:#E0C0E0,eolfilled" % faces)
|
||||||
|
|
||||||
def SetText(self, *args, **kwds):
|
def SetText(self, *args, **kwds):
|
||||||
self.SetReadOnly(0)
|
self.SetReadOnly(0)
|
||||||
wxStyledTextCtrl.SetText(self, *args, **kwds)
|
stc.wxStyledTextCtrl.SetText(self, *args, **kwds)
|
||||||
self.SetReadOnly(1)
|
self.SetReadOnly(1)
|
||||||
|
|
||||||
|
|
||||||
class Filling(wxSplitterWindow):
|
class Filling(wx.wxSplitterWindow):
|
||||||
"""PyCrust Filling based on wxSplitterWindow."""
|
"""PyCrust Filling based on wxSplitterWindow."""
|
||||||
|
|
||||||
name = 'PyCrust Filling'
|
name = 'PyCrust Filling'
|
||||||
revision = __revision__
|
revision = __revision__
|
||||||
|
|
||||||
def __init__(self, parent, id=-1, pos=wxDefaultPosition, \
|
def __init__(self, parent, id=-1, pos=wx.wxDefaultPosition,
|
||||||
size=wxDefaultSize, style=wxSP_3D, name='Filling Window', \
|
size=wx.wxDefaultSize, style=wx.wxSP_3D, name='Filling Window',
|
||||||
rootObject=None, rootLabel=None, rootIsNamespace=0):
|
rootObject=None, rootLabel=None, rootIsNamespace=0):
|
||||||
"""Create a PyCrust Filling instance."""
|
"""Create a PyCrust Filling instance."""
|
||||||
wxSplitterWindow.__init__(self, parent, id, pos, size, style, name)
|
wx.wxSplitterWindow.__init__(self, parent, id, pos, size, style, name)
|
||||||
self.fillingTree = FillingTree(parent=self, rootObject=rootObject, \
|
self.fillingTree = FillingTree(parent=self, rootObject=rootObject,
|
||||||
rootLabel=rootLabel, \
|
rootLabel=rootLabel,
|
||||||
rootIsNamespace=rootIsNamespace)
|
rootIsNamespace=rootIsNamespace)
|
||||||
self.fillingText = FillingText(parent=self)
|
self.fillingText = FillingText(parent=self)
|
||||||
self.SplitVertically(self.fillingTree, self.fillingText, 200)
|
self.SplitVertically(self.fillingTree, self.fillingText, 200)
|
||||||
@@ -305,41 +307,41 @@ class Filling(wxSplitterWindow):
|
|||||||
self.fillingTree.SelectItem(self.fillingTree.root)
|
self.fillingTree.SelectItem(self.fillingTree.root)
|
||||||
|
|
||||||
|
|
||||||
class FillingFrame(wxFrame):
|
class FillingFrame(wx.wxFrame):
|
||||||
"""Frame containing the PyCrust filling, or namespace tree component."""
|
"""Frame containing the PyCrust filling, or namespace tree component."""
|
||||||
|
|
||||||
name = 'PyCrust Filling Frame'
|
name = 'PyCrust Filling Frame'
|
||||||
revision = __revision__
|
revision = __revision__
|
||||||
|
|
||||||
def __init__(self, parent=None, id=-1, title='PyFilling', \
|
def __init__(self, parent=None, id=-1, title='PyFilling',
|
||||||
pos=wxDefaultPosition, size=wxDefaultSize, \
|
pos=wx.wxDefaultPosition, size=wx.wxDefaultSize,
|
||||||
style=wxDEFAULT_FRAME_STYLE, rootObject=None, \
|
style=wx.wxDEFAULT_FRAME_STYLE, rootObject=None,
|
||||||
rootLabel=None, rootIsNamespace=0):
|
rootLabel=None, rootIsNamespace=0):
|
||||||
"""Create a PyCrust FillingFrame instance."""
|
"""Create a PyCrust FillingFrame instance."""
|
||||||
wxFrame.__init__(self, parent, id, title, pos, size, style)
|
wx.wxFrame.__init__(self, parent, id, title, pos, size, style)
|
||||||
intro = 'Welcome To PyFilling - The Tastiest Namespace Inspector'
|
intro = 'Welcome To PyFilling - The Tastiest Namespace Inspector'
|
||||||
self.CreateStatusBar()
|
self.CreateStatusBar()
|
||||||
self.SetStatusText(intro)
|
self.SetStatusText(intro)
|
||||||
if wxPlatform == '__WXMSW__':
|
if wx.wxPlatform == '__WXMSW__':
|
||||||
import os
|
import os
|
||||||
filename = os.path.join(os.path.dirname(__file__), 'PyCrust.ico')
|
filename = os.path.join(os.path.dirname(__file__), 'PyCrust.ico')
|
||||||
icon = wxIcon(filename, wxBITMAP_TYPE_ICO)
|
icon = wx.wxIcon(filename, wx.wxBITMAP_TYPE_ICO)
|
||||||
self.SetIcon(icon)
|
self.SetIcon(icon)
|
||||||
self.filling = Filling(parent=self, rootObject=rootObject, \
|
self.filling = Filling(parent=self, rootObject=rootObject,
|
||||||
rootLabel=rootLabel, \
|
rootLabel=rootLabel,
|
||||||
rootIsNamespace=rootIsNamespace)
|
rootIsNamespace=rootIsNamespace)
|
||||||
# Override the filling so that status messages go to the status bar.
|
# Override the filling so that status messages go to the status bar.
|
||||||
self.filling.fillingTree.setStatusText = self.SetStatusText
|
self.filling.fillingTree.setStatusText = self.SetStatusText
|
||||||
|
|
||||||
|
|
||||||
class App(wxApp):
|
class App(wx.wxApp):
|
||||||
"""PyFilling standalone application."""
|
"""PyFilling standalone application."""
|
||||||
|
|
||||||
def OnInit(self):
|
def OnInit(self):
|
||||||
self.fillingFrame = FillingFrame()
|
self.fillingFrame = FillingFrame()
|
||||||
self.fillingFrame.Show(true)
|
self.fillingFrame.Show(True)
|
||||||
self.SetTopWindow(self.fillingFrame)
|
self.SetTopWindow(self.fillingFrame)
|
||||||
return true
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@@ -15,7 +15,7 @@ class Interpreter(InteractiveInterpreter):
|
|||||||
|
|
||||||
revision = __revision__
|
revision = __revision__
|
||||||
|
|
||||||
def __init__(self, locals=None, rawin=None, \
|
def __init__(self, locals=None, rawin=None,
|
||||||
stdin=sys.stdin, stdout=sys.stdout, stderr=sys.stderr):
|
stdin=sys.stdin, stdout=sys.stdout, stderr=sys.stderr):
|
||||||
"""Create an interactive interpreter object."""
|
"""Create an interactive interpreter object."""
|
||||||
InteractiveInterpreter.__init__(self, locals=locals)
|
InteractiveInterpreter.__init__(self, locals=locals)
|
||||||
@@ -27,7 +27,7 @@ class Interpreter(InteractiveInterpreter):
|
|||||||
__builtin__.raw_input = rawin
|
__builtin__.raw_input = rawin
|
||||||
del __builtin__
|
del __builtin__
|
||||||
copyright = \
|
copyright = \
|
||||||
'Type "copyright", "credits" or "license" for more information.'
|
'Type "help", "copyright", "credits" or "license" for more information.'
|
||||||
self.introText = 'Python %s on %s%s%s' % \
|
self.introText = 'Python %s on %s%s%s' % \
|
||||||
(sys.version, sys.platform, os.linesep, copyright)
|
(sys.version, sys.platform, os.linesep, copyright)
|
||||||
try:
|
try:
|
||||||
@@ -98,10 +98,10 @@ class Interpreter(InteractiveInterpreter):
|
|||||||
class InterpreterAlaCarte(Interpreter):
|
class InterpreterAlaCarte(Interpreter):
|
||||||
"""PyCrustAlaCarte Demo Interpreter."""
|
"""PyCrustAlaCarte Demo Interpreter."""
|
||||||
|
|
||||||
def __init__(self, locals, rawin, stdin, stdout, stderr, \
|
def __init__(self, locals, rawin, stdin, stdout, stderr,
|
||||||
ps1='main prompt', ps2='continuation prompt'):
|
ps1='main prompt', ps2='continuation prompt'):
|
||||||
"""Create an interactive interpreter object."""
|
"""Create an interactive interpreter object."""
|
||||||
Interpreter.__init__(self, locals=locals, rawin=rawin, \
|
Interpreter.__init__(self, locals=locals, rawin=rawin,
|
||||||
stdin=stdin, stdout=stdout, stderr=stderr)
|
stdin=stdin, stdout=stdout, stderr=stderr)
|
||||||
sys.ps1 = ps1
|
sys.ps1 = ps1
|
||||||
sys.ps2 = ps2
|
sys.ps2 = ps2
|
||||||
|
@@ -5,11 +5,15 @@ __author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
|||||||
__cvsid__ = "$Id$"
|
__cvsid__ = "$Id$"
|
||||||
__revision__ = "$Revision$"[11:-2]
|
__revision__ = "$Revision$"[11:-2]
|
||||||
|
|
||||||
|
from __future__ import nested_scopes
|
||||||
|
|
||||||
|
import cStringIO
|
||||||
import inspect
|
import inspect
|
||||||
import string
|
import string
|
||||||
|
import tokenize
|
||||||
import types
|
import types
|
||||||
|
|
||||||
def getAutoCompleteList(command='', locals=None, includeMagic=1, \
|
def getAutoCompleteList(command='', locals=None, includeMagic=1,
|
||||||
includeSingle=1, includeDouble=1):
|
includeSingle=1, includeDouble=1):
|
||||||
"""Return list of auto-completion options for command.
|
"""Return list of auto-completion options for command.
|
||||||
|
|
||||||
@@ -25,7 +29,7 @@ def getAutoCompleteList(command='', locals=None, includeMagic=1, \
|
|||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
attributes = getAttributeNames(object, includeMagic, \
|
attributes = getAttributeNames(object, includeMagic,
|
||||||
includeSingle, includeDouble)
|
includeSingle, includeDouble)
|
||||||
return attributes
|
return attributes
|
||||||
|
|
||||||
@@ -36,8 +40,8 @@ def getAttributeNames(object, includeMagic=1, includeSingle=1, includeDouble=1):
|
|||||||
if not hasattrAlwaysReturnsTrue(object):
|
if not hasattrAlwaysReturnsTrue(object):
|
||||||
# Add some attributes that don't always get picked up.
|
# Add some attributes that don't always get picked up.
|
||||||
# If they don't apply, they'll get filtered out at the end.
|
# If they don't apply, they'll get filtered out at the end.
|
||||||
attributes += ['__bases__', '__class__', '__dict__', '__name__', \
|
attributes += ['__bases__', '__class__', '__dict__', '__name__',
|
||||||
'func_closure', 'func_code', 'func_defaults', \
|
'func_closure', 'func_code', 'func_defaults',
|
||||||
'func_dict', 'func_doc', 'func_globals', 'func_name']
|
'func_dict', 'func_doc', 'func_globals', 'func_name']
|
||||||
if includeMagic:
|
if includeMagic:
|
||||||
try: attributes += object._getAttributeNames()
|
try: attributes += object._getAttributeNames()
|
||||||
@@ -182,37 +186,83 @@ def getRoot(command, terminator=None):
|
|||||||
Return only the root portion that can be eval()'d without side effects.
|
Return only the root portion that can be eval()'d without side effects.
|
||||||
The command would normally terminate with a "(" or ".". The terminator
|
The command would normally terminate with a "(" or ".". The terminator
|
||||||
and anything after the terminator will be dropped."""
|
and anything after the terminator will be dropped."""
|
||||||
root = ''
|
|
||||||
validChars = "._" + string.uppercase + string.lowercase + string.digits
|
|
||||||
emptyTypes = ("''", '""', '""""""', "''''''", '[]', '()', '{}')
|
|
||||||
validSeparators = string.whitespace + ',+-*/=%<>&|^~:([{'
|
|
||||||
# Drop the final terminator and anything that follows.
|
|
||||||
command = rtrimTerminus(command, terminator)
|
command = rtrimTerminus(command, terminator)
|
||||||
if len(command) == 0:
|
command = command.rstrip()
|
||||||
root = ''
|
tokens = getTokens(command)
|
||||||
elif command in emptyTypes and terminator in ('.', '', None):
|
tokens.reverse()
|
||||||
# Let empty type delimiter pairs go through.
|
line = ''
|
||||||
root = command
|
start = None
|
||||||
else:
|
prefix = ''
|
||||||
# Go backward through the command until we hit an "invalid" character.
|
laststring = '.'
|
||||||
i = len(command)
|
emptyTypes = ('[]', '()', '{}')
|
||||||
while i and command[i-1] in validChars:
|
for token in tokens:
|
||||||
i -= 1
|
tokentype = token[0]
|
||||||
# Default to everything from the "invalid" character to the end.
|
tokenstring = token[1]
|
||||||
root = command[i:]
|
line = token[4]
|
||||||
# Override certain exceptions.
|
if tokentype is tokenize.ENDMARKER:
|
||||||
if i > 0 and command[i-1] in ("'", '"'):
|
continue
|
||||||
# Detect situations where we are in the middle of a string.
|
if tokentype in (tokenize.NAME, tokenize.STRING, tokenize.NUMBER) \
|
||||||
# This code catches the simplest case, but needs to catch others.
|
and laststring != '.':
|
||||||
root = ''
|
# We've reached something that's not part of the root.
|
||||||
elif ((2 <= i < len(command) and command[i] == '.') \
|
if prefix and line[token[3][1]] != ' ':
|
||||||
or (2 <= i <= len(command) and terminator in ('.', '', None))) \
|
# If it doesn't have a space after it, remove the prefix.
|
||||||
and command[i-2:i] in emptyTypes:
|
prefix = ''
|
||||||
# Allow empty types to get through.
|
break
|
||||||
# Don't confuse an empty tupple with an argumentless callable.
|
if tokentype in (tokenize.NAME, tokenize.STRING, tokenize.NUMBER) \
|
||||||
if i == 2 or (i >= 3 and command[i-3] in validSeparators):
|
or (tokentype is tokenize.OP and tokenstring == '.'):
|
||||||
root = command[i-2:]
|
if prefix:
|
||||||
return root
|
# The prefix isn't valid because it comes after a dot.
|
||||||
|
prefix = ''
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
# start represents the last known good point in the line.
|
||||||
|
start = token[2][1]
|
||||||
|
elif tokenstring in ('[({])}'):
|
||||||
|
# Remember, we're working backwords.
|
||||||
|
# So prefix += tokenstring would be wrong.
|
||||||
|
if prefix in emptyTypes and tokenstring in ('[({'):
|
||||||
|
# We've already got an empty type identified so now we are in
|
||||||
|
# a nested situation and we can break out with what we've got.
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
prefix = tokenstring + prefix
|
||||||
|
else:
|
||||||
|
# We've reached something that's not part of the root.
|
||||||
|
break
|
||||||
|
laststring = tokenstring
|
||||||
|
if start is None:
|
||||||
|
start = len(line)
|
||||||
|
root = line[start:]
|
||||||
|
if prefix in emptyTypes:
|
||||||
|
# Empty types are safe to be eval()'d and introspected.
|
||||||
|
root = prefix + root
|
||||||
|
return root
|
||||||
|
|
||||||
|
def getTokens(command):
|
||||||
|
"""Return list of token tuples for command."""
|
||||||
|
command = str(command) # In case the command is unicode, which won't work.
|
||||||
|
f = cStringIO.StringIO(command)
|
||||||
|
# tokens is a list of token tuples, each looking like:
|
||||||
|
# (type, string, (srow, scol), (erow, ecol), line)
|
||||||
|
tokens = []
|
||||||
|
# Can't use list comprehension:
|
||||||
|
# tokens = [token for token in tokenize.generate_tokens(f.readline)]
|
||||||
|
# because of need to append as much as possible before TokenError.
|
||||||
|
try:
|
||||||
|
## This code wasn't backward compatible with Python 2.1.3.
|
||||||
|
##
|
||||||
|
## for token in tokenize.generate_tokens(f.readline):
|
||||||
|
## tokens.append(token)
|
||||||
|
|
||||||
|
# This works with Python 2.1.3 (with nested_scopes).
|
||||||
|
def eater(*args):
|
||||||
|
tokens.append(args)
|
||||||
|
tokenize.tokenize_loop(f.readline, eater)
|
||||||
|
except tokenize.TokenError:
|
||||||
|
# This is due to a premature EOF, which we expect since
|
||||||
|
# we are feeding in fragments of Python code.
|
||||||
|
pass
|
||||||
|
return tokens
|
||||||
|
|
||||||
def rtrimTerminus(command, terminator=None):
|
def rtrimTerminus(command, terminator=None):
|
||||||
"""Return command minus the final terminator and anything that follows."""
|
"""Return command minus the final terminator and anything that follows."""
|
||||||
|
@@ -64,11 +64,13 @@ class PseudoFile:
|
|||||||
|
|
||||||
class PseudoFileIn(PseudoFile):
|
class PseudoFileIn(PseudoFile):
|
||||||
|
|
||||||
def __init__(self, readline):
|
def __init__(self, readline, readlines=None):
|
||||||
if callable(readline):
|
if callable(readline):
|
||||||
self.readline = readline
|
self.readline = readline
|
||||||
else:
|
else:
|
||||||
raise ValueError, 'readline must be callable'
|
raise ValueError, 'readline must be callable'
|
||||||
|
if callable(readlines):
|
||||||
|
self.readlines = readlines
|
||||||
|
|
||||||
def isatty(self):
|
def isatty(self):
|
||||||
return 1
|
return 1
|
||||||
|
@@ -8,21 +8,26 @@ __author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
|||||||
__cvsid__ = "$Id$"
|
__cvsid__ = "$Id$"
|
||||||
__revision__ = "$Revision$"[11:-2]
|
__revision__ = "$Revision$"[11:-2]
|
||||||
|
|
||||||
from wxPython.wx import *
|
from wxPython import wx
|
||||||
from wxPython.stc import *
|
from wxPython import stc
|
||||||
import keyword
|
import keyword
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
import time
|
||||||
from pseudo import PseudoFileIn
|
from pseudo import PseudoFileIn
|
||||||
from pseudo import PseudoFileOut
|
from pseudo import PseudoFileOut
|
||||||
from pseudo import PseudoFileErr
|
from pseudo import PseudoFileErr
|
||||||
|
from shellmenu import ShellMenu
|
||||||
from version import VERSION
|
from version import VERSION
|
||||||
|
|
||||||
|
True, False = 1, 0
|
||||||
|
|
||||||
sys.ps3 = '<-- ' # Input prompt.
|
sys.ps3 = '<-- ' # Input prompt.
|
||||||
|
|
||||||
NAVKEYS = (WXK_END, WXK_LEFT, WXK_RIGHT, WXK_UP, WXK_DOWN, WXK_PRIOR, WXK_NEXT)
|
NAVKEYS = (wx.WXK_END, wx.WXK_LEFT, wx.WXK_RIGHT,
|
||||||
|
wx.WXK_UP, wx.WXK_DOWN, wx.WXK_PRIOR, wx.WXK_NEXT)
|
||||||
|
|
||||||
if wxPlatform == '__WXMSW__':
|
if wx.wxPlatform == '__WXMSW__':
|
||||||
faces = { 'times' : 'Times New Roman',
|
faces = { 'times' : 'Times New Roman',
|
||||||
'mono' : 'Courier New',
|
'mono' : 'Courier New',
|
||||||
'helv' : 'Lucida Console',
|
'helv' : 'Lucida Console',
|
||||||
@@ -32,11 +37,6 @@ if wxPlatform == '__WXMSW__':
|
|||||||
'lnsize' : 9,
|
'lnsize' : 9,
|
||||||
'backcol': '#FFFFFF',
|
'backcol': '#FFFFFF',
|
||||||
}
|
}
|
||||||
# Versions of wxPython prior to 2.3.2 had a sizing bug on Win platform.
|
|
||||||
# The font was 2 points too large. So we need to reduce the font size.
|
|
||||||
if (wxMAJOR_VERSION, wxMINOR_VERSION, wxRELEASE_NUMBER) < (2, 3, 2):
|
|
||||||
faces['size'] -= 2
|
|
||||||
faces['lnsize'] -= 2
|
|
||||||
else: # GTK
|
else: # GTK
|
||||||
faces = { 'times' : 'Times',
|
faces = { 'times' : 'Times',
|
||||||
'mono' : 'Courier',
|
'mono' : 'Courier',
|
||||||
@@ -48,10 +48,42 @@ else: # GTK
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class ShellFrame(wx.wxFrame, ShellMenu):
|
||||||
|
"""Frame containing the PyCrust shell component."""
|
||||||
|
|
||||||
|
name = 'PyCrust Shell Frame'
|
||||||
|
revision = __revision__
|
||||||
|
|
||||||
|
def __init__(self, parent=None, id=-1, title='PyShell',
|
||||||
|
pos=wx.wxDefaultPosition, size=wx.wxDefaultSize,
|
||||||
|
style=wx.wxDEFAULT_FRAME_STYLE, locals=None,
|
||||||
|
InterpClass=None, *args, **kwds):
|
||||||
|
"""Create a PyCrust ShellFrame instance."""
|
||||||
|
wx.wxFrame.__init__(self, parent, id, title, pos, size, style)
|
||||||
|
intro = 'Welcome To PyCrust %s - The Flakiest Python Shell' % VERSION
|
||||||
|
intro += '\nSponsored by Orbtech - Your source for Python programming expertise.'
|
||||||
|
self.CreateStatusBar()
|
||||||
|
self.SetStatusText(intro.replace('\n', ', '))
|
||||||
|
filename = os.path.join(os.path.dirname(__file__), 'PyCrust.ico')
|
||||||
|
icon = wx.wxIcon(filename, wx.wxBITMAP_TYPE_ICO)
|
||||||
|
self.SetIcon(icon)
|
||||||
|
self.shell = Shell(parent=self, id=-1, introText=intro,
|
||||||
|
locals=locals, InterpClass=InterpClass,
|
||||||
|
*args, **kwds)
|
||||||
|
# Override the shell so that status messages go to the status bar.
|
||||||
|
self.shell.setStatusText = self.SetStatusText
|
||||||
|
self.createMenus()
|
||||||
|
wx.EVT_CLOSE(self, self.OnCloseWindow)
|
||||||
|
|
||||||
|
def OnCloseWindow(self, event):
|
||||||
|
self.shell.destroy()
|
||||||
|
self.Destroy()
|
||||||
|
|
||||||
|
|
||||||
class ShellFacade:
|
class ShellFacade:
|
||||||
"""Simplified interface to all shell-related functionality.
|
"""Simplified interface to all shell-related functionality.
|
||||||
|
|
||||||
This is a semi-transparent facade, in that all attributes of other are
|
This is a semi-transparent facade, in that all attributes of other are
|
||||||
still accessible, even though only some are visible to the user."""
|
still accessible, even though only some are visible to the user."""
|
||||||
|
|
||||||
name = 'PyCrust Shell Interface'
|
name = 'PyCrust Shell Interface'
|
||||||
@@ -59,19 +91,21 @@ class ShellFacade:
|
|||||||
|
|
||||||
def __init__(self, other):
|
def __init__(self, other):
|
||||||
"""Create a ShellFacade instance."""
|
"""Create a ShellFacade instance."""
|
||||||
methods = ['ask',
|
methods = [
|
||||||
'clear',
|
'about',
|
||||||
'pause',
|
'ask',
|
||||||
'prompt',
|
'clear',
|
||||||
'quit',
|
'pause',
|
||||||
'redirectStderr',
|
'prompt',
|
||||||
'redirectStdin',
|
'quit',
|
||||||
'redirectStdout',
|
'redirectStderr',
|
||||||
'run',
|
'redirectStdin',
|
||||||
'runfile',
|
'redirectStdout',
|
||||||
'wrap',
|
'run',
|
||||||
'zoom',
|
'runfile',
|
||||||
]
|
'wrap',
|
||||||
|
'zoom',
|
||||||
|
]
|
||||||
for method in methods:
|
for method in methods:
|
||||||
self.__dict__[method] = getattr(other, method)
|
self.__dict__[method] = getattr(other, method)
|
||||||
d = self.__dict__
|
d = self.__dict__
|
||||||
@@ -129,17 +163,17 @@ F8 Command-completion of History item.
|
|||||||
return list
|
return list
|
||||||
|
|
||||||
|
|
||||||
class Shell(wxStyledTextCtrl):
|
class Shell(stc.wxStyledTextCtrl):
|
||||||
"""PyCrust Shell based on wxStyledTextCtrl."""
|
"""PyCrust Shell based on wxStyledTextCtrl."""
|
||||||
|
|
||||||
name = 'PyCrust Shell'
|
name = 'PyCrust Shell'
|
||||||
revision = __revision__
|
revision = __revision__
|
||||||
|
|
||||||
def __init__(self, parent, id=-1, pos=wxDefaultPosition, \
|
def __init__(self, parent, id=-1, pos=wx.wxDefaultPosition,
|
||||||
size=wxDefaultSize, style=wxCLIP_CHILDREN, introText='', \
|
size=wx.wxDefaultSize, style=wx.wxCLIP_CHILDREN, introText='',
|
||||||
locals=None, InterpClass=None, *args, **kwds):
|
locals=None, InterpClass=None, *args, **kwds):
|
||||||
"""Create a PyCrust Shell instance."""
|
"""Create a PyCrust Shell instance."""
|
||||||
wxStyledTextCtrl.__init__(self, parent, id, pos, size, style)
|
stc.wxStyledTextCtrl.__init__(self, parent, id, pos, size, style)
|
||||||
# Grab these so they can be restored by self.redirect* methods.
|
# Grab these so they can be restored by self.redirect* methods.
|
||||||
self.stdin = sys.stdin
|
self.stdin = sys.stdin
|
||||||
self.stdout = sys.stdout
|
self.stdout = sys.stdout
|
||||||
@@ -160,15 +194,15 @@ class Shell(wxStyledTextCtrl):
|
|||||||
if locals:
|
if locals:
|
||||||
shellLocals.update(locals)
|
shellLocals.update(locals)
|
||||||
# Create a replacement for stdin.
|
# Create a replacement for stdin.
|
||||||
self.reader = PseudoFileIn(self.readline)
|
self.reader = PseudoFileIn(self.readline, self.readlines)
|
||||||
self.reader.input = ''
|
self.reader.input = ''
|
||||||
self.reader.isreading = 0
|
self.reader.isreading = 0
|
||||||
# Set up the interpreter.
|
# Set up the interpreter.
|
||||||
self.interp = Interpreter(locals=shellLocals, \
|
self.interp = Interpreter(locals=shellLocals,
|
||||||
rawin=self.raw_input, \
|
rawin=self.raw_input,
|
||||||
stdin=self.reader, \
|
stdin=self.reader,
|
||||||
stdout=PseudoFileOut(self.writeOut), \
|
stdout=PseudoFileOut(self.writeOut),
|
||||||
stderr=PseudoFileErr(self.writeErr), \
|
stderr=PseudoFileErr(self.writeErr),
|
||||||
*args, **kwds)
|
*args, **kwds)
|
||||||
# Find out for which keycodes the interpreter will autocomplete.
|
# Find out for which keycodes the interpreter will autocomplete.
|
||||||
self.autoCompleteKeys = self.interp.getAutoCompleteKeys()
|
self.autoCompleteKeys = self.interp.getAutoCompleteKeys()
|
||||||
@@ -186,10 +220,13 @@ class Shell(wxStyledTextCtrl):
|
|||||||
self.history = []
|
self.history = []
|
||||||
self.historyIndex = -1
|
self.historyIndex = -1
|
||||||
# Assign handlers for keyboard events.
|
# Assign handlers for keyboard events.
|
||||||
EVT_KEY_DOWN(self, self.OnKeyDown)
|
wx.EVT_KEY_DOWN(self, self.OnKeyDown)
|
||||||
EVT_CHAR(self, self.OnChar)
|
wx.EVT_CHAR(self, self.OnChar)
|
||||||
# Assign handlers for wxSTC events.
|
# Assign handlers for wxSTC events.
|
||||||
EVT_STC_UPDATEUI(self, id, self.OnUpdateUI)
|
stc.EVT_STC_UPDATEUI(self, id, self.OnUpdateUI)
|
||||||
|
# Assign handler for idle time.
|
||||||
|
self.waiting = False
|
||||||
|
wx.EVT_IDLE(self, self.OnIdle)
|
||||||
# Configure various defaults and user preferences.
|
# Configure various defaults and user preferences.
|
||||||
self.config()
|
self.config()
|
||||||
# Display the introductory banner information.
|
# Display the introductory banner information.
|
||||||
@@ -212,10 +249,10 @@ class Shell(wxStyledTextCtrl):
|
|||||||
|
|
||||||
def config(self):
|
def config(self):
|
||||||
"""Configure shell based on user preferences."""
|
"""Configure shell based on user preferences."""
|
||||||
self.SetMarginType(1, wxSTC_MARGIN_NUMBER)
|
self.SetMarginType(1, stc.wxSTC_MARGIN_NUMBER)
|
||||||
self.SetMarginWidth(1, 40)
|
self.SetMarginWidth(1, 40)
|
||||||
|
|
||||||
self.SetLexer(wxSTC_LEX_PYTHON)
|
self.SetLexer(stc.wxSTC_LEX_PYTHON)
|
||||||
self.SetKeyWords(0, ' '.join(keyword.kwlist))
|
self.SetKeyWords(0, ' '.join(keyword.kwlist))
|
||||||
|
|
||||||
self.setStyles(faces)
|
self.setStyles(faces)
|
||||||
@@ -231,10 +268,10 @@ class Shell(wxStyledTextCtrl):
|
|||||||
self.AutoCompSetIgnoreCase(self.autoCompleteCaseInsensitive)
|
self.AutoCompSetIgnoreCase(self.autoCompleteCaseInsensitive)
|
||||||
# Do we want to automatically pop up command argument help?
|
# Do we want to automatically pop up command argument help?
|
||||||
self.autoCallTip = 1
|
self.autoCallTip = 1
|
||||||
self.CallTipSetBackground(wxColour(255, 255, 232))
|
self.CallTipSetBackground(wx.wxColour(255, 255, 232))
|
||||||
self.wrap()
|
self.wrap()
|
||||||
try:
|
try:
|
||||||
self.SetEndAtLastLine(false)
|
self.SetEndAtLastLine(False)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@@ -247,7 +284,7 @@ class Shell(wxStyledTextCtrl):
|
|||||||
self.write(self.interp.introText)
|
self.write(self.interp.introText)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
pass
|
pass
|
||||||
wxCallAfter(self.ScrollToLine, 0)
|
wx.wxCallAfter(self.ScrollToLine, 0)
|
||||||
|
|
||||||
def setBuiltinKeywords(self):
|
def setBuiltinKeywords(self):
|
||||||
"""Create pseudo keywords as part of builtins.
|
"""Create pseudo keywords as part of builtins.
|
||||||
@@ -286,33 +323,50 @@ class Shell(wxStyledTextCtrl):
|
|||||||
"""Configure font size, typeface and color for lexer."""
|
"""Configure font size, typeface and color for lexer."""
|
||||||
|
|
||||||
# Default style
|
# Default style
|
||||||
self.StyleSetSpec(wxSTC_STYLE_DEFAULT, "face:%(mono)s,size:%(size)d,back:%(backcol)s" % faces)
|
self.StyleSetSpec(stc.wxSTC_STYLE_DEFAULT, "face:%(mono)s,size:%(size)d,back:%(backcol)s" % faces)
|
||||||
|
|
||||||
self.StyleClearAll()
|
self.StyleClearAll()
|
||||||
|
|
||||||
# Built in styles
|
# Built in styles
|
||||||
self.StyleSetSpec(wxSTC_STYLE_LINENUMBER, "back:#C0C0C0,face:%(mono)s,size:%(lnsize)d" % faces)
|
self.StyleSetSpec(stc.wxSTC_STYLE_LINENUMBER, "back:#C0C0C0,face:%(mono)s,size:%(lnsize)d" % faces)
|
||||||
self.StyleSetSpec(wxSTC_STYLE_CONTROLCHAR, "face:%(mono)s" % faces)
|
self.StyleSetSpec(stc.wxSTC_STYLE_CONTROLCHAR, "face:%(mono)s" % faces)
|
||||||
self.StyleSetSpec(wxSTC_STYLE_BRACELIGHT, "fore:#0000FF,back:#FFFF88")
|
self.StyleSetSpec(stc.wxSTC_STYLE_BRACELIGHT, "fore:#0000FF,back:#FFFF88")
|
||||||
self.StyleSetSpec(wxSTC_STYLE_BRACEBAD, "fore:#FF0000,back:#FFFF88")
|
self.StyleSetSpec(stc.wxSTC_STYLE_BRACEBAD, "fore:#FF0000,back:#FFFF88")
|
||||||
|
|
||||||
# Python styles
|
# Python styles
|
||||||
self.StyleSetSpec(wxSTC_P_DEFAULT, "face:%(mono)s" % faces)
|
self.StyleSetSpec(stc.wxSTC_P_DEFAULT, "face:%(mono)s" % faces)
|
||||||
self.StyleSetSpec(wxSTC_P_COMMENTLINE, "fore:#007F00,face:%(mono)s" % faces)
|
self.StyleSetSpec(stc.wxSTC_P_COMMENTLINE, "fore:#007F00,face:%(mono)s" % faces)
|
||||||
self.StyleSetSpec(wxSTC_P_NUMBER, "")
|
self.StyleSetSpec(stc.wxSTC_P_NUMBER, "")
|
||||||
self.StyleSetSpec(wxSTC_P_STRING, "fore:#7F007F,face:%(mono)s" % faces)
|
self.StyleSetSpec(stc.wxSTC_P_STRING, "fore:#7F007F,face:%(mono)s" % faces)
|
||||||
self.StyleSetSpec(wxSTC_P_CHARACTER, "fore:#7F007F,face:%(mono)s" % faces)
|
self.StyleSetSpec(stc.wxSTC_P_CHARACTER, "fore:#7F007F,face:%(mono)s" % faces)
|
||||||
self.StyleSetSpec(wxSTC_P_WORD, "fore:#00007F,bold")
|
self.StyleSetSpec(stc.wxSTC_P_WORD, "fore:#00007F,bold")
|
||||||
self.StyleSetSpec(wxSTC_P_TRIPLE, "fore:#7F0000")
|
self.StyleSetSpec(stc.wxSTC_P_TRIPLE, "fore:#7F0000")
|
||||||
self.StyleSetSpec(wxSTC_P_TRIPLEDOUBLE, "fore:#000033,back:#FFFFE8")
|
self.StyleSetSpec(stc.wxSTC_P_TRIPLEDOUBLE, "fore:#000033,back:#FFFFE8")
|
||||||
self.StyleSetSpec(wxSTC_P_CLASSNAME, "fore:#0000FF,bold")
|
self.StyleSetSpec(stc.wxSTC_P_CLASSNAME, "fore:#0000FF,bold")
|
||||||
self.StyleSetSpec(wxSTC_P_DEFNAME, "fore:#007F7F,bold")
|
self.StyleSetSpec(stc.wxSTC_P_DEFNAME, "fore:#007F7F,bold")
|
||||||
self.StyleSetSpec(wxSTC_P_OPERATOR, "")
|
self.StyleSetSpec(stc.wxSTC_P_OPERATOR, "")
|
||||||
self.StyleSetSpec(wxSTC_P_IDENTIFIER, "")
|
self.StyleSetSpec(stc.wxSTC_P_IDENTIFIER, "")
|
||||||
self.StyleSetSpec(wxSTC_P_COMMENTBLOCK, "fore:#7F7F7F")
|
self.StyleSetSpec(stc.wxSTC_P_COMMENTBLOCK, "fore:#7F7F7F")
|
||||||
self.StyleSetSpec(wxSTC_P_STRINGEOL, "fore:#000000,face:%(mono)s,back:#E0C0E0,eolfilled" % faces)
|
self.StyleSetSpec(stc.wxSTC_P_STRINGEOL, "fore:#000000,face:%(mono)s,back:#E0C0E0,eolfilled" % faces)
|
||||||
|
|
||||||
def OnUpdateUI(self, evt):
|
def about(self):
|
||||||
|
"""Display information about PyCrust."""
|
||||||
|
text = """
|
||||||
|
PyCrust Version: %s
|
||||||
|
Shell Revision: %s
|
||||||
|
Interpreter Revision: %s
|
||||||
|
Python Version: %s
|
||||||
|
wxPython Version: %s
|
||||||
|
Platform: %s""" % (VERSION, self.revision, self.interp.revision,
|
||||||
|
sys.version.split()[0], wx.__version__, sys.platform)
|
||||||
|
self.write(text.strip())
|
||||||
|
|
||||||
|
def OnIdle(self, event):
|
||||||
|
"""Free the CPU to do other things."""
|
||||||
|
if self.waiting:
|
||||||
|
time.sleep(0.1)
|
||||||
|
|
||||||
|
def OnUpdateUI(self, event):
|
||||||
"""Check for matching braces."""
|
"""Check for matching braces."""
|
||||||
braceAtCaret = -1
|
braceAtCaret = -1
|
||||||
braceOpposite = -1
|
braceOpposite = -1
|
||||||
@@ -328,7 +382,7 @@ class Shell(wxStyledTextCtrl):
|
|||||||
|
|
||||||
# Check before.
|
# Check before.
|
||||||
if charBefore and chr(charBefore) in '[]{}()' \
|
if charBefore and chr(charBefore) in '[]{}()' \
|
||||||
and styleBefore == wxSTC_P_OPERATOR:
|
and styleBefore == stc.wxSTC_P_OPERATOR:
|
||||||
braceAtCaret = caretPos - 1
|
braceAtCaret = caretPos - 1
|
||||||
|
|
||||||
# Check after.
|
# Check after.
|
||||||
@@ -340,7 +394,7 @@ class Shell(wxStyledTextCtrl):
|
|||||||
#***
|
#***
|
||||||
styleAfter = self.GetStyleAt(caretPos)
|
styleAfter = self.GetStyleAt(caretPos)
|
||||||
if charAfter and chr(charAfter) in '[]{}()' \
|
if charAfter and chr(charAfter) in '[]{}()' \
|
||||||
and styleAfter == wxSTC_P_OPERATOR:
|
and styleAfter == stc.wxSTC_P_OPERATOR:
|
||||||
braceAtCaret = caretPos
|
braceAtCaret = caretPos
|
||||||
|
|
||||||
if braceAtCaret >= 0:
|
if braceAtCaret >= 0:
|
||||||
@@ -353,7 +407,7 @@ class Shell(wxStyledTextCtrl):
|
|||||||
|
|
||||||
def OnChar(self, event):
|
def OnChar(self, event):
|
||||||
"""Keypress event handler.
|
"""Keypress event handler.
|
||||||
|
|
||||||
Only receives an event if OnKeyDown calls event.Skip() for
|
Only receives an event if OnKeyDown calls event.Skip() for
|
||||||
the corresponding event."""
|
the corresponding event."""
|
||||||
|
|
||||||
@@ -364,7 +418,7 @@ class Shell(wxStyledTextCtrl):
|
|||||||
currpos = self.GetCurrentPos()
|
currpos = self.GetCurrentPos()
|
||||||
stoppos = self.promptPosEnd
|
stoppos = self.promptPosEnd
|
||||||
# Return (Enter) needs to be ignored in this handler.
|
# Return (Enter) needs to be ignored in this handler.
|
||||||
if key == WXK_RETURN:
|
if key == wx.WXK_RETURN:
|
||||||
pass
|
pass
|
||||||
elif key in self.autoCompleteKeys:
|
elif key in self.autoCompleteKeys:
|
||||||
# Usually the dot (period) key activates auto completion.
|
# Usually the dot (period) key activates auto completion.
|
||||||
@@ -399,12 +453,12 @@ class Shell(wxStyledTextCtrl):
|
|||||||
endpos = self.GetTextLength()
|
endpos = self.GetTextLength()
|
||||||
selecting = self.GetSelectionStart() != self.GetSelectionEnd()
|
selecting = self.GetSelectionStart() != self.GetSelectionEnd()
|
||||||
# Return (Enter) is used to submit a command to the interpreter.
|
# Return (Enter) is used to submit a command to the interpreter.
|
||||||
if not controlDown and key == WXK_RETURN:
|
if not controlDown and key == wx.WXK_RETURN:
|
||||||
if self.AutoCompActive(): self.AutoCompCancel()
|
if self.AutoCompActive(): self.AutoCompCancel()
|
||||||
if self.CallTipActive(): self.CallTipCancel()
|
if self.CallTipActive(): self.CallTipCancel()
|
||||||
self.processLine()
|
self.processLine()
|
||||||
# Ctrl+Return (Cntrl+Enter) is used to insert a line break.
|
# Ctrl+Return (Cntrl+Enter) is used to insert a line break.
|
||||||
elif controlDown and key == WXK_RETURN:
|
elif controlDown and key == wx.WXK_RETURN:
|
||||||
if self.AutoCompActive(): self.AutoCompCancel()
|
if self.AutoCompActive(): self.AutoCompCancel()
|
||||||
if self.CallTipActive(): self.CallTipCancel()
|
if self.CallTipActive(): self.CallTipCancel()
|
||||||
if currpos == endpos:
|
if currpos == endpos:
|
||||||
@@ -418,25 +472,25 @@ class Shell(wxStyledTextCtrl):
|
|||||||
elif controlDown and altDown:
|
elif controlDown and altDown:
|
||||||
event.Skip()
|
event.Skip()
|
||||||
# Clear the current, unexecuted command.
|
# Clear the current, unexecuted command.
|
||||||
elif key == WXK_ESCAPE:
|
elif key == wx.WXK_ESCAPE:
|
||||||
if self.CallTipActive():
|
if self.CallTipActive():
|
||||||
event.Skip()
|
event.Skip()
|
||||||
else:
|
else:
|
||||||
self.clearCommand()
|
self.clearCommand()
|
||||||
# Cut to the clipboard.
|
# Cut to the clipboard.
|
||||||
elif (controlDown and key in (ord('X'), ord('x'))) \
|
elif (controlDown and key in (ord('X'), ord('x'))) \
|
||||||
or (shiftDown and key == WXK_DELETE):
|
or (shiftDown and key == wx.WXK_DELETE):
|
||||||
self.Cut()
|
self.Cut()
|
||||||
# Copy to the clipboard.
|
# Copy to the clipboard.
|
||||||
elif controlDown and not shiftDown \
|
elif controlDown and not shiftDown \
|
||||||
and key in (ord('C'), ord('c'), WXK_INSERT):
|
and key in (ord('C'), ord('c'), wx.WXK_INSERT):
|
||||||
self.Copy()
|
self.Copy()
|
||||||
# Copy to the clipboard, including prompts.
|
# Copy to the clipboard, including prompts.
|
||||||
elif controlDown and shiftDown \
|
elif controlDown and shiftDown \
|
||||||
and key in (ord('C'), ord('c'), WXK_INSERT):
|
and key in (ord('C'), ord('c'), wx.WXK_INSERT):
|
||||||
self.CopyWithPrompts()
|
self.CopyWithPrompts()
|
||||||
# Home needs to be aware of the prompt.
|
# Home needs to be aware of the prompt.
|
||||||
elif key == WXK_HOME:
|
elif key == wx.WXK_HOME:
|
||||||
home = self.promptPosEnd
|
home = self.promptPosEnd
|
||||||
if currpos > home:
|
if currpos > home:
|
||||||
self.SetCurrentPos(home)
|
self.SetCurrentPos(home)
|
||||||
@@ -455,41 +509,41 @@ class Shell(wxStyledTextCtrl):
|
|||||||
# Paste from the clipboard.
|
# Paste from the clipboard.
|
||||||
elif (controlDown and not shiftDown \
|
elif (controlDown and not shiftDown \
|
||||||
and key in (ord('V'), ord('v'))) \
|
and key in (ord('V'), ord('v'))) \
|
||||||
or (shiftDown and not controlDown and key == WXK_INSERT):
|
or (shiftDown and not controlDown and key == wx.WXK_INSERT):
|
||||||
self.Paste()
|
self.Paste()
|
||||||
# Paste from the clipboard, run commands.
|
# Paste from the clipboard, run commands.
|
||||||
elif controlDown and shiftDown \
|
elif controlDown and shiftDown \
|
||||||
and key in (ord('V'), ord('v')):
|
and key in (ord('V'), ord('v')):
|
||||||
self.PasteAndRun()
|
self.PasteAndRun()
|
||||||
# Replace with the previous command from the history buffer.
|
# Replace with the previous command from the history buffer.
|
||||||
elif (controlDown and key == WXK_UP) \
|
elif (controlDown and key == wx.WXK_UP) \
|
||||||
or (altDown and key in (ord('P'), ord('p'))):
|
or (altDown and key in (ord('P'), ord('p'))):
|
||||||
self.OnHistoryReplace(step=+1)
|
self.OnHistoryReplace(step=+1)
|
||||||
# Replace with the next command from the history buffer.
|
# Replace with the next command from the history buffer.
|
||||||
elif (controlDown and key == WXK_DOWN) \
|
elif (controlDown and key == wx.WXK_DOWN) \
|
||||||
or (altDown and key in (ord('N'), ord('n'))):
|
or (altDown and key in (ord('N'), ord('n'))):
|
||||||
self.OnHistoryReplace(step=-1)
|
self.OnHistoryReplace(step=-1)
|
||||||
# Insert the previous command from the history buffer.
|
# Insert the previous command from the history buffer.
|
||||||
elif (shiftDown and key == WXK_UP) and self.CanEdit():
|
elif (shiftDown and key == wx.WXK_UP) and self.CanEdit():
|
||||||
self.OnHistoryInsert(step=+1)
|
self.OnHistoryInsert(step=+1)
|
||||||
# Insert the next command from the history buffer.
|
# Insert the next command from the history buffer.
|
||||||
elif (shiftDown and key == WXK_DOWN) and self.CanEdit():
|
elif (shiftDown and key == wx.WXK_DOWN) and self.CanEdit():
|
||||||
self.OnHistoryInsert(step=-1)
|
self.OnHistoryInsert(step=-1)
|
||||||
# Search up the history for the text in front of the cursor.
|
# Search up the history for the text in front of the cursor.
|
||||||
elif key == WXK_F8:
|
elif key == wx.WXK_F8:
|
||||||
self.OnHistorySearch()
|
self.OnHistorySearch()
|
||||||
# Don't backspace over the latest non-continuation prompt.
|
# Don't backspace over the latest non-continuation prompt.
|
||||||
elif key == WXK_BACK:
|
elif key == wx.WXK_BACK:
|
||||||
if selecting and self.CanEdit():
|
if selecting and self.CanEdit():
|
||||||
event.Skip()
|
event.Skip()
|
||||||
elif currpos > self.promptPosEnd:
|
elif currpos > self.promptPosEnd:
|
||||||
event.Skip()
|
event.Skip()
|
||||||
# Only allow these keys after the latest prompt.
|
# Only allow these keys after the latest prompt.
|
||||||
elif key in (WXK_TAB, WXK_DELETE):
|
elif key in (wx.WXK_TAB, wx.WXK_DELETE):
|
||||||
if self.CanEdit():
|
if self.CanEdit():
|
||||||
event.Skip()
|
event.Skip()
|
||||||
# Don't toggle between insert mode and overwrite mode.
|
# Don't toggle between insert mode and overwrite mode.
|
||||||
elif key == WXK_INSERT:
|
elif key == wx.WXK_INSERT:
|
||||||
pass
|
pass
|
||||||
# Don't allow line deletion.
|
# Don't allow line deletion.
|
||||||
elif controlDown and key in (ord('L'), ord('l')):
|
elif controlDown and key in (ord('L'), ord('l')):
|
||||||
@@ -590,7 +644,7 @@ class Shell(wxStyledTextCtrl):
|
|||||||
# The user hit ENTER and we need to decide what to do. They could be
|
# The user hit ENTER and we need to decide what to do. They could be
|
||||||
# sitting on any line in the shell.
|
# sitting on any line in the shell.
|
||||||
|
|
||||||
thepos = self.GetCurrentPos()
|
thepos = self.GetCurrentPos()
|
||||||
startpos = self.promptPosEnd
|
startpos = self.promptPosEnd
|
||||||
endpos = self.GetTextLength()
|
endpos = self.GetTextLength()
|
||||||
# If they hit RETURN inside the current command, execute the command.
|
# If they hit RETURN inside the current command, execute the command.
|
||||||
@@ -685,12 +739,14 @@ class Shell(wxStyledTextCtrl):
|
|||||||
elif text[:ps2size] == ps2:
|
elif text[:ps2size] == ps2:
|
||||||
text = text[ps2size:]
|
text = text[ps2size:]
|
||||||
return text
|
return text
|
||||||
|
|
||||||
def push(self, command):
|
def push(self, command):
|
||||||
"""Send command to the interpreter for execution."""
|
"""Send command to the interpreter for execution."""
|
||||||
self.write(os.linesep)
|
self.write(os.linesep)
|
||||||
busy = wxBusyCursor()
|
busy = wx.wxBusyCursor()
|
||||||
|
self.waiting = True
|
||||||
self.more = self.interp.push(command)
|
self.more = self.interp.push(command)
|
||||||
|
self.waiting = False
|
||||||
del busy
|
del busy
|
||||||
if not self.more:
|
if not self.more:
|
||||||
self.addHistory(command.rstrip())
|
self.addHistory(command.rstrip())
|
||||||
@@ -765,13 +821,34 @@ class Shell(wxStyledTextCtrl):
|
|||||||
self.prompt()
|
self.prompt()
|
||||||
try:
|
try:
|
||||||
while not reader.input:
|
while not reader.input:
|
||||||
wxYield()
|
time.sleep(0.1) # Free up the CPU.
|
||||||
|
wx.wxYield()
|
||||||
input = reader.input
|
input = reader.input
|
||||||
finally:
|
finally:
|
||||||
reader.input = ''
|
reader.input = ''
|
||||||
reader.isreading = 0
|
reader.isreading = 0
|
||||||
return input
|
return input
|
||||||
|
|
||||||
|
def readlines(self):
|
||||||
|
"""Replacement for stdin.readlines()."""
|
||||||
|
lines = []
|
||||||
|
input = ''
|
||||||
|
reader = self.reader
|
||||||
|
reader.isreading = 1
|
||||||
|
try:
|
||||||
|
while lines[-1:] != ['\n']:
|
||||||
|
self.prompt()
|
||||||
|
while not reader.input:
|
||||||
|
time.sleep(0.1) # Free up the CPU.
|
||||||
|
wx.wxYield()
|
||||||
|
input = reader.input
|
||||||
|
lines.append(input)
|
||||||
|
reader.input = ''
|
||||||
|
finally:
|
||||||
|
reader.input = ''
|
||||||
|
reader.isreading = 0
|
||||||
|
return lines
|
||||||
|
|
||||||
def raw_input(self, prompt=''):
|
def raw_input(self, prompt=''):
|
||||||
"""Return string based on user input."""
|
"""Return string based on user input."""
|
||||||
if prompt:
|
if prompt:
|
||||||
@@ -780,10 +857,10 @@ class Shell(wxStyledTextCtrl):
|
|||||||
|
|
||||||
def ask(self, prompt='Please enter your response:'):
|
def ask(self, prompt='Please enter your response:'):
|
||||||
"""Get response from the user using a dialog box."""
|
"""Get response from the user using a dialog box."""
|
||||||
dialog = wxTextEntryDialog(None, prompt, \
|
dialog = wx.wxTextEntryDialog(None, prompt,
|
||||||
'Input Dialog (Raw)', '')
|
'Input Dialog (Raw)', '')
|
||||||
try:
|
try:
|
||||||
if dialog.ShowModal() == wxID_OK:
|
if dialog.ShowModal() == wx.wxID_OK:
|
||||||
text = dialog.GetValue()
|
text = dialog.GetValue()
|
||||||
return text
|
return text
|
||||||
finally:
|
finally:
|
||||||
@@ -803,11 +880,11 @@ class Shell(wxStyledTextCtrl):
|
|||||||
>>> shell.run('print "this"')
|
>>> shell.run('print "this"')
|
||||||
>>> print "this"
|
>>> print "this"
|
||||||
this
|
this
|
||||||
>>>
|
>>>
|
||||||
"""
|
"""
|
||||||
# Go to the very bottom of the text.
|
# Go to the very bottom of the text.
|
||||||
endpos = self.GetTextLength()
|
endpos = self.GetTextLength()
|
||||||
self.SetCurrentPos(endpos)
|
self.SetCurrentPos(endpos)
|
||||||
command = command.rstrip()
|
command = command.rstrip()
|
||||||
if prompt: self.prompt()
|
if prompt: self.prompt()
|
||||||
if verbose: self.write(command)
|
if verbose: self.write(command)
|
||||||
@@ -828,9 +905,9 @@ class Shell(wxStyledTextCtrl):
|
|||||||
|
|
||||||
def autoCompleteShow(self, command):
|
def autoCompleteShow(self, command):
|
||||||
"""Display auto-completion popup list."""
|
"""Display auto-completion popup list."""
|
||||||
list = self.interp.getAutoCompleteList(command,
|
list = self.interp.getAutoCompleteList(command,
|
||||||
includeMagic=self.autoCompleteIncludeMagic,
|
includeMagic=self.autoCompleteIncludeMagic,
|
||||||
includeSingle=self.autoCompleteIncludeSingle,
|
includeSingle=self.autoCompleteIncludeSingle,
|
||||||
includeDouble=self.autoCompleteIncludeDouble)
|
includeDouble=self.autoCompleteIncludeDouble)
|
||||||
if list:
|
if list:
|
||||||
options = ' '.join(list)
|
options = ' '.join(list)
|
||||||
@@ -898,7 +975,7 @@ class Shell(wxStyledTextCtrl):
|
|||||||
|
|
||||||
def CanPaste(self):
|
def CanPaste(self):
|
||||||
"""Return true if a paste should succeed."""
|
"""Return true if a paste should succeed."""
|
||||||
if self.CanEdit() and wxStyledTextCtrl.CanPaste(self):
|
if self.CanEdit() and stc.wxStyledTextCtrl.CanPaste(self):
|
||||||
return 1
|
return 1
|
||||||
else:
|
else:
|
||||||
return 0
|
return 0
|
||||||
@@ -929,26 +1006,28 @@ class Shell(wxStyledTextCtrl):
|
|||||||
command = command.replace(os.linesep + sys.ps2, os.linesep)
|
command = command.replace(os.linesep + sys.ps2, os.linesep)
|
||||||
command = command.replace(os.linesep + sys.ps1, os.linesep)
|
command = command.replace(os.linesep + sys.ps1, os.linesep)
|
||||||
command = self.lstripPrompt(text=command)
|
command = self.lstripPrompt(text=command)
|
||||||
data = wxTextDataObject(command)
|
data = wx.wxTextDataObject(command)
|
||||||
if wxTheClipboard.Open():
|
if wx.wxTheClipboard.Open():
|
||||||
wxTheClipboard.SetData(data)
|
wx.wxTheClipboard.UsePrimarySelection(False)
|
||||||
wxTheClipboard.Close()
|
wx.wxTheClipboard.SetData(data)
|
||||||
|
wx.wxTheClipboard.Close()
|
||||||
|
|
||||||
def CopyWithPrompts(self):
|
def CopyWithPrompts(self):
|
||||||
"""Copy selection, including prompts, and place it on the clipboard."""
|
"""Copy selection, including prompts, and place it on the clipboard."""
|
||||||
if self.CanCopy():
|
if self.CanCopy():
|
||||||
command = self.GetSelectedText()
|
command = self.GetSelectedText()
|
||||||
data = wxTextDataObject(command)
|
data = wx.wxTextDataObject(command)
|
||||||
if wxTheClipboard.Open():
|
if wx.wxTheClipboard.Open():
|
||||||
wxTheClipboard.SetData(data)
|
wx.wxTheClipboard.UsePrimarySelection(False)
|
||||||
wxTheClipboard.Close()
|
wx.wxTheClipboard.SetData(data)
|
||||||
|
wx.wxTheClipboard.Close()
|
||||||
|
|
||||||
def Paste(self):
|
def Paste(self):
|
||||||
"""Replace selection with clipboard contents."""
|
"""Replace selection with clipboard contents."""
|
||||||
if self.CanPaste() and wxTheClipboard.Open():
|
if self.CanPaste() and wx.wxTheClipboard.Open():
|
||||||
if wxTheClipboard.IsSupported(wxDataFormat(wxDF_TEXT)):
|
if wx.wxTheClipboard.IsSupported(wx.wxDataFormat(wx.wxDF_TEXT)):
|
||||||
data = wxTextDataObject()
|
data = wx.wxTextDataObject()
|
||||||
if wxTheClipboard.GetData(data):
|
if wx.wxTheClipboard.GetData(data):
|
||||||
self.ReplaceSelection('')
|
self.ReplaceSelection('')
|
||||||
command = data.GetText()
|
command = data.GetText()
|
||||||
command = command.rstrip()
|
command = command.rstrip()
|
||||||
@@ -958,14 +1037,14 @@ class Shell(wxStyledTextCtrl):
|
|||||||
command = command.replace(os.linesep, '\n')
|
command = command.replace(os.linesep, '\n')
|
||||||
command = command.replace('\n', os.linesep + sys.ps2)
|
command = command.replace('\n', os.linesep + sys.ps2)
|
||||||
self.write(command)
|
self.write(command)
|
||||||
wxTheClipboard.Close()
|
wx.wxTheClipboard.Close()
|
||||||
|
|
||||||
def PasteAndRun(self):
|
def PasteAndRun(self):
|
||||||
"""Replace selection with clipboard contents, run commands."""
|
"""Replace selection with clipboard contents, run commands."""
|
||||||
if wxTheClipboard.Open():
|
if wx.wxTheClipboard.Open():
|
||||||
if wxTheClipboard.IsSupported(wxDataFormat(wxDF_TEXT)):
|
if wx.wxTheClipboard.IsSupported(wx.wxDataFormat(wx.wxDF_TEXT)):
|
||||||
data = wxTextDataObject()
|
data = wx.wxTextDataObject()
|
||||||
if wxTheClipboard.GetData(data):
|
if wx.wxTheClipboard.GetData(data):
|
||||||
endpos = self.GetTextLength()
|
endpos = self.GetTextLength()
|
||||||
self.SetCurrentPos(endpos)
|
self.SetCurrentPos(endpos)
|
||||||
startpos = self.promptPosEnd
|
startpos = self.promptPosEnd
|
||||||
@@ -994,11 +1073,11 @@ class Shell(wxStyledTextCtrl):
|
|||||||
command += '\n'
|
command += '\n'
|
||||||
command += line
|
command += line
|
||||||
commands.append(command)
|
commands.append(command)
|
||||||
for command in commands:
|
for command in commands:
|
||||||
command = command.replace('\n', os.linesep + sys.ps2)
|
command = command.replace('\n', os.linesep + sys.ps2)
|
||||||
self.write(command)
|
self.write(command)
|
||||||
self.processLine()
|
self.processLine()
|
||||||
wxTheClipboard.Close()
|
wx.wxTheClipboard.Close()
|
||||||
|
|
||||||
def wrap(self, wrap=1):
|
def wrap(self, wrap=1):
|
||||||
"""Sets whether text is word wrapped."""
|
"""Sets whether text is word wrapped."""
|
||||||
@@ -1009,214 +1088,8 @@ class Shell(wxStyledTextCtrl):
|
|||||||
|
|
||||||
def zoom(self, points=0):
|
def zoom(self, points=0):
|
||||||
"""Set the zoom level.
|
"""Set the zoom level.
|
||||||
|
|
||||||
This number of points is added to the size of all fonts.
|
This number of points is added to the size of all fonts.
|
||||||
It may be positive to magnify or negative to reduce."""
|
It may be positive to magnify or negative to reduce."""
|
||||||
self.SetZoom(points)
|
self.SetZoom(points)
|
||||||
|
|
||||||
|
|
||||||
wxID_SELECTALL = NewId() # This *should* be defined by wxPython.
|
|
||||||
ID_AUTOCOMP = NewId()
|
|
||||||
ID_AUTOCOMP_SHOW = NewId()
|
|
||||||
ID_AUTOCOMP_INCLUDE_MAGIC = NewId()
|
|
||||||
ID_AUTOCOMP_INCLUDE_SINGLE = NewId()
|
|
||||||
ID_AUTOCOMP_INCLUDE_DOUBLE = NewId()
|
|
||||||
ID_CALLTIPS = NewId()
|
|
||||||
ID_CALLTIPS_SHOW = NewId()
|
|
||||||
|
|
||||||
|
|
||||||
class ShellMenu:
|
|
||||||
"""Mixin class to add standard menu items."""
|
|
||||||
|
|
||||||
def createMenus(self):
|
|
||||||
m = self.fileMenu = wxMenu()
|
|
||||||
m.AppendSeparator()
|
|
||||||
m.Append(wxID_EXIT, 'E&xit', 'Exit PyCrust')
|
|
||||||
|
|
||||||
m = self.editMenu = wxMenu()
|
|
||||||
m.Append(wxID_UNDO, '&Undo \tCtrl+Z', 'Undo the last action')
|
|
||||||
m.Append(wxID_REDO, '&Redo \tCtrl+Y', 'Redo the last undone action')
|
|
||||||
m.AppendSeparator()
|
|
||||||
m.Append(wxID_CUT, 'Cu&t \tCtrl+X', 'Cut the selection')
|
|
||||||
m.Append(wxID_COPY, '&Copy \tCtrl+C', 'Copy the selection')
|
|
||||||
m.Append(wxID_PASTE, '&Paste \tCtrl+V', 'Paste')
|
|
||||||
m.AppendSeparator()
|
|
||||||
m.Append(wxID_CLEAR, 'Cle&ar', 'Delete the selection')
|
|
||||||
m.Append(wxID_SELECTALL, 'Select A&ll', 'Select all text')
|
|
||||||
|
|
||||||
m = self.autocompMenu = wxMenu()
|
|
||||||
m.Append(ID_AUTOCOMP_SHOW, 'Show Auto Completion', \
|
|
||||||
'Show auto completion during dot syntax', 1)
|
|
||||||
m.Append(ID_AUTOCOMP_INCLUDE_MAGIC, 'Include Magic Attributes', \
|
|
||||||
'Include attributes visible to __getattr__ and __setattr__', 1)
|
|
||||||
m.Append(ID_AUTOCOMP_INCLUDE_SINGLE, 'Include Single Underscores', \
|
|
||||||
'Include attibutes prefixed by a single underscore', 1)
|
|
||||||
m.Append(ID_AUTOCOMP_INCLUDE_DOUBLE, 'Include Double Underscores', \
|
|
||||||
'Include attibutes prefixed by a double underscore', 1)
|
|
||||||
|
|
||||||
m = self.calltipsMenu = wxMenu()
|
|
||||||
m.Append(ID_CALLTIPS_SHOW, 'Show Call Tips', \
|
|
||||||
'Show call tips with argument specifications', 1)
|
|
||||||
|
|
||||||
m = self.optionsMenu = wxMenu()
|
|
||||||
m.AppendMenu(ID_AUTOCOMP, '&Auto Completion', self.autocompMenu, \
|
|
||||||
'Auto Completion Options')
|
|
||||||
m.AppendMenu(ID_CALLTIPS, '&Call Tips', self.calltipsMenu, \
|
|
||||||
'Call Tip Options')
|
|
||||||
|
|
||||||
m = self.helpMenu = wxMenu()
|
|
||||||
m.AppendSeparator()
|
|
||||||
m.Append(wxID_ABOUT, '&About...', 'About PyCrust')
|
|
||||||
|
|
||||||
b = self.menuBar = wxMenuBar()
|
|
||||||
b.Append(self.fileMenu, '&File')
|
|
||||||
b.Append(self.editMenu, '&Edit')
|
|
||||||
b.Append(self.optionsMenu, '&Options')
|
|
||||||
b.Append(self.helpMenu, '&Help')
|
|
||||||
self.SetMenuBar(b)
|
|
||||||
|
|
||||||
EVT_MENU(self, wxID_EXIT, self.OnExit)
|
|
||||||
EVT_MENU(self, wxID_UNDO, self.OnUndo)
|
|
||||||
EVT_MENU(self, wxID_REDO, self.OnRedo)
|
|
||||||
EVT_MENU(self, wxID_CUT, self.OnCut)
|
|
||||||
EVT_MENU(self, wxID_COPY, self.OnCopy)
|
|
||||||
EVT_MENU(self, wxID_PASTE, self.OnPaste)
|
|
||||||
EVT_MENU(self, wxID_CLEAR, self.OnClear)
|
|
||||||
EVT_MENU(self, wxID_SELECTALL, self.OnSelectAll)
|
|
||||||
EVT_MENU(self, wxID_ABOUT, self.OnAbout)
|
|
||||||
EVT_MENU(self, ID_AUTOCOMP_SHOW, \
|
|
||||||
self.OnAutoCompleteShow)
|
|
||||||
EVT_MENU(self, ID_AUTOCOMP_INCLUDE_MAGIC, \
|
|
||||||
self.OnAutoCompleteIncludeMagic)
|
|
||||||
EVT_MENU(self, ID_AUTOCOMP_INCLUDE_SINGLE, \
|
|
||||||
self.OnAutoCompleteIncludeSingle)
|
|
||||||
EVT_MENU(self, ID_AUTOCOMP_INCLUDE_DOUBLE, \
|
|
||||||
self.OnAutoCompleteIncludeDouble)
|
|
||||||
EVT_MENU(self, ID_CALLTIPS_SHOW, \
|
|
||||||
self.OnCallTipsShow)
|
|
||||||
|
|
||||||
EVT_UPDATE_UI(self, wxID_UNDO, self.OnUpdateMenu)
|
|
||||||
EVT_UPDATE_UI(self, wxID_REDO, self.OnUpdateMenu)
|
|
||||||
EVT_UPDATE_UI(self, wxID_CUT, self.OnUpdateMenu)
|
|
||||||
EVT_UPDATE_UI(self, wxID_COPY, self.OnUpdateMenu)
|
|
||||||
EVT_UPDATE_UI(self, wxID_PASTE, self.OnUpdateMenu)
|
|
||||||
EVT_UPDATE_UI(self, wxID_CLEAR, self.OnUpdateMenu)
|
|
||||||
EVT_UPDATE_UI(self, ID_AUTOCOMP_SHOW, self.OnUpdateMenu)
|
|
||||||
EVT_UPDATE_UI(self, ID_AUTOCOMP_INCLUDE_MAGIC, self.OnUpdateMenu)
|
|
||||||
EVT_UPDATE_UI(self, ID_AUTOCOMP_INCLUDE_SINGLE, self.OnUpdateMenu)
|
|
||||||
EVT_UPDATE_UI(self, ID_AUTOCOMP_INCLUDE_DOUBLE, self.OnUpdateMenu)
|
|
||||||
EVT_UPDATE_UI(self, ID_CALLTIPS_SHOW, self.OnUpdateMenu)
|
|
||||||
|
|
||||||
def OnExit(self, event):
|
|
||||||
self.Close(true)
|
|
||||||
|
|
||||||
def OnUndo(self, event):
|
|
||||||
self.shell.Undo()
|
|
||||||
|
|
||||||
def OnRedo(self, event):
|
|
||||||
self.shell.Redo()
|
|
||||||
|
|
||||||
def OnCut(self, event):
|
|
||||||
self.shell.Cut()
|
|
||||||
|
|
||||||
def OnCopy(self, event):
|
|
||||||
self.shell.Copy()
|
|
||||||
|
|
||||||
def OnPaste(self, event):
|
|
||||||
self.shell.Paste()
|
|
||||||
|
|
||||||
def OnClear(self, event):
|
|
||||||
self.shell.Clear()
|
|
||||||
|
|
||||||
def OnSelectAll(self, event):
|
|
||||||
self.shell.SelectAll()
|
|
||||||
|
|
||||||
def OnAbout(self, event):
|
|
||||||
"""Display an About PyCrust window."""
|
|
||||||
import sys
|
|
||||||
title = 'About PyCrust'
|
|
||||||
text = 'PyCrust %s\n\n' % VERSION + \
|
|
||||||
'Yet another Python shell, only flakier.\n\n' + \
|
|
||||||
'Half-baked by Patrick K. O\'Brien,\n' + \
|
|
||||||
'the other half is still in the oven.\n\n' + \
|
|
||||||
'Shell Revision: %s\n' % self.shell.revision + \
|
|
||||||
'Interpreter Revision: %s\n\n' % self.shell.interp.revision + \
|
|
||||||
'Python Version: %s\n' % sys.version.split()[0] + \
|
|
||||||
'wxPython Version: %s\n' % wx.__version__ + \
|
|
||||||
'Platform: %s\n' % sys.platform
|
|
||||||
dialog = wxMessageDialog(self, text, title, wxOK | wxICON_INFORMATION)
|
|
||||||
dialog.ShowModal()
|
|
||||||
dialog.Destroy()
|
|
||||||
|
|
||||||
def OnAutoCompleteShow(self, event):
|
|
||||||
self.shell.autoComplete = event.IsChecked()
|
|
||||||
|
|
||||||
def OnAutoCompleteIncludeMagic(self, event):
|
|
||||||
self.shell.autoCompleteIncludeMagic = event.IsChecked()
|
|
||||||
|
|
||||||
def OnAutoCompleteIncludeSingle(self, event):
|
|
||||||
self.shell.autoCompleteIncludeSingle = event.IsChecked()
|
|
||||||
|
|
||||||
def OnAutoCompleteIncludeDouble(self, event):
|
|
||||||
self.shell.autoCompleteIncludeDouble = event.IsChecked()
|
|
||||||
|
|
||||||
def OnCallTipsShow(self, event):
|
|
||||||
self.shell.autoCallTip = event.IsChecked()
|
|
||||||
|
|
||||||
def OnUpdateMenu(self, event):
|
|
||||||
"""Update menu items based on current status."""
|
|
||||||
id = event.GetId()
|
|
||||||
if id == wxID_UNDO:
|
|
||||||
event.Enable(self.shell.CanUndo())
|
|
||||||
elif id == wxID_REDO:
|
|
||||||
event.Enable(self.shell.CanRedo())
|
|
||||||
elif id == wxID_CUT:
|
|
||||||
event.Enable(self.shell.CanCut())
|
|
||||||
elif id == wxID_COPY:
|
|
||||||
event.Enable(self.shell.CanCopy())
|
|
||||||
elif id == wxID_PASTE:
|
|
||||||
event.Enable(self.shell.CanPaste())
|
|
||||||
elif id == wxID_CLEAR:
|
|
||||||
event.Enable(self.shell.CanCut())
|
|
||||||
elif id == ID_AUTOCOMP_SHOW:
|
|
||||||
event.Check(self.shell.autoComplete)
|
|
||||||
elif id == ID_AUTOCOMP_INCLUDE_MAGIC:
|
|
||||||
event.Check(self.shell.autoCompleteIncludeMagic)
|
|
||||||
elif id == ID_AUTOCOMP_INCLUDE_SINGLE:
|
|
||||||
event.Check(self.shell.autoCompleteIncludeSingle)
|
|
||||||
elif id == ID_AUTOCOMP_INCLUDE_DOUBLE:
|
|
||||||
event.Check(self.shell.autoCompleteIncludeDouble)
|
|
||||||
elif id == ID_CALLTIPS_SHOW:
|
|
||||||
event.Check(self.shell.autoCallTip)
|
|
||||||
|
|
||||||
|
|
||||||
class ShellFrame(wxFrame, ShellMenu):
|
|
||||||
"""Frame containing the PyCrust shell component."""
|
|
||||||
|
|
||||||
name = 'PyCrust Shell Frame'
|
|
||||||
revision = __revision__
|
|
||||||
|
|
||||||
def __init__(self, parent=None, id=-1, title='PyShell', \
|
|
||||||
pos=wxDefaultPosition, size=wxDefaultSize, \
|
|
||||||
style=wxDEFAULT_FRAME_STYLE, locals=None, \
|
|
||||||
InterpClass=None, *args, **kwds):
|
|
||||||
"""Create a PyCrust ShellFrame instance."""
|
|
||||||
wxFrame.__init__(self, parent, id, title, pos, size, style)
|
|
||||||
intro = 'Welcome To PyCrust %s - The Flakiest Python Shell' % VERSION
|
|
||||||
intro += '\nSponsored by Orbtech - Your source for Python programming expertise.'
|
|
||||||
self.CreateStatusBar()
|
|
||||||
self.SetStatusText(intro.replace('\n', ', '))
|
|
||||||
import images
|
|
||||||
self.SetIcon(images.getPyCrustIcon())
|
|
||||||
self.shell = Shell(parent=self, id=-1, introText=intro, \
|
|
||||||
locals=locals, InterpClass=InterpClass, \
|
|
||||||
*args, **kwds)
|
|
||||||
# Override the shell so that status messages go to the status bar.
|
|
||||||
self.shell.setStatusText = self.SetStatusText
|
|
||||||
self.createMenus()
|
|
||||||
EVT_CLOSE(self, self.OnCloseWindow)
|
|
||||||
|
|
||||||
def OnCloseWindow(self, event):
|
|
||||||
self.shell.destroy()
|
|
||||||
self.Destroy()
|
|
||||||
|
|
||||||
|
213
wxPython/wxPython/lib/PyCrust/shellmenu.py
Normal file
213
wxPython/wxPython/lib/PyCrust/shellmenu.py
Normal file
@@ -0,0 +1,213 @@
|
|||||||
|
"""Shell menu mixin shared by shell and crust."""
|
||||||
|
|
||||||
|
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
||||||
|
__cvsid__ = "$Id$"
|
||||||
|
__revision__ = "$Revision$"[11:-2]
|
||||||
|
|
||||||
|
from wxPython import wx
|
||||||
|
import sys
|
||||||
|
from version import VERSION
|
||||||
|
|
||||||
|
|
||||||
|
True, False = 1, 0
|
||||||
|
|
||||||
|
ID_AUTOCOMP = wx.NewId()
|
||||||
|
ID_AUTOCOMP_SHOW = wx.NewId()
|
||||||
|
ID_AUTOCOMP_INCLUDE_MAGIC = wx.NewId()
|
||||||
|
ID_AUTOCOMP_INCLUDE_SINGLE = wx.NewId()
|
||||||
|
ID_AUTOCOMP_INCLUDE_DOUBLE = wx.NewId()
|
||||||
|
ID_CALLTIPS = wx.NewId()
|
||||||
|
ID_CALLTIPS_SHOW = wx.NewId()
|
||||||
|
ID_COPY_PLUS = wx.NewId()
|
||||||
|
ID_PASTE_PLUS = wx.NewId()
|
||||||
|
ID_WRAP = wx.NewId()
|
||||||
|
|
||||||
|
|
||||||
|
class ShellMenu:
|
||||||
|
"""Mixin class to add standard menu items."""
|
||||||
|
|
||||||
|
def createMenus(self):
|
||||||
|
m = self.fileMenu = wx.wxMenu()
|
||||||
|
m.AppendSeparator()
|
||||||
|
m.Append(wx.wxID_EXIT, 'E&xit', 'Exit PyCrust')
|
||||||
|
|
||||||
|
m = self.editMenu = wx.wxMenu()
|
||||||
|
m.Append(wx.wxID_UNDO, '&Undo \tCtrl+Z', 'Undo the last action')
|
||||||
|
m.Append(wx.wxID_REDO, '&Redo \tCtrl+Y', 'Redo the last undone action')
|
||||||
|
m.AppendSeparator()
|
||||||
|
m.Append(wx.wxID_CUT, 'Cu&t \tCtrl+X', 'Cut the selection')
|
||||||
|
m.Append(wx.wxID_COPY, '&Copy \tCtrl+C', 'Copy the selection - removing prompts')
|
||||||
|
m.Append(ID_COPY_PLUS, 'Cop&y Plus \tCtrl+Shift+C', 'Copy the selection - retaining prompts')
|
||||||
|
m.Append(wx.wxID_PASTE, '&Paste \tCtrl+V', 'Paste')
|
||||||
|
m.Append(ID_PASTE_PLUS, 'Past&e Plus \tCtrl+Shift+V', 'Paste and run commands')
|
||||||
|
m.AppendSeparator()
|
||||||
|
m.Append(wx.wxID_CLEAR, 'Cle&ar', 'Delete the selection')
|
||||||
|
m.Append(wx.wxID_SELECTALL, 'Select A&ll \tCtrl+A', 'Select all text')
|
||||||
|
|
||||||
|
m = self.autocompMenu = wx.wxMenu()
|
||||||
|
m.Append(ID_AUTOCOMP_SHOW, 'Show Auto Completion',
|
||||||
|
'Show auto completion during dot syntax', 1)
|
||||||
|
m.Append(ID_AUTOCOMP_INCLUDE_MAGIC, 'Include Magic Attributes',
|
||||||
|
'Include attributes visible to __getattr__ and __setattr__', 1)
|
||||||
|
m.Append(ID_AUTOCOMP_INCLUDE_SINGLE, 'Include Single Underscores',
|
||||||
|
'Include attibutes prefixed by a single underscore', 1)
|
||||||
|
m.Append(ID_AUTOCOMP_INCLUDE_DOUBLE, 'Include Double Underscores',
|
||||||
|
'Include attibutes prefixed by a double underscore', 1)
|
||||||
|
|
||||||
|
m = self.calltipsMenu = wx.wxMenu()
|
||||||
|
m.Append(ID_CALLTIPS_SHOW, 'Show Call Tips',
|
||||||
|
'Show call tips with argument specifications', 1)
|
||||||
|
|
||||||
|
m = self.optionsMenu = wx.wxMenu()
|
||||||
|
m.AppendMenu(ID_AUTOCOMP, '&Auto Completion', self.autocompMenu,
|
||||||
|
'Auto Completion Options')
|
||||||
|
m.AppendMenu(ID_CALLTIPS, '&Call Tips', self.calltipsMenu,
|
||||||
|
'Call Tip Options')
|
||||||
|
m.Append(ID_WRAP, '&Wrap Lines',
|
||||||
|
'Wrap lines at right edge', 1)
|
||||||
|
|
||||||
|
m = self.helpMenu = wx.wxMenu()
|
||||||
|
m.AppendSeparator()
|
||||||
|
m.Append(wx.wxID_ABOUT, '&About...', 'About PyCrust')
|
||||||
|
|
||||||
|
b = self.menuBar = wx.wxMenuBar()
|
||||||
|
b.Append(self.fileMenu, '&File')
|
||||||
|
b.Append(self.editMenu, '&Edit')
|
||||||
|
b.Append(self.optionsMenu, '&Options')
|
||||||
|
b.Append(self.helpMenu, '&Help')
|
||||||
|
self.SetMenuBar(b)
|
||||||
|
|
||||||
|
wx.EVT_MENU(self, wx.wxID_EXIT, self.OnExit)
|
||||||
|
wx.EVT_MENU(self, wx.wxID_UNDO, self.OnUndo)
|
||||||
|
wx.EVT_MENU(self, wx.wxID_REDO, self.OnRedo)
|
||||||
|
wx.EVT_MENU(self, wx.wxID_CUT, self.OnCut)
|
||||||
|
wx.EVT_MENU(self, wx.wxID_COPY, self.OnCopy)
|
||||||
|
wx.EVT_MENU(self, ID_COPY_PLUS, self.OnCopyPlus)
|
||||||
|
wx.EVT_MENU(self, wx.wxID_PASTE, self.OnPaste)
|
||||||
|
wx.EVT_MENU(self, ID_PASTE_PLUS, self.OnPastePlus)
|
||||||
|
wx.EVT_MENU(self, wx.wxID_CLEAR, self.OnClear)
|
||||||
|
wx.EVT_MENU(self, wx.wxID_SELECTALL, self.OnSelectAll)
|
||||||
|
wx.EVT_MENU(self, wx.wxID_ABOUT, self.OnAbout)
|
||||||
|
wx.EVT_MENU(self, ID_AUTOCOMP_SHOW,
|
||||||
|
self.OnAutoCompleteShow)
|
||||||
|
wx.EVT_MENU(self, ID_AUTOCOMP_INCLUDE_MAGIC,
|
||||||
|
self.OnAutoCompleteIncludeMagic)
|
||||||
|
wx.EVT_MENU(self, ID_AUTOCOMP_INCLUDE_SINGLE,
|
||||||
|
self.OnAutoCompleteIncludeSingle)
|
||||||
|
wx.EVT_MENU(self, ID_AUTOCOMP_INCLUDE_DOUBLE,
|
||||||
|
self.OnAutoCompleteIncludeDouble)
|
||||||
|
wx.EVT_MENU(self, ID_CALLTIPS_SHOW,
|
||||||
|
self.OnCallTipsShow)
|
||||||
|
wx.EVT_MENU(self, ID_WRAP, self.OnWrap)
|
||||||
|
|
||||||
|
wx.EVT_UPDATE_UI(self, wx.wxID_UNDO, self.OnUpdateMenu)
|
||||||
|
wx.EVT_UPDATE_UI(self, wx.wxID_REDO, self.OnUpdateMenu)
|
||||||
|
wx.EVT_UPDATE_UI(self, wx.wxID_CUT, self.OnUpdateMenu)
|
||||||
|
wx.EVT_UPDATE_UI(self, wx.wxID_COPY, self.OnUpdateMenu)
|
||||||
|
wx.EVT_UPDATE_UI(self, ID_COPY_PLUS, self.OnUpdateMenu)
|
||||||
|
wx.EVT_UPDATE_UI(self, wx.wxID_PASTE, self.OnUpdateMenu)
|
||||||
|
wx.EVT_UPDATE_UI(self, ID_PASTE_PLUS, self.OnUpdateMenu)
|
||||||
|
wx.EVT_UPDATE_UI(self, wx.wxID_CLEAR, self.OnUpdateMenu)
|
||||||
|
wx.EVT_UPDATE_UI(self, ID_AUTOCOMP_SHOW, self.OnUpdateMenu)
|
||||||
|
wx.EVT_UPDATE_UI(self, ID_AUTOCOMP_INCLUDE_MAGIC, self.OnUpdateMenu)
|
||||||
|
wx.EVT_UPDATE_UI(self, ID_AUTOCOMP_INCLUDE_SINGLE, self.OnUpdateMenu)
|
||||||
|
wx.EVT_UPDATE_UI(self, ID_AUTOCOMP_INCLUDE_DOUBLE, self.OnUpdateMenu)
|
||||||
|
wx.EVT_UPDATE_UI(self, ID_CALLTIPS_SHOW, self.OnUpdateMenu)
|
||||||
|
wx.EVT_UPDATE_UI(self, ID_WRAP, self.OnUpdateMenu)
|
||||||
|
|
||||||
|
def OnExit(self, event):
|
||||||
|
self.Close(True)
|
||||||
|
|
||||||
|
def OnUndo(self, event):
|
||||||
|
self.shell.Undo()
|
||||||
|
|
||||||
|
def OnRedo(self, event):
|
||||||
|
self.shell.Redo()
|
||||||
|
|
||||||
|
def OnCut(self, event):
|
||||||
|
self.shell.Cut()
|
||||||
|
|
||||||
|
def OnCopy(self, event):
|
||||||
|
self.shell.Copy()
|
||||||
|
|
||||||
|
def OnCopyPlus(self, event):
|
||||||
|
self.shell.CopyWithPrompts()
|
||||||
|
|
||||||
|
def OnPaste(self, event):
|
||||||
|
self.shell.Paste()
|
||||||
|
|
||||||
|
def OnPastePlus(self, event):
|
||||||
|
self.shell.PasteAndRun()
|
||||||
|
|
||||||
|
def OnClear(self, event):
|
||||||
|
self.shell.Clear()
|
||||||
|
|
||||||
|
def OnSelectAll(self, event):
|
||||||
|
self.shell.SelectAll()
|
||||||
|
|
||||||
|
def OnAbout(self, event):
|
||||||
|
"""Display an About PyCrust window."""
|
||||||
|
title = 'About PyCrust'
|
||||||
|
text = 'PyCrust %s\n\n' % VERSION + \
|
||||||
|
'Yet another Python shell, only flakier.\n\n' + \
|
||||||
|
'Half-baked by Patrick K. O\'Brien,\n' + \
|
||||||
|
'the other half is still in the oven.\n\n' + \
|
||||||
|
'Shell Revision: %s\n' % self.shell.revision + \
|
||||||
|
'Interpreter Revision: %s\n\n' % self.shell.interp.revision + \
|
||||||
|
'Python Version: %s\n' % sys.version.split()[0] + \
|
||||||
|
'wxPython Version: %s\n' % wx.__version__ + \
|
||||||
|
'Platform: %s\n' % sys.platform
|
||||||
|
dialog = wx.wxMessageDialog(self, text, title, wx.wxOK | wx.wxICON_INFORMATION)
|
||||||
|
dialog.ShowModal()
|
||||||
|
dialog.Destroy()
|
||||||
|
|
||||||
|
def OnAutoCompleteShow(self, event):
|
||||||
|
self.shell.autoComplete = event.IsChecked()
|
||||||
|
|
||||||
|
def OnAutoCompleteIncludeMagic(self, event):
|
||||||
|
self.shell.autoCompleteIncludeMagic = event.IsChecked()
|
||||||
|
|
||||||
|
def OnAutoCompleteIncludeSingle(self, event):
|
||||||
|
self.shell.autoCompleteIncludeSingle = event.IsChecked()
|
||||||
|
|
||||||
|
def OnAutoCompleteIncludeDouble(self, event):
|
||||||
|
self.shell.autoCompleteIncludeDouble = event.IsChecked()
|
||||||
|
|
||||||
|
def OnCallTipsShow(self, event):
|
||||||
|
self.shell.autoCallTip = event.IsChecked()
|
||||||
|
|
||||||
|
def OnWrap(self, event):
|
||||||
|
self.shell.SetWrapMode(event.IsChecked())
|
||||||
|
|
||||||
|
def OnUpdateMenu(self, event):
|
||||||
|
"""Update menu items based on current status."""
|
||||||
|
id = event.GetId()
|
||||||
|
if id == wx.wxID_UNDO:
|
||||||
|
event.Enable(self.shell.CanUndo())
|
||||||
|
elif id == wx.wxID_REDO:
|
||||||
|
event.Enable(self.shell.CanRedo())
|
||||||
|
elif id == wx.wxID_CUT:
|
||||||
|
event.Enable(self.shell.CanCut())
|
||||||
|
elif id == wx.wxID_COPY:
|
||||||
|
event.Enable(self.shell.CanCopy())
|
||||||
|
elif id == ID_COPY_PLUS:
|
||||||
|
event.Enable(self.shell.CanCopy())
|
||||||
|
elif id == wx.wxID_PASTE:
|
||||||
|
event.Enable(self.shell.CanPaste())
|
||||||
|
elif id == ID_PASTE_PLUS:
|
||||||
|
event.Enable(self.shell.CanPaste())
|
||||||
|
elif id == wx.wxID_CLEAR:
|
||||||
|
event.Enable(self.shell.CanCut())
|
||||||
|
elif id == ID_AUTOCOMP_SHOW:
|
||||||
|
event.Check(self.shell.autoComplete)
|
||||||
|
elif id == ID_AUTOCOMP_INCLUDE_MAGIC:
|
||||||
|
event.Check(self.shell.autoCompleteIncludeMagic)
|
||||||
|
elif id == ID_AUTOCOMP_INCLUDE_SINGLE:
|
||||||
|
event.Check(self.shell.autoCompleteIncludeSingle)
|
||||||
|
elif id == ID_AUTOCOMP_INCLUDE_DOUBLE:
|
||||||
|
event.Check(self.shell.autoCompleteIncludeDouble)
|
||||||
|
elif id == ID_CALLTIPS_SHOW:
|
||||||
|
event.Check(self.shell.autoCallTip)
|
||||||
|
elif id == ID_WRAP:
|
||||||
|
event.Check(self.shell.GetWrapMode())
|
||||||
|
|
@@ -6,5 +6,5 @@ __author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
|
|||||||
__cvsid__ = "$Id$"
|
__cvsid__ = "$Id$"
|
||||||
__revision__ = "$Revision$"[11:-2]
|
__revision__ = "$Revision$"[11:-2]
|
||||||
|
|
||||||
VERSION = '0.7.2'
|
VERSION = '0.8'
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user