Deprecated PyShell and PyShellWindow, added a snapshot of PyCrust.

Added the new virtual list capabilities to wxListCtrl.

Other odds and ends.


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@11380 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Robin Dunn
2001-08-14 19:19:48 +00:00
parent 6443de0263
commit c7e7022c2c
35 changed files with 3771 additions and 1641 deletions

View File

@@ -0,0 +1,148 @@
#!/usr/bin/env python
"""PyCrust is a python shell application.
"""
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
__cvsid__ = "$Id$"
__date__ = "July 1, 2001"
__version__ = "$Revision$"[11:-2]
from wxPython.wx import *
from PyCrustVersion import version
from PyCrustShell import Shell
class Frame(wxFrame):
"""Main window for the PyCrust application."""
def __init__(self, parent, id, title):
"""Create the main frame object for the application."""
wxFrame.__init__(self, parent, id, title)
intro = 'Welcome To PyCrust %s - The Flakiest Python Shell' % version
self.CreateStatusBar()
self.SetStatusText(intro)
self.createMenus()
# Create the shell, which will create a default editor and
# a default interpreter.
self.shell = Shell(editorParent=self, introText=intro)
# Override the editor so that status messages go to the status bar.
self.shell.editor.setStatusText = self.SetStatusText
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 \tDel', 'Delete the selection')
m.Append(wxID_SELECTALL, 'Select A&ll \tCtrl+A', 'Select all text')
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.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_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)
def OnExit(self, event):
self.Close(true)
def OnUndo(self, event):
self.shell.editor.Undo()
def OnRedo(self, event):
self.shell.editor.Redo()
def OnCut(self, event):
self.shell.editor.Cut()
def OnCopy(self, event):
self.shell.editor.Copy()
def OnPaste(self, event):
self.shell.editor.Paste()
def OnClear(self, event):
self.shell.editor.Clear()
def OnSelectAll(self, event):
self.shell.editor.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.'
dialog = wxMessageDialog(self, text, title, wxOK | wxICON_INFORMATION)
dialog.ShowModal()
dialog.Destroy()
def OnUpdateMenu(self, event):
"""Update menu items based on which should be enabled/disabled."""
id = event.GetId()
if id == wxID_UNDO:
event.Enable(self.shell.editor.CanUndo())
elif id == wxID_REDO:
event.Enable(self.shell.editor.CanRedo())
elif id == wxID_CUT:
event.Enable(self.shell.editor.CanCut())
elif id == wxID_COPY:
event.Enable(self.shell.editor.CanCopy())
elif id == wxID_PASTE:
event.Enable(self.shell.editor.CanPaste())
elif id == wxID_CLEAR:
event.Enable(self.shell.editor.CanCut())
class App(wxApp):
def OnInit(self):
parent = None
id = -1
title = 'PyCrust'
self.frame = Frame(parent, id, title)
self.frame.Show(true)
self.SetTopWindow(self.frame)
return true
def main():
import sys
application = App(0)
# Add the application object to the sys module's namespace.
# This allows a shell user to do:
# >>> import sys
# >>> sys.application.whatever
sys.application = application
application.MainLoop()
if __name__ == '__main__':
main()

View File

@@ -0,0 +1,349 @@
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
__cvsid__ = "$Id$"
__date__ = "July 1, 2001"
__version__ = "$Revision$"[11:-2]
from wxPython.wx import *
from wxPython.stc import *
import keyword
import sys
if wxPlatform == '__WXMSW__':
faces = { 'times' : 'Times New Roman',
'mono' : 'Courier New',
'helv' : 'Lucida Console',
'lucida' : 'Lucida Console',
'other' : 'Comic Sans MS',
'size' : 8,
'lnsize' : 7,
'backcol': '#FFFFFF',
}
else: # GTK
faces = { 'times' : 'Times',
'mono' : 'Courier',
'helv' : 'Helvetica',
'other' : 'new century schoolbook',
'size' : 9,
'lnsize' : 8,
'backcol': '#FFFFFF',
}
class Editor(wxStyledTextCtrl):
"""PyCrust Editor based on wxStyledTextCtrl."""
revision = __version__
def __init__(self, parent, id):
"""Create a PyCrust editor object based on wxStyledTextCtrl."""
wxStyledTextCtrl.__init__(self, parent, id, style=wxCLIP_CHILDREN)
# Commands get pushed to a method determined by the outer shell.
#self.shellPush = pushMethod
# Keep track of the most recent prompt starting and ending positions.
self.promptPos = [0, 0]
# Keep track of multi-line commands.
self.more = 0
# Configure various defaults and user preferences.
self.config()
# Assign handlers for keyboard events.
EVT_KEY_DOWN(self, self.OnKeyDown)
EVT_CHAR(self, self.OnChar)
def config(self):
"""Configure editor based on user preferences."""
self.SetMarginType(1, wxSTC_MARGIN_NUMBER)
self.SetMarginWidth(1, 40)
self.SetLexer(wxSTC_LEX_PYTHON)
self.SetKeyWords(0, ' '.join(keyword.kwlist))
self.setStyles(faces)
self.SetViewWhiteSpace(0)
self.SetTabWidth(4)
self.SetUseTabs(0)
# Do we want to automatically pop up command completion options?
self.autoComplete = 1
self.autoCompleteCaseInsensitive = 1
self.AutoCompSetIgnoreCase(self.autoCompleteCaseInsensitive)
# De we want to automatically pop up command argument help?
self.autoCallTip = 1
self.CallTipSetBackground(wxColour(255, 255, 232))
def setStyles(self, faces):
"""Configure font size, typeface and color for lexer."""
# Default style
self.StyleSetSpec(wxSTC_STYLE_DEFAULT, "face:%(mono)s,size:%(size)d" % faces)
self.StyleClearAll()
# Built in styles
self.StyleSetSpec(wxSTC_STYLE_LINENUMBER, "back:#C0C0C0,face:%(mono)s,size:%(lnsize)d" % faces)
self.StyleSetSpec(wxSTC_STYLE_CONTROLCHAR, "face:%(mono)s" % faces)
self.StyleSetSpec(wxSTC_STYLE_BRACELIGHT, "fore:#0000FF,back:#FFFF88")
self.StyleSetSpec(wxSTC_STYLE_BRACEBAD, "fore:#FF0000,back:#FFFF88")
# Python styles
self.StyleSetSpec(wxSTC_P_DEFAULT, "face:%(mono)s" % faces)
self.StyleSetSpec(wxSTC_P_COMMENTLINE, "fore:#007F00,face:%(mono)s" % faces)
self.StyleSetSpec(wxSTC_P_NUMBER, "")
self.StyleSetSpec(wxSTC_P_STRING, "fore:#7F007F,face:%(mono)s" % faces)
self.StyleSetSpec(wxSTC_P_CHARACTER, "fore:#7F007F,face:%(mono)s" % faces)
self.StyleSetSpec(wxSTC_P_WORD, "fore:#00007F,bold")
self.StyleSetSpec(wxSTC_P_TRIPLE, "fore:#7F0000")
self.StyleSetSpec(wxSTC_P_TRIPLEDOUBLE, "fore:#000033,back:#FFFFE8")
self.StyleSetSpec(wxSTC_P_CLASSNAME, "fore:#0000FF,bold")
self.StyleSetSpec(wxSTC_P_DEFNAME, "fore:#007F7F,bold")
self.StyleSetSpec(wxSTC_P_OPERATOR, "")
self.StyleSetSpec(wxSTC_P_IDENTIFIER, "")
self.StyleSetSpec(wxSTC_P_COMMENTBLOCK, "fore:#7F7F7F")
self.StyleSetSpec(wxSTC_P_STRINGEOL, "fore:#000000,face:%(mono)s,back:#E0C0E0,eolfilled" % faces)
def OnKeyDown(self, event):
"""Key down event handler.
The main goal here is to not allow modifications to previous
lines of text.
"""
key = event.KeyCode()
currpos = self.GetCurrentPos()
stoppos = self.promptPos[1]
# If the auto-complete window is up let it do its thing.
if self.AutoCompActive():
event.Skip()
# Return is used to submit a command to the interpreter.
elif key == WXK_RETURN:
if self.CallTipActive: self.CallTipCancel()
self.processLine()
# Home needs to be aware of the prompt.
elif key == WXK_HOME:
if currpos >= stoppos:
self.SetCurrentPos(stoppos)
self.SetAnchor(stoppos)
else:
event.Skip()
# Basic navigation keys should work anywhere.
elif key in (WXK_END, WXK_LEFT, WXK_RIGHT, WXK_UP, WXK_DOWN, \
WXK_PRIOR, WXK_NEXT):
event.Skip()
# Don't backspace over the latest prompt.
elif key == WXK_BACK:
if currpos > stoppos:
event.Skip()
# Only allow these keys after the latest prompt.
elif key in (WXK_TAB, WXK_DELETE):
if currpos >= stoppos:
event.Skip()
# Don't toggle between insert mode and overwrite mode.
elif key == WXK_INSERT:
pass
else:
event.Skip()
def OnChar(self, event):
"""Keypress event handler.
The main goal here is to not allow modifications to previous
lines of text.
"""
key = event.KeyCode()
currpos = self.GetCurrentPos()
stoppos = self.promptPos[1]
if currpos >= stoppos:
if key == 46:
# "." The dot or period key activates auto completion.
# Get the command between the prompt and the cursor.
# Add a dot to the end of the command.
command = self.GetTextRange(stoppos, currpos) + '.'
self.write('.')
if self.autoComplete: self.autoCompleteShow(command)
elif key == 40:
# "(" The left paren activates a call tip and cancels
# an active auto completion.
if self.AutoCompActive(): self.AutoCompCancel()
# Get the command between the prompt and the cursor.
# Add the '(' to the end of the command.
command = self.GetTextRange(stoppos, currpos) + '('
self.write('(')
if self.autoCallTip: self.autoCallTipShow(command)
else:
# Allow the normal event handling to take place.
event.Skip()
else:
pass
def setStatusText(self, text):
"""Display status information."""
# This method will most likely be replaced by the enclosing app
# to do something more interesting, like write to a status bar.
print text
def autoCompleteShow(self, command):
"""Display auto-completion popup list."""
list = self.getAutoCompleteList(command)
if list:
options = ' '.join(list)
offset = 0
self.AutoCompShow(offset, options)
def getAutoCompleteList(self, command):
"""Return list of auto-completion options for command."""
# This method needs to be replaced by the enclosing app
# to get the proper auto complete list from the interpreter.
return []
def autoCallTipShow(self, command):
"""Display argument spec and docstring in a popup bubble thingie."""
if self.CallTipActive: self.CallTipCancel()
tip = self.getCallTip(command)
if tip:
offset = self.GetCurrentPos()
self.CallTipShow(offset, tip)
def getCallTip(self, command):
"""Return arguments and docstring for command."""
# This method needs to be replaced by the enclosing app
# to get the proper auto complete list from the interpreter.
return ''
def processLine(self):
"""Process the line of text at which the user hit Enter."""
# The user hit ENTER and we need to decide what to do. They could be
# sitting on any line in the editor.
# Grab information about the current line.
thepos = self.GetCurrentPos()
theline = self.GetCurrentLine()
thetext = self.GetCurLine()[0]
command = self.getCommand(thetext)
# Go to the very bottom of the editor.
endpos = self.GetTextLength()
self.SetCurrentPos(endpos)
endline = self.GetCurrentLine()
# If they hit RETURN on the last line, execute the command.
if theline == endline:
self.push(command)
# Otherwise, replace the last line with the new line.
else:
# If the new line contains a command (even an invalid one).
if command:
startpos = self.PositionFromLine(endline)
self.SetSelection(startpos, endpos)
self.ReplaceSelection('')
self.prompt()
self.write(command)
# Otherwise, put the cursor back where we started.
else:
self.SetCurrentPos(thepos)
self.SetAnchor(thepos)
def getCommand(self, text):
"""Extract a command from text which may include a shell prompt.
The command may not necessarily be valid Python syntax.
"""
# XXX Need to extract real prompts here. Need to keep track of the
# prompt every time a command is issued. Do this in the interpreter
# with a line number, prompt, command dictionary. For the history, perhaps.
ps1 = str(sys.ps1)
ps1size = len(ps1)
ps2 = str(sys.ps2)
ps2size = len(ps2)
text = text.rstrip()
# Strip the prompt off the front of text leaving just the command.
if text[:ps1size] == ps1:
command = text[ps1size:]
elif text[:ps2size] == ps2:
command = text[ps2size:]
else:
command = ''
return command
def push(self, command):
"""Start a new line, send command to the shell, display a prompt."""
self.write('\n')
self.more = self.shellPush(command)
self.prompt()
# Keep the undo feature from undoing previous responses. The only
# thing that can be undone is stuff typed after the prompt, before
# hitting enter. After they hit enter it becomes permanent.
self.EmptyUndoBuffer()
def clear(self):
"""Delete all text from the editor."""
self.ClearAll()
def prompt(self):
"""Display appropriate prompt for the context, either ps1 or ps2.
If this is a continuation line, autoindent as necessary.
"""
if self.more:
prompt = str(sys.ps2)
else:
prompt = str(sys.ps1)
pos = self.GetCurLine()[1]
if pos > 0: self.write('\n')
self.promptPos[0] = self.GetCurrentPos()
self.write(prompt)
self.promptPos[1] = self.GetCurrentPos()
# XXX Add some autoindent magic here if more.
if self.more:
self.write('\t') # Temporary hack indentation.
self.EnsureCaretVisible()
self.ScrollToColumn(0)
def readIn(self):
"""Replacement for stdin."""
prompt = 'Please enter your response:'
dialog = wxTextEntryDialog(None, prompt, \
'Input Dialog (Standard)', '')
try:
if dialog.ShowModal() == wxID_OK:
text = dialog.GetValue()
self.write(text + '\n')
return text
finally:
dialog.Destroy()
return ''
def readRaw(self, prompt='Please enter your response:'):
"""Replacement for raw_input."""
dialog = wxTextEntryDialog(None, prompt, \
'Input Dialog (Raw)', '')
try:
if dialog.ShowModal() == wxID_OK:
text = dialog.GetValue()
return text
finally:
dialog.Destroy()
return ''
def write(self, text):
"""Display text in the editor."""
self.AddText(text)
self.EnsureCaretVisible()
#self.ScrollToColumn(0)
def writeOut(self, text):
"""Replacement for stdout."""
self.write(text)
def writeErr(self, text):
"""Replacement for stderr."""
self.write(text)
def CanCut(self):
"""Return true if text is selected and can be cut."""
return self.GetSelectionStart() != self.GetSelectionEnd()
def CanCopy(self):
"""Return true if text is selected and can be copied."""
return self.GetSelectionStart() != self.GetSelectionEnd()

View File

@@ -0,0 +1,81 @@
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
__cvsid__ = "$Id$"
__date__ = "July 1, 2001"
__version__ = "$Revision$"[11:-2]
import os
import sys
from code import InteractiveInterpreter
import introspect
class Interpreter(InteractiveInterpreter):
"""PyCrust Interpreter based on code.InteractiveInterpreter."""
revision = __version__
def __init__(self, locals=None, rawin=None,
stdin=sys.stdin, stdout=sys.stdout, stderr=sys.stderr):
"""Create an interactive interpreter object."""
InteractiveInterpreter.__init__(self, locals=locals)
self.stdin = stdin
self.stdout = stdout
self.stderr = stderr
if rawin is not None:
import __builtin__
__builtin__.raw_input = rawin
del __builtin__
copyright = 'Type "copyright", "credits" or "license" for more information.'
self.introText = 'Python %s on %s\n%s' % \
(sys.version, sys.platform, copyright)
try:
sys.ps1
except AttributeError:
sys.ps1 = '>>> '
try:
sys.ps2
except AttributeError:
sys.ps2 = '... '
self.more = 0
self.commandBuffer = [] # List of lists to support recursive push().
self.commandHistory = []
self.startupScript = os.environ.get('PYTHONSTARTUP')
def push(self, command):
"""Send command to the interpreter to be executed.
Because this may be called recursively, we append a new list
onto the commandBuffer list and then append commands into that.
If the passed in command is part of a multi-line command we keep
appending the pieces to the last list in commandBuffer until we
have a complete command, then, finally, we delete that last list.
"""
if not self.more: self.commandBuffer.append([])
self.commandBuffer[-1].append(command)
source = '\n'.join(self.commandBuffer[-1])
self.more = self.runsource(source)
if not self.more: del self.commandBuffer[-1]
return self.more
def runsource(self, source):
"""Compile and run source code in the interpreter."""
stdin, stdout, stderr = sys.stdin, sys.stdout, sys.stderr
sys.stdin = self.stdin
sys.stdout = self.stdout
sys.stderr = self.stderr
more = InteractiveInterpreter.runsource(self, source)
sys.stdin, sys.stdout, sys.stderr = stdin, stdout, stderr
return more
def getAutoCompleteList(self, command=''):
"""Return list of auto-completion options for a command.
The list of options will be based on the locals namespace."""
return introspect.getAutoCompleteList(command, self.locals)
def getCallTip(self, command=''):
"""Return call tip text for a command.
The call tip information will be based on the locals namespace."""
return introspect.getCallTip(command, self.locals)

View File

@@ -0,0 +1,180 @@
"""
"""
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
__cvsid__ = "$Id$"
__date__ = "July 1, 2001"
__version__ = "$Revision$"[11:-2]
import os
from PyCrustVersion import version
class Shell:
"""PyCrust Shell manages the Editor and Interpreter."""
name = 'PyCrust Shell'
revision = __version__
def __init__(self, editorParent=None, introText='', editor=None, interp=None):
"""Create a PyCrust shell object to manage the editor and interpreter."""
try:
eval('crap')
except:
pass
self.introText = introText
# Create a default editor if one isn't provided.
if editor == None:
from PyCrustEditor import Editor
self.editor = Editor(editorParent, id=-1)
else:
self.editor = editor
# Link the editor to the shell so that the shell is a conduit for
# pushing commands to the interpreter.
self.editor.shellPush = self.shellPush
# Create a default interpreter if one isn't provided.
if interp == None:
from PyCrustInterp import Interpreter
from pseudo import PseudoFileIn, PseudoFileOut, PseudoFileErr
self.stdin = PseudoFileIn(self.editor.readIn)
self.stdout = PseudoFileOut(self.editor.writeOut)
self.stderr = PseudoFileErr(self.editor.writeErr)
# Override the default locals so we have something interesting.
locals = {'__name__': 'PyCrust',
'__doc__': 'PyCrust, The Python Shell.',
'__version__': version,
}
self.interp = Interpreter(locals=locals,
rawin=self.editor.readRaw,
stdin=self.stdin,
stdout=self.stdout,
stderr=self.stderr)
else:
self.interp = interp
# XXX redo this using hasattr() or something so that we can link
# these if a provided editor has this method.
if editor == None or editor == self:
# Override so the auto complete list comes from the interpreter.
self.editor.getAutoCompleteList = self.interp.getAutoCompleteList
# Override so the call tip comes from the interpreter.
self.editor.getCallTip = self.interp.getCallTip
# Keep track of whether the interpreter needs more.
self.more = 0
try:
self.showIntro(self.introText)
except:
pass
try:
self.setBuiltinKeywords()
except:
pass
try:
self.setLocalShell()
except:
pass
# Do this last so the user has complete control over their
# environment. They can override anything they want.
try:
self.execStartupScript(self.interp.startupScript)
except:
pass
def destroy(self):
del self.editor
del self.stdin
del self.stdout
del self.stderr
del self.interp
def showIntro(self, text=''):
"""Display introductory text in the shell editor."""
if text:
if text[-1] != '\n': text += '\n'
self.editor.write(text)
try:
self.editor.write(self.interp.introText)
except AttributeError:
pass
def setBuiltinKeywords(self):
"""Create pseudo keywords as part of builtins.
This is a rather clever hack that sets "close", "exit" and "quit"
to a PseudoKeyword object so that we can make them do what we want.
In this case what we want is to call our self.quit() method.
The user can type "close", "exit" or "quit" without the final parens.
"""
import __builtin__
from pseudo import PseudoKeyword
__builtin__.close = __builtin__.exit = __builtin__.quit = \
PseudoKeyword(self.quit)
def quit(self):
"""Quit the application."""
# XXX Good enough for now but later we want to send a close event.
# In the close event handler we can prompt to make sure they want to quit.
# Other applications, like PythonCard, may choose to hide rather than
# quit so we should just post the event and let the surrounding app
# decide what it wants to do.
self.editor.write('Click on the close button to leave the application.')
def setLocalShell(self):
"""Add 'shell' to locals."""
self.interp.locals['shell'] = self
def execStartupScript(self, startupScript):
"""Execute the user's PYTHONSTARTUP script if they have one."""
if startupScript and os.path.isfile(startupScript):
startupText = 'Startup script executed: ' + startupScript
self.editor.push('print %s;execfile(%s)' % \
(`startupText`, `startupScript`))
else:
self.editor.push('')
def run(self, command, prompt=1, verbose=1):
"""Execute command within the shell as if it was typed in directly.
>>> shell.run('print "this"')
>>> print "this"
this
>>>
"""
command = command.rstrip()
if prompt: self.editor.prompt()
if verbose: self.editor.write(command)
self.editor.push(command)
def runfile(self, filename):
"""Execute all commands in file as if they were typed into the shell."""
file = open(filename)
try:
self.editor.prompt()
for command in file.readlines():
if command[:6] == 'shell.': # Run shell methods silently.
self.run(command, prompt=0, verbose=0)
else:
self.run(command, prompt=0, verbose=1)
finally:
file.close()
def push(self, command):
"""Send command to the interpreter for execution."""
self.more = self.interp.push(command)
return self.more
shellPush = push
def ask(self, prompt='Please enter your response:'):
"""Get response from the user."""
return raw_input(prompt=prompt)
def pause(self):
"""Halt execution pending a response from the user."""
self.ask('Press enter to continue:')
def clear(self):
"""Delete all text from the shell editor."""
self.editor.clear()

View File

@@ -0,0 +1,10 @@
"""Provides an object representing the current "version" or "release" of
PyCrust as a whole. Individual classes, such as the shell, editor and
interpreter, each have a revision property based on the CVS $Revision$."""
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
__cvsid__ = "$Id$"
__date__ = "July 1, 2001"
__version__ = "$Revision$"[11:-2]
version = '0.5'

View File

@@ -0,0 +1 @@
# Orbtech python package.

View File

@@ -0,0 +1,140 @@
"""Provides a variety of introspective-type support functions for things
like call tips and command auto completion."""
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
__cvsid__ = "$Id$"
__date__ = "August 8, 2001"
__version__ = "$Revision$"[11:-2]
import inspect
import string
def getAutoCompleteList(command='', locals=None):
"""Return list of auto-completion options for command.
The list of options will be based on the locals namespace."""
# Get the proper chunk of code from the command.
root = getRoot(command, terminator='.')
try:
object = eval(root, locals)
attributes = getAttributes(object)
return attributes
except:
return []
def getAttributes(object):
"""Return list of unique attributes, including inherited, for an object."""
attributes = []
dict = {}
# Remove duplicates from the attribute list.
for item in getAllAttributes(object):
dict[item] = None
attributes += dict.keys()
attributes.sort()
return attributes
def getAllAttributes(object):
"""Return list of all attributes, including inherited, for an object.
Recursively walk through a class and all base classes.
"""
attributes = []
try:
attributes += dir(object)
if hasattr(object, '__class__'):
attributes += getAllAttributes(object.__class__)
if hasattr(object, '__bases__'):
for base in object.__bases__:
attributes += getAllAttributes(base)
finally:
return attributes
def getCallTip(command='', locals=None):
"""Return call tip text for a command.
The call tip information will be based on the locals namespace."""
# Get the proper chunk of code from the command.
root = getRoot(command, terminator='(')
try:
object = eval(root, locals)
except:
return ''
dropSelf = 0
if hasattr(object, '__name__'): # Make sure this is a useable object.
# Switch to the object that has the information we need.
if inspect.ismethod(object):
# Get the function from the object otherwise inspec.getargspec()
# complains that the object isn't a Python function.
object = object.im_func
dropSelf = 1
elif inspect.isclass(object):
# Get the __init__ method for the class.
try:
object = object.__init__.im_func
dropSelf = 1
except AttributeError:
for base in object.__bases__:
constructor = _find_constructor(base)
if constructor is not None:
object = constructor
dropSelf = 1
break
name = object.__name__
if inspect.isbuiltin(object):
# Builtin functions don't have an argspec that we can get.
tip1 = ''
else:
# tip1 is a string like: "getCallTip(command='', locals=None)"
argspec = apply(inspect.formatargspec, inspect.getargspec(object))
if dropSelf:
# The first parameter to a method is a reference to the
# instance, usually coded as "self", and is passed
# automatically by Python and therefore we want to drop it.
temp = argspec.split(',')
if len(temp) == 1: # No other arguments.
argspec = '()'
else: # Drop the first argument.
argspec = '(' + ','.join(temp[1:]).lstrip()
tip1 = name + argspec
doc = inspect.getdoc(object)
if doc:
# tip2 is the first separated line of the docstring, like:
# "Return call tip text for a command."
# tip3 is the rest of the docstring, like:
# "The call tip information will be based on ... <snip>
docpieces = doc.split('\n\n')
tip2 = docpieces[0]
tip3 = '\n\n'.join(docpieces[1:])
tip = '%s\n\n%s\n\n%s' % (tip1, tip2, tip3)
else:
tip = tip1
return tip.strip()
else:
return ''
def getRoot(command, terminator=None):
"""Return the rightmost root portion of an arbitrary Python command.
The command would normally terminate with a "(" or ".". Anything after
the terminator will be dropped, allowing you to get back to the root.
"""
root = ''
validChars = "._" + string.uppercase + string.lowercase + string.digits
# Remove all whitespace from the command.
command = ''.join(command.split())
# Deal with the terminator.
if terminator:
pieces = command.split(terminator)
if len(pieces) > 1:
# Drop the final terminator and anything that follows.
command = terminator.join(pieces[:-1])
# Go backward through the command until we hit an "invalid" character.
i = len(command)
while i and command[i-1] in validChars:
i -= 1
# Grab everything from the "invalid" character to the end.
root = command[i:]
return root

View File

@@ -0,0 +1,90 @@
"""Provides a variety of classes to create pseudo keywords and pseudo files."""
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
__cvsid__ = "$Id$"
__date__ = "July 1, 2001"
__version__ = "$Revision$"[11:-2]
class PseudoKeyword:
"""A callable class that calls a method passed as a parameter.
Good for creating a pseudo keyword in the python runtime
environment. The keyword is really an object that has a repr()
that calls itself which calls the method that was passed in the
init of the object. All this just to avoid having to type in the
closing parens on a method. So, for example:
>>> quit = PseudoKeyword(SomeObject.someMethod)
>>> quit
SomeObject.someMethod gets executed as if it had been called
directly and the user didn't have to type the parens, like
"quit()". This technique is most applicable for pseudo keywords
like quit, exit and help.
If SomeObject.someMethod can take parameters, they can still be
passed by using the keyword in the traditional way with parens.
"""
def __init__(self, method):
"""Create a callable object that executes method when called."""
# XXX Should probably check that this is a callable object.
self.method = method
def __call__(self, *args, **kwds):
self.method(*args, **kwds)
def __repr__(self):
self()
return ''
class PseudoFile:
def __init__(self):
"""Create a file-like object."""
pass
def readline(self):
pass
def write(self, s):
pass
def writelines(self, l):
map(self.write, l)
def flush(self):
pass
def isatty(self):
pass
class PseudoFileIn(PseudoFile):
def __init__(self, readline):
self.readline = readline
def isatty(self):
return 1
class PseudoFileOut(PseudoFile):
def __init__(self, write):
self.write = write
def isatty(self):
return 1
class PseudoFileErr(PseudoFile):
def __init__(self, write):
self.write = write
def isatty(self):
return 1

View File

@@ -20,6 +20,10 @@ There is still much to be done to improve this class, such as line
buffering/recall, autoindent, calltips, autocomplete, fixing the colourizer,
etc... But it's a good start.
8-10-2001 THIS MODULE IS NOW DEPRECATED. Please see the most excellent
PyCrust package instead.
"""

View File

@@ -17,11 +17,14 @@ History:
input prompts and output styles added to customized demo
some html cleanups
04-oct-1999 [rpd] Changed to use the new sizers
05-oct-1990 [als] changes inspired by code.InteractiveInterpreter()
05-oct-1999 [als] changes inspired by code.InteractiveInterpreter()
from Python Library. if i knew about this class earlier,
i would rather inherit from it.
renamed to wxPyShell.py since i've renounced the 8.3 scheme
8-10-2001 THIS MODULE IS NOW DEPRECATED. Please see the most excellent
PyCrust package instead.
"""
__version__ ="$Revision$"
# $RCSfile$