A couple little fixes for wxSTC

Updated to 0.6 of PyCrust


git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@11560 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Robin Dunn 2001-09-04 23:44:17 +00:00
parent 8de28db94f
commit fea018f801
19 changed files with 955 additions and 332 deletions

View File

@ -9,7 +9,8 @@ EVT_DETAILED_HELP_RANGE, EVT_CONTEXT_MENU, wxHelpEvent,
wxContextMenuEvent, wxContextHelp, wxContextHelpButton, wxTipWindow,
and a demo to show them in action.
Deprecated PyShell and PyShellWindow, added a snapshot of PyCrust.
Deprecated PyShell and PyShellWindow, added a snapshot of PyCrust (see
http://sourceforge.net/projects/pycrust/. )
Added the new virtual list capabilities to wxListCtrl.
@ -40,6 +41,8 @@ Added wxGenBitmapTextButton, TablePrint, etc. contribs from Lorne White.
Added wxNativeFontInfo and wxFontMapper.
2.3.1
-----
Added EVT_GRID_EDITOR_CREATED and wxGridEditorCreatedEvent so the user

View File

@ -988,7 +988,7 @@ static PyObject *_wrap_wxStyledTextCtrl_GetCurLine(PyObject *self, PyObject *arg
PyObject * _resultobj;
wxString * _result;
wxStyledTextCtrl * _arg0;
int * _arg1 = (int *) NULL;
int * _arg1;
int temp;
PyObject * _argo0 = 0;
char *_kwnames[] = { "self", NULL };
@ -7532,8 +7532,8 @@ static PyObject *_wrap_wxStyledTextCtrl_GetModEventMask(PyObject *self, PyObject
return _resultobj;
}
#define wxStyledTextCtrl_SetFocus(_swigobj,_swigarg0) (_swigobj->SetFocus(_swigarg0))
static PyObject *_wrap_wxStyledTextCtrl_SetFocus(PyObject *self, PyObject *args, PyObject *kwargs) {
#define wxStyledTextCtrl_SetSTCFocus(_swigobj,_swigarg0) (_swigobj->SetSTCFocus(_swigarg0))
static PyObject *_wrap_wxStyledTextCtrl_SetSTCFocus(PyObject *self, PyObject *args, PyObject *kwargs) {
PyObject * _resultobj;
wxStyledTextCtrl * _arg0;
bool _arg1;
@ -7542,19 +7542,19 @@ static PyObject *_wrap_wxStyledTextCtrl_SetFocus(PyObject *self, PyObject *args,
char *_kwnames[] = { "self","focus", NULL };
self = self;
if(!PyArg_ParseTupleAndKeywords(args,kwargs,"Oi:wxStyledTextCtrl_SetFocus",_kwnames,&_argo0,&tempbool1))
if(!PyArg_ParseTupleAndKeywords(args,kwargs,"Oi:wxStyledTextCtrl_SetSTCFocus",_kwnames,&_argo0,&tempbool1))
return NULL;
if (_argo0) {
if (_argo0 == Py_None) { _arg0 = NULL; }
else if (SWIG_GetPtrObj(_argo0,(void **) &_arg0,"_wxStyledTextCtrl_p")) {
PyErr_SetString(PyExc_TypeError,"Type error in argument 1 of wxStyledTextCtrl_SetFocus. Expected _wxStyledTextCtrl_p.");
PyErr_SetString(PyExc_TypeError,"Type error in argument 1 of wxStyledTextCtrl_SetSTCFocus. Expected _wxStyledTextCtrl_p.");
return NULL;
}
}
_arg1 = (bool ) tempbool1;
{
wxPy_BEGIN_ALLOW_THREADS;
wxStyledTextCtrl_SetFocus(_arg0,_arg1);
wxStyledTextCtrl_SetSTCFocus(_arg0,_arg1);
wxPy_END_ALLOW_THREADS;
} Py_INCREF(Py_None);
@ -7562,8 +7562,8 @@ static PyObject *_wrap_wxStyledTextCtrl_SetFocus(PyObject *self, PyObject *args,
return _resultobj;
}
#define wxStyledTextCtrl_GetFocus(_swigobj) (_swigobj->GetFocus())
static PyObject *_wrap_wxStyledTextCtrl_GetFocus(PyObject *self, PyObject *args, PyObject *kwargs) {
#define wxStyledTextCtrl_GetSTCFocus(_swigobj) (_swigobj->GetSTCFocus())
static PyObject *_wrap_wxStyledTextCtrl_GetSTCFocus(PyObject *self, PyObject *args, PyObject *kwargs) {
PyObject * _resultobj;
bool _result;
wxStyledTextCtrl * _arg0;
@ -7571,18 +7571,18 @@ static PyObject *_wrap_wxStyledTextCtrl_GetFocus(PyObject *self, PyObject *args,
char *_kwnames[] = { "self", NULL };
self = self;
if(!PyArg_ParseTupleAndKeywords(args,kwargs,"O:wxStyledTextCtrl_GetFocus",_kwnames,&_argo0))
if(!PyArg_ParseTupleAndKeywords(args,kwargs,"O:wxStyledTextCtrl_GetSTCFocus",_kwnames,&_argo0))
return NULL;
if (_argo0) {
if (_argo0 == Py_None) { _arg0 = NULL; }
else if (SWIG_GetPtrObj(_argo0,(void **) &_arg0,"_wxStyledTextCtrl_p")) {
PyErr_SetString(PyExc_TypeError,"Type error in argument 1 of wxStyledTextCtrl_GetFocus. Expected _wxStyledTextCtrl_p.");
PyErr_SetString(PyExc_TypeError,"Type error in argument 1 of wxStyledTextCtrl_GetSTCFocus. Expected _wxStyledTextCtrl_p.");
return NULL;
}
}
{
wxPy_BEGIN_ALLOW_THREADS;
_result = (bool )wxStyledTextCtrl_GetFocus(_arg0);
_result = (bool )wxStyledTextCtrl_GetSTCFocus(_arg0);
wxPy_END_ALLOW_THREADS;
} _resultobj = Py_BuildValue("i",_result);
@ -9869,8 +9869,8 @@ static PyMethodDef stc_cMethods[] = {
{ "wxStyledTextCtrl_SetMouseDownCaptures", (PyCFunction) _wrap_wxStyledTextCtrl_SetMouseDownCaptures, METH_VARARGS | METH_KEYWORDS },
{ "wxStyledTextCtrl_GetStatus", (PyCFunction) _wrap_wxStyledTextCtrl_GetStatus, METH_VARARGS | METH_KEYWORDS },
{ "wxStyledTextCtrl_SetStatus", (PyCFunction) _wrap_wxStyledTextCtrl_SetStatus, METH_VARARGS | METH_KEYWORDS },
{ "wxStyledTextCtrl_GetFocus", (PyCFunction) _wrap_wxStyledTextCtrl_GetFocus, METH_VARARGS | METH_KEYWORDS },
{ "wxStyledTextCtrl_SetFocus", (PyCFunction) _wrap_wxStyledTextCtrl_SetFocus, METH_VARARGS | METH_KEYWORDS },
{ "wxStyledTextCtrl_GetSTCFocus", (PyCFunction) _wrap_wxStyledTextCtrl_GetSTCFocus, METH_VARARGS | METH_KEYWORDS },
{ "wxStyledTextCtrl_SetSTCFocus", (PyCFunction) _wrap_wxStyledTextCtrl_SetSTCFocus, METH_VARARGS | METH_KEYWORDS },
{ "wxStyledTextCtrl_GetModEventMask", (PyCFunction) _wrap_wxStyledTextCtrl_GetModEventMask, METH_VARARGS | METH_KEYWORDS },
{ "wxStyledTextCtrl_ReleaseDocument", (PyCFunction) _wrap_wxStyledTextCtrl_ReleaseDocument, METH_VARARGS | METH_KEYWORDS },
{ "wxStyledTextCtrl_AddRefDocument", (PyCFunction) _wrap_wxStyledTextCtrl_AddRefDocument, METH_VARARGS | METH_KEYWORDS },
@ -10150,12 +10150,14 @@ static struct { char *n1; char *n2; void *(*pcnv)(void *); } _swig_mapping[] = {
{ "_wxChar","_char",0},
{ "_wxCommandEvent","_wxStyledTextEvent",SwigwxStyledTextEventTowxCommandEvent},
{ "_char","_wxChar",0},
{ "_struct_wxNativeFontInfo","_wxNativeFontInfo",0},
{ "_EBool","_wxCoord",0},
{ "_EBool","_wxPrintQuality",0},
{ "_EBool","_signed_int",0},
{ "_EBool","_int",0},
{ "_EBool","_wxWindowID",0},
{ "_unsigned_long","_long",0},
{ "_wxNativeFontInfo","_struct_wxNativeFontInfo",0},
{ "_signed_int","_wxCoord",0},
{ "_signed_int","_wxPrintQuality",0},
{ "_signed_int","_EBool",0},

View File

@ -822,11 +822,11 @@ class wxStyledTextCtrlPtr(wxControlPtr):
def GetModEventMask(self, *_args, **_kwargs):
val = apply(stc_c.wxStyledTextCtrl_GetModEventMask,(self,) + _args, _kwargs)
return val
def SetFocus(self, *_args, **_kwargs):
val = apply(stc_c.wxStyledTextCtrl_SetFocus,(self,) + _args, _kwargs)
def SetSTCFocus(self, *_args, **_kwargs):
val = apply(stc_c.wxStyledTextCtrl_SetSTCFocus,(self,) + _args, _kwargs)
return val
def GetFocus(self, *_args, **_kwargs):
val = apply(stc_c.wxStyledTextCtrl_GetFocus,(self,) + _args, _kwargs)
def GetSTCFocus(self, *_args, **_kwargs):
val = apply(stc_c.wxStyledTextCtrl_GetSTCFocus,(self,) + _args, _kwargs)
return val
def SetStatus(self, *_args, **_kwargs):
val = apply(stc_c.wxStyledTextCtrl_SetStatus,(self,) + _args, _kwargs)

View File

@ -24,6 +24,7 @@ import images
_treeList = [
('New since last release', ['ContextHelp',
'PyCrust',
'PyCrustWithFilling',
'VirtualListCtrl',
'wxListCtrl',
'TablePrint',

View File

@ -0,0 +1,20 @@
from wxPython.wx import *
from wxPython.lib.PyCrust import shell, version, filling
#----------------------------------------------------------------------
intro = 'Welcome To PyCrust %s - The Flakiest Python Shell' % version.VERSION
def runTest(frame, nb, log):
win = wxSplitterWindow(nb, -1, size=(640, 480))
shellWin = shell.Shell(win, -1, introText=intro)
fillingWin = filling.Filling(win, -1, size=(640, 480),
ingredients=shellWin.interp.locals)
win.SplitHorizontally(shellWin, fillingWin)
return win
#----------------------------------------------------------------------
overview = filling.__doc__

View File

@ -175,6 +175,8 @@ def runTest(frame, nb, log):
print "GetStyledText(98, 104): ", repr(ed.GetStyledText(98, 104)), len(ed.GetStyledText(98, 104))
print
print "GetCurLine(): ", repr(ed.GetCurLine())
ed.GotoPos(5)
print "GetCurLine(): ", repr(ed.GetCurLine())
print
print "GetLine(1): ", repr(ed.GetLine(1))
print

View File

@ -13,7 +13,7 @@ from my_distutils import run_swig, contrib_copy_tree
# flags and values that affect this script
#----------------------------------------------------------------------
VERSION = "2.3.2b1"
VERSION = "2.3.2b2"
DESCRIPTION = "Cross platform GUI toolkit for Python"
AUTHOR = "Robin Dunn"
AUTHOR_EMAIL = "Robin Dunn <robin@alldunn.com>"

View File

@ -1 +1 @@
ver = '2.3.2b1'
ver = '2.3.2b2'

Binary file not shown.

Before

Width:  |  Height:  |  Size: 766 B

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -1,6 +1,5 @@
#!/usr/bin/env python
"""PyCrust is a python shell application.
"""
"""PyCrust is a python shell and namespace browser application."""
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
__cvsid__ = "$Id$"
@ -8,209 +7,32 @@ __date__ = "July 1, 2001"
__version__ = "$Revision$"[11:-2]
from wxPython.wx import *
from version import VERSION
from shell import Shell
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 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.icon = wxIcon('PyCrust.ico', wxBITMAP_TYPE_ICO)
self.SetIcon(self.icon)
self.createMenus()
# Create the shell, which will create a default interpreter.
locals = {'__app__': 'PyCrust Application'}
self.shell = Shell(parent=self, id=-1, introText=intro, locals=locals)
# Override the shell so that status messages go to the status bar.
self.shell.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.autocompMenu = wxMenu()
m.Append(ID_AUTOCOMP_SHOW, 'Show Auto Completion', \
'Show auto completion during dot syntax', checkable=1)
m.Append(ID_AUTOCOMP_INCLUDE_MAGIC, 'Include Magic Attributes', \
'Include attributes visible to __getattr__ and __setattr__', checkable=1)
m.Append(ID_AUTOCOMP_INCLUDE_SINGLE, 'Include Single Underscores', \
'Include attibutes prefixed by a single underscore', checkable=1)
m.Append(ID_AUTOCOMP_INCLUDE_DOUBLE, 'Include Double Underscores', \
'Include attibutes prefixed by a double underscore', checkable=1)
m = self.calltipsMenu = wxMenu()
m.Append(ID_CALLTIPS_SHOW, 'Show Call Tips', \
'Show call tips with argument specifications', checkable=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."""
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' % self.shell.interp.revision
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)
from crust import CrustFrame
class App(wxApp):
"""PyCrust standalone application."""
def OnInit(self):
parent = None
id = -1
title = 'PyCrust'
self.frame = Frame(parent, id, title)
self.frame.Show(true)
self.SetTopWindow(self.frame)
locals = {'__app__': 'PyCrust Standalone Application'}
self.crustFrame = CrustFrame(locals=locals)
self.crustFrame.Show(true)
# Set focus to the shell editor.
self.crustFrame.crust.shell.SetFocus()
self.SetTopWindow(self.crustFrame)
# Add the application object to the sys module's namespace.
# This allows a shell user to do:
# >>> import sys
# >>> sys.application.whatever
import sys
sys.application = self
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,35 @@
#!/usr/bin/env python
"""PyFilling is a python namespace inspection application."""
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
__cvsid__ = "$Id$"
__date__ = "August 21, 2001"
__version__ = "$Revision$"[11:-2]
# We use this object to get more introspection when run standalone.
application = None
import filling
# These are imported just to have something interesting to inspect.
import crust
import interpreter
import introspect
import pseudo
import shell
import sys
from wxPython import wx
def main():
"""Create and run the application."""
global application
application = filling.App(0)
root = application.fillingFrame.filling.fillingTree.root
application.fillingFrame.filling.fillingTree.Expand(root)
application.MainLoop()
if __name__ == '__main__':
main()

View File

@ -0,0 +1,36 @@
#!/usr/bin/env python
"""PyShell 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 shell import ShellFrame
class App(wxApp):
"""PyShell standalone application."""
def OnInit(self):
locals = {'__app__': 'PyShell Standalone Application'}
self.shellFrame = ShellFrame(locals=locals)
self.shellFrame.Show(true)
self.SetTopWindow(self.shellFrame)
# Add the application object to the sys module's namespace.
# This allows a shell user to do:
# >>> import sys
# >>> sys.application.whatever
import sys
sys.application = self
return true
def main():
application = App(0)
application.MainLoop()
if __name__ == '__main__':
main()

View File

@ -4,40 +4,63 @@ Half-baked by Patrick K. O'Brien (pobrien@orbtech.com)
What is PyCrust?
----------------
PyCrust is an interactive Python environment written in Python.
PyCrust components can run standalone or be integrated into other
development environments and/or other Python applications.
PyCrust is is an interactive Python Shell written in Python.
PyCrust can be run standalone or integrated into other development
environments or other Python applications.
PyCrust comes with an interactive Python shell (PyShell), an
interactive namespace/object tree control (PyFilling) and an
integrated, split-window combination of the two (PyCrust).
Where can I get the latest files and join the mailing lists?
What is PyCrust good for?
-------------------------
Have you ever tried to bake a pie without one? Well, you
shouldn't build a Python program without a PyCrust either.
Where can I get the latest release of PyCrust?
------------------------------------------------------------
Latest PyCrust releases:
The latest PyCrust releases are available at:
http://sourceforge.net/project/showfiles.php?group_id=31263
PyCrust home page:
http://pycrust.sourceforge.net/
SourceForge summary page:
http://sourceforge.net/projects/pycrust/
PyCrust Mailing lists:
http://sourceforge.net/mail/?group_id=31263
What else do I need to use PyCrust?
-----------------------------------
PyCrust requires Python 2.1 or later, and wxPython 2.3.1 or later.
PyCrust uses wxPython and the Scintilla wrapper class (wxStyledTextCtrl).
PyCrust uses wxPython and the Scintilla wrapper (wxStyledTextCtrl).
Python is available at http://www.python.org/.
wxPython is available at http://www.wxpython.org/.
Where is the PyCrust project hosted?
------------------------------------
At SourceForge, of course. The SourceForge summary page:
http://sourceforge.net/projects/pycrust/
Does PyCrust have a mailing list full of wonderful people?
----------------------------------------------------------
As a matter of fact, we do. Join the PyCrust mailing lists at:
http://sourceforge.net/mail/?group_id=31263
I found a bug in PyCrust, what do I do with it?
-----------------------------------------------
You can send it to me at pobrien@orbtech.com, or, preferably,
submit a bug report on our bug tracker at SourceForge:
http://sourceforge.net/tracker/?group_id=31263
I want a new feature added to PyCrust. Will you do it?
------------------------------------------------------
Flattery and money will get you anything. Short of that, you
can try posting a request on our feature tracker at SourceForge:
http://sourceforge.net/tracker/?group_id=31263
What is the CVS information for this README file?
-------------------------------------------------
$Date$
$Revision$
$Id$

View File

@ -0,0 +1,67 @@
"""PyCrust Crust combines the shell and filling into one control."""
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
__cvsid__ = "$Id$"
__date__ = "July 1, 2001"
__version__ = "$Revision$"[11:-2]
from wxPython.wx import *
from shell import Shell
from filling import Filling
from version import VERSION
class Crust(wxSplitterWindow):
"""PyCrust Crust based on wxSplitterWindow."""
name = 'PyCrust Crust'
revision = __version__
def __init__(self, parent, id=-1, pos=wxDefaultPosition, \
size=wxDefaultSize, style=wxSP_3D, name='Crust Window', \
ingredients=None, rootLabel=None, intro='', locals=None, \
InterpClass=None, *args, **kwds):
"""Create a PyCrust Crust instance."""
wxSplitterWindow.__init__(self, parent, id, pos, size, style, name)
self.shell = Shell(parent=self, introText=intro, \
locals=locals, InterpClass=InterpClass, \
*args, **kwds)
self.filling = Filling(parent=self, \
ingredients=self.shell.interp.locals, \
rootLabel=rootLabel)
"""Add 'filling' to the interpreter's locals."""
self.shell.interp.locals['filling'] = self.filling
self.SplitHorizontally(self.shell, self.filling, 300)
# Set focus to the shell editor. Doesn't always work as intended.
self.shell.SetFocus()
class CrustFrame(wxFrame):
"""Frame containing all the PyCrust components."""
name = 'PyCrust Frame'
revision = __version__
def __init__(self, parent=None, id=-1, title='PyCrust', \
ingredients=None, rootLabel=None, locals=None, \
InterpClass=None, *args, **kwds):
"""Create a PyCrust CrustFrame instance."""
wxFrame.__init__(self, parent, id, title)
intro = 'Welcome To PyCrust %s - The Flakiest Python Shell' % VERSION
self.CreateStatusBar()
self.SetStatusText(intro)
if wxPlatform == '__WXMSW__':
icon = wxIcon('PyCrust.ico', wxBITMAP_TYPE_ICO)
self.SetIcon(icon)
self.crust = Crust(parent=self, intro=intro, \
ingredients=ingredients, \
rootLabel=rootLabel, locals=locals, \
InterpClass=InterpClass, *args, **kwds)
# Override the filling so that status messages go to the status bar.
self.crust.filling.fillingTree.setStatusText = self.SetStatusText
# Override the shell so that status messages go to the status bar.
self.crust.shell.setStatusText = self.SetStatusText
# Set focus to the shell editor. Doesn't always work as intended.
self.crust.shell.SetFocus()

View File

@ -0,0 +1,292 @@
"""PyCrust Filling is the gui tree control through which a user can navigate
the local namespace or any object."""
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
__cvsid__ = "$Id$"
__date__ = "August 21, 2001"
__version__ = "$Revision$"[11:-2]
from wxPython.wx import *
from wxPython.stc import *
from version import VERSION
import inspect
import introspect
import keyword
import sys
import types
class FillingTree(wxTreeCtrl):
"""PyCrust FillingTree based on wxTreeCtrl."""
name = 'PyCrust Filling Tree'
revision = __version__
def __init__(self, parent, id=-1, pos=wxDefaultPosition, \
size=wxDefaultSize, style=wxTR_HAS_BUTTONS, \
ingredients=None, rootLabel=None):
"""Create a PyCrust FillingTree instance."""
wxTreeCtrl.__init__(self, parent, id, pos, size)
if not ingredients:
import __main__
ingredients = __main__
if not rootLabel: rootLabel = 'Ingredients'
rootdata = wxTreeItemData(ingredients)
self.root = self.AddRoot(rootLabel, -1, -1, rootdata)
self.SetItemHasChildren(self.root, self.hasChildren(self.root))
EVT_TREE_ITEM_EXPANDING(self, self.GetId(), self.OnItemExpanding)
EVT_TREE_ITEM_COLLAPSED(self, self.GetId(), self.OnItemCollapsed)
EVT_TREE_SEL_CHANGED(self, self.GetId(), self.OnSelChanged)
def hasChildren(self, object):
"""Return true if object has children."""
if self.getChildren(object):
return true
else:
return false
def getChildren(self, object):
"""Return a dictionary with the attributes or contents of object."""
dict = {}
objtype = type(object)
if objtype is types.DictType:
dict = object
elif objtype in (types.InstanceType, types.ModuleType):
for key in introspect.getAttributeNames(object):
# Believe it or not, some attributes can disappear, such as
# the exc_traceback attribute of the sys module. So this is
# nested in a try block.
try:
dict[key] = getattr(object, key)
except:
pass
return dict
def OnItemExpanding(self, event):
selection = event.GetItem()
if self.IsExpanded(selection):
return
object = self.GetPyData(selection)
children = self.getChildren(object)
if not children:
return
list = children.keys()
list.sort()
for item in list:
itemtext = str(item)
# Show string dictionary items with single quotes, except for
# the first level of items, which represent the local namespace.
if type(object) is types.DictType \
and type(item) is types.StringType \
and selection != self.root:
itemtext = repr(item)
child = self.AppendItem(selection, itemtext, -1, -1, \
wxTreeItemData(children[item]))
self.SetItemHasChildren(child, self.hasChildren(children[item]))
def OnItemCollapsed(self, event):
"""Remove all children from the item."""
item = event.GetItem()
self.DeleteChildren(item)
def OnSelChanged(self, event):
item = event.GetItem()
if item == self.root:
self.setText('')
return
object = self.GetPyData(item)
text = ''
text += self.getFullName(item)
text += '\n\nType: ' + str(type(object))[7:-2]
value = str(object)
if type(object) is types.StringType:
value = repr(value)
text += '\n\nValue: ' + value
if type(object) is types.InstanceType:
try:
text += '\n\nClass Definition:\n\n' + \
inspect.getsource(object.__class__)
except:
try:
text += '\n\n"""' + inspect.getdoc(object).strip() + '"""'
except:
pass
else:
try:
text += '\n\nSource Code:\n\n' + \
inspect.getsource(object)
except:
try:
text += '\n\n"""' + inspect.getdoc(object).strip() + '"""'
except:
pass
self.setText(text)
def getFullName(self, item, partial=''):
"""Return a syntactically proper name for item."""
parent = self.GetItemParent(item)
parentobject = self.GetPyData(parent)
name = self.GetItemText(item)
# Apply dictionary syntax to dictionary items, except the root
# and first level children.
if item != self.root and parent != self.root \
and type(parentobject) is types.DictType:
name = '[' + name + ']'
# Apply dot syntax to multipart names.
if partial:
if partial[0] == '[':
name += partial
else:
name += '.' + partial
# Repeat for everything but the root item and first level children.
if item != self.root and parent != self.root:
name = self.getFullName(parent, partial=name)
return name
def setText(self, text):
"""Display information about the current selection."""
# This method will most likely be replaced by the enclosing app
# to do something more interesting, like write to a text control.
print text
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
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' : 12,
'lnsize' : 10,
'backcol': '#FFFFFF',
}
class FillingText(wxStyledTextCtrl):
"""PyCrust FillingText based on wxStyledTextCtrl."""
name = 'PyCrust Filling Text'
revision = __version__
def __init__(self, parent, id=-1, pos=wxDefaultPosition, \
size=wxDefaultSize, style=wxCLIP_CHILDREN):
"""Create a PyCrust FillingText instance."""
wxStyledTextCtrl.__init__(self, parent, id, pos, size, style)
# Configure various defaults and user preferences.
self.config()
def config(self):
"""Configure shell based on user preferences."""
self.SetMarginWidth(1, 0)
self.SetLexer(wxSTC_LEX_PYTHON)
self.SetKeyWords(0, ' '.join(keyword.kwlist))
self.setStyles(faces)
self.SetViewWhiteSpace(0)
self.SetTabWidth(4)
self.SetUseTabs(0)
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)
class Filling(wxSplitterWindow):
"""PyCrust Filling based on wxSplitterWindow."""
name = 'PyCrust Filling'
revision = __version__
def __init__(self, parent, id=-1, pos=wxDefaultPosition, \
size=wxDefaultSize, style=wxSP_3D, name='Filling Window', \
ingredients=None, rootLabel=None):
"""Create a PyCrust Filling instance."""
wxSplitterWindow.__init__(self, parent, id, pos, size, style, name)
self.fillingTree = FillingTree(parent=self, ingredients=ingredients, \
rootLabel=rootLabel)
self.fillingText = FillingText(parent=self)
self.SplitVertically(self.fillingTree, self.fillingText, 200)
# Override the filling so that descriptions go to fillingText.
self.fillingTree.setText = self.fillingText.SetText
# Select the root item.
self.fillingTree.SelectItem(self.fillingTree.root)
class FillingFrame(wxFrame):
"""Frame containing the PyCrust filling, or namespace tree component."""
name = 'PyCrust Filling Frame'
revision = __version__
def __init__(self, parent=None, id=-1, title='PyFilling', \
pos=wxDefaultPosition, size=wxDefaultSize, \
style=wxDEFAULT_FRAME_STYLE, ingredients=None, \
rootLabel=None):
"""Create a PyCrust FillingFrame instance."""
wxFrame.__init__(self, parent, id, title, pos, size, style)
intro = 'Welcome To PyFilling - The Tastiest Namespace Inspector'
self.CreateStatusBar()
self.SetStatusText(intro)
if wxPlatform == '__WXMSW__':
icon = wxIcon('PyCrust.ico', wxBITMAP_TYPE_ICO)
self.SetIcon(icon)
self.filling = Filling(parent=self, ingredients=ingredients, \
rootLabel=rootLabel)
# Override the filling so that status messages go to the status bar.
self.filling.fillingTree.setStatusText = self.SetStatusText
class App(wxApp):
"""PyFilling standalone application."""
def OnInit(self):
self.fillingFrame = FillingFrame()
self.fillingFrame.Show(true)
self.SetTopWindow(self.fillingFrame)
return true

View File

@ -1,5 +1,4 @@
"""PyCrust Interpreter executes Python commands.
"""
"""PyCrust Interpreter executes Python commands."""
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
__cvsid__ = "$Id$"
@ -8,15 +7,16 @@ __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,
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)
@ -28,8 +28,8 @@ class Interpreter(InteractiveInterpreter):
__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)
self.introText = 'Python %s on %s%s%s' % \
(sys.version, sys.platform, os.linesep, copyright)
try:
sys.ps1
except AttributeError:
@ -81,3 +81,15 @@ class Interpreter(InteractiveInterpreter):
The call tip information will be based on the locals namespace."""
return introspect.getCallTip(command, self.locals, *args, **kwds)
class InterpreterAlaCarte(Interpreter):
"""PyCrustAlaCarte Demo Interpreter."""
def __init__(self, locals, rawin, stdin, stdout, stderr, \
ps1='main prompt', ps2='continuation prompt'):
"""Create an interactive interpreter object."""
Interpreter.__init__(self, locals=locals, rawin=rawin, \
stdin=stdin, stdout=stdout, stderr=stderr)
sys.ps1 = ps1
sys.ps2 = ps2

View File

@ -19,27 +19,28 @@ def getAutoCompleteList(command='', locals=None, includeMagic=1, \
root = getRoot(command, terminator='.')
try:
object = eval(root, locals)
attributes = getAttributeNames(object)
if includeMagic:
try: attributes += object._getAttributeNames()
except: pass
if not includeSingle:
attributes = filter(lambda item: item[0]!='_' or item[1]=='_', attributes)
if not includeDouble:
attributes = filter(lambda item: item[:2]!='__', attributes)
attributes = getAttributeNames(object, includeMagic, \
includeSingle, includeDouble)
return attributes
except:
return []
def getAttributeNames(object):
def getAttributeNames(object, includeMagic=1, includeSingle=1, includeDouble=1):
"""Return list of unique attributes, including inherited, for an object."""
attributes = []
dict = {}
# Remove duplicates from the attribute list.
if includeMagic:
try: attributes += object._getAttributeNames()
except: pass
# Get all attribute names, removing duplicates from the attribute list.
for item in getAllAttributeNames(object):
dict[item] = None
attributes += dict.keys()
attributes.sort()
if not includeSingle:
attributes = filter(lambda item: item[0]!='_' or item[1]=='_', attributes)
if not includeDouble:
attributes = filter(lambda item: item[:2]!='__', attributes)
return attributes
def getAllAttributeNames(object):
@ -137,7 +138,9 @@ def getRoot(command, terminator=None):
pieces = command.split(terminator)
if len(pieces) > 1:
command = terminator.join(pieces[:-1])
if command in ("''", '""', '""""""', '[]', '()', '{}'):
if len(command) == 0:
root = ''
elif command in ("''", '""', '""""""', '[]', '()', '{}'):
# Let empty type delimiter pairs go through.
root = command
else:

View File

@ -1,7 +1,7 @@
"""PyCrust Shell is the gui text control in which a user interacts and types
in commands to be sent to the interpreter. This particular shell is based on
wxPython's wxStyledTextCtrl.
"""
"""The PyCrust Shell is an interactive text control in which a user types in
commands to be sent to the interpreter. This particular shell is based on
wxPython's wxStyledTextCtrl. The latest files are always available at the
SourceForge project page at http://sourceforge.net/projects/pycrust/."""
__author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
__cvsid__ = "$Id$"
@ -10,13 +10,12 @@ __version__ = "$Revision$"[11:-2]
from wxPython.wx import *
from wxPython.stc import *
import keyword
import os
import sys
from version import VERSION
if wxPlatform == '__WXMSW__':
faces = { 'times' : 'Times New Roman',
'mono' : 'Courier New',
@ -32,79 +31,85 @@ else: # GTK
'mono' : 'Courier',
'helv' : 'Helvetica',
'other' : 'new century schoolbook',
'size' : 9,
'lnsize' : 8,
'size' : 12,
'lnsize' : 10,
'backcol': '#FFFFFF',
}
class Shell(wxStyledTextCtrl):
"""PyCrust Shell based on wxStyledTextCtrl."""
name = 'PyCrust Shell'
revision = __version__
def __init__(self, parent, id, introText='', locals=None, interp=None):
"""Create a PyCrust Shell object."""
wxStyledTextCtrl.__init__(self, parent, id, style=wxCLIP_CHILDREN)
self.introText = introText
def __init__(self, parent, id=-1, pos=wxDefaultPosition, \
size=wxDefaultSize, style=wxCLIP_CHILDREN, introText='', \
locals=None, InterpClass=None, *args, **kwds):
"""Create a PyCrust Shell instance."""
wxStyledTextCtrl.__init__(self, parent, id, pos, size, style)
# Import a default interpreter class if one isn't provided.
if InterpClass == None:
from interpreter import Interpreter
else:
Interpreter = InterpClass
# Create default locals so we have something interesting.
shellLocals = {'__name__': 'PyShell',
'__doc__': 'PyShell, The PyCrust Python Shell.',
'__version__': VERSION,
}
# Add the dictionary that was passed in.
if locals:
shellLocals.update(locals)
from pseudo import PseudoFileIn, PseudoFileOut, PseudoFileErr
self.interp = Interpreter(locals=shellLocals, \
rawin=self.readRaw, \
stdin=PseudoFileIn(self.readIn), \
stdout=PseudoFileOut(self.writeOut), \
stderr=PseudoFileErr(self.writeErr), \
*args, **kwds)
# Keep track of the most recent prompt starting and ending positions.
self.promptPos = [0, 0]
# Keep track of multi-line commands.
self.more = 0
# Create the command history. Commands are added into the front of
# the list (ie. at index 0) as they are entered. self.historyPos is
# the current position in the history; it gets incremented as you
# retrieve the previous command, decremented as you retrieve the next,
# and reset when you hit Enter. self.historyPos == -1 means you're on
# the current command, not in the history. self.tempCommand is
# storage space for whatever was on the last line when you first hit
# "Retrieve-Previous", so that the final "Retrieve-Next" will restore
# whatever was originally there. self.lastCommandRecalled remembers
# the index of the last command to be recalled from the history, so
# you can repeat a group of commands by going up-up-up-enter to find
# the first one in the group then down-enter-down-enter to recall each
# subsequent command. Also useful for multiline commands, in lieu of
# a proper implementation of those.
self.history = []
self.historyPos = -1
self.tempCommand = ''
self.lastCommandRecalled = -1
# Assign handlers for keyboard events.
EVT_KEY_DOWN(self, self.OnKeyDown)
EVT_CHAR(self, self.OnChar)
# Create a default interpreter if one isn't provided.
if interp == None:
from interpreter import Interpreter
from pseudo import PseudoFileIn, PseudoFileOut, PseudoFileErr
self.stdin = PseudoFileIn(self.readIn)
self.stdout = PseudoFileOut(self.writeOut)
self.stderr = PseudoFileErr(self.writeErr)
# Override the default locals so we have something interesting.
self.locals = {'__name__': 'PyCrust',
'__doc__': 'PyCrust, The Python Shell.',
'__version__': VERSION,
}
# Add the dictionary that was passed in.
if locals:
self.locals.update(locals)
self.interp = Interpreter(locals=self.locals,
rawin=self.readRaw,
stdin=self.stdin,
stdout=self.stdout,
stderr=self.stderr)
else:
self.interp = interp
# Configure various defaults and user preferences.
self.config()
try:
self.showIntro(self.introText)
except:
pass
try:
self.setBuiltinKeywords()
except:
pass
try:
self.setLocalShell()
except:
pass
# Display the introductory banner information.
try: self.showIntro(introText)
except: pass
# Assign some pseudo keywords to the interpreter's namespace.
try: self.setBuiltinKeywords()
except: pass
# Add 'shell' to the interpreter's local namespace.
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
try: self.execStartupScript(self.interp.startupScript)
except: pass
def destroy(self):
del self.stdin
del self.stdout
del self.stderr
del self.interp
def config(self):
@ -133,7 +138,7 @@ class Shell(wxStyledTextCtrl):
def showIntro(self, text=''):
"""Display introductory text in the shell."""
if text:
if text[-1] != '\n': text += '\n'
if not text.endswith(os.linesep): text += os.linesep
self.write(text)
try:
self.write(self.interp.introText)
@ -148,10 +153,15 @@ class Shell(wxStyledTextCtrl):
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.
"""
## POB: This is having some weird side-effects so I'm taking it out.
## import __builtin__
## from pseudo import PseudoKeyword
## __builtin__.close = __builtin__.exit = __builtin__.quit = \
## PseudoKeyword(self.quit)
import __builtin__
from pseudo import PseudoKeyword
__builtin__.close = __builtin__.exit = __builtin__.quit = \
PseudoKeyword(self.quit)
'Click on the close button to leave the application.'
def quit(self):
"""Quit the application."""
@ -211,14 +221,86 @@ class Shell(wxStyledTextCtrl):
"""Key down event handler.
The main goal here is to not allow modifications to previous
lines of text.
"""
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()
# Control+UpArrow steps up through the history.
elif key == WXK_UP and event.ControlDown() \
and self.historyPos < len(self.history) - 1:
# Move to the end of the buffer.
endpos = self.GetTextLength()
self.SetCurrentPos(endpos)
# The first Control+Up stores the current command;
# Control+Down brings it back.
if self.historyPos == -1:
self.tempCommand = self.getCommand()
# Now replace the current line with the next one from the history.
self.historyPos = self.historyPos + 1
self.SetSelection(stoppos, endpos)
self.ReplaceSelection(self.history[self.historyPos])
# Control+DownArrow steps down through the history.
elif key == WXK_DOWN and event.ControlDown():
# Move to the end of the buffer.
endpos = self.GetTextLength()
self.SetCurrentPos(endpos)
# Are we at the bottom end of the history?
if self.historyPos == -1:
# Do we have a lastCommandRecalled stored?
if self.lastCommandRecalled >= 0:
# Replace the current line with the command after the
# last-recalled command (you'd think there should be a +1
# here but there isn't because the history was shuffled up
# by 1 after the previous command was recalled).
self.SetSelection(stoppos, endpos)
self.ReplaceSelection(self.history[self.lastCommandRecalled])
# We've now warped into middle of the history.
self.historyPos = self.lastCommandRecalled
self.lastCommandRecalled = -1
else:
# Fetch either the previous line from the history, or the saved
# command if we're back at the start.
self.historyPos = self.historyPos - 1
if self.historyPos == -1:
newText = self.tempCommand
else:
newText = self.history[self.historyPos]
# Replace the current line with the new text.
self.SetSelection(stoppos, endpos)
self.ReplaceSelection(newText)
# F8 on the last line does a search up the history for the text in
# front of the cursor.
elif key == WXK_F8 and self.GetCurrentLine() == self.GetLineCount()-1:
tempCommand = self.getCommand()
# The first F8 saves the current command, just like Control+Up.
if self.historyPos == -1:
self.tempCommand = tempCommand
# The text up to the cursor is what we search for.
searchText = tempCommand
numCharsAfterCursor = self.GetTextLength() - self.GetCurrentPos()
if numCharsAfterCursor > 0:
searchText = searchText[:-numCharsAfterCursor]
# Search upwards from the current history position and loop back
# to the beginning if we don't find anything.
for i in range(self.historyPos+1, len(self.history)) + \
range(self.historyPos):
command = self.history[i]
if command[:len(searchText)] == searchText:
# Replace the current line with the one we've found.
endpos = self.GetTextLength()
self.SetSelection(stoppos, endpos)
self.ReplaceSelection(command)
# Put the cursor back at the end of the search text.
pos = self.GetTextLength() - len(command) + len(searchText)
self.SetCurrentPos(pos)
self.SetAnchor(pos)
# We've now warped into middle of the history.
self.historyPos = i
self.lastCommandRecalled = -1
break
# Return is used to submit a command to the interpreter.
elif key == WXK_RETURN:
if self.CallTipActive: self.CallTipCancel()
@ -252,8 +334,7 @@ class Shell(wxStyledTextCtrl):
"""Keypress event handler.
The main goal here is to not allow modifications to previous
lines of text.
"""
lines of text."""
key = event.KeyCode()
currpos = self.GetCurrentPos()
stoppos = self.promptPos[1]
@ -296,14 +377,24 @@ class Shell(wxStyledTextCtrl):
# Grab information about the current line.
thepos = self.GetCurrentPos()
theline = self.GetCurrentLine()
thetext = self.GetCurLine()[0]
command = self.getCommand(thetext)
command = self.getCommand()
# Go to the very bottom of the text.
endpos = self.GetTextLength()
self.SetCurrentPos(endpos)
endline = self.GetCurrentLine()
# If they hit RETURN on the last line, execute the command.
if theline == endline:
# Store the last-recalled command; see the main comment for
# self.lastCommandRecalled.
if command != '':
self.lastCommandRecalled = self.historyPos
# Reset the history position.
self.historyPos = -1
# Insert this command into the history, unless it's a blank line
# or the same as the last command.
if command != '' \
and (len(self.history) == 0 or command != self.history[0]):
self.history.insert(0, command)
self.push(command)
# Otherwise, replace the last line with the new line.
else:
@ -319,15 +410,19 @@ class Shell(wxStyledTextCtrl):
self.SetCurrentPos(thepos)
self.SetAnchor(thepos)
def getCommand(self, text):
def getCommand(self, text=None):
"""Extract a command from text which may include a shell prompt.
The command may not necessarily be valid Python syntax.
"""
The command may not necessarily be valid Python syntax."""
if not text:
text = self.GetCurLine()[0]
## This is a hack due to a bug in the wxPython 2.3.2 beta. The following
## two lines of code should go away once the bug has been fixed and the
## line above should be restored.
## self.write(' ')
## text = self.GetCurLine()[0][:-1]
# 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.
# prompt every time a command is issued.
ps1 = str(sys.ps1)
ps1size = len(ps1)
ps2 = str(sys.ps2)
@ -344,7 +439,7 @@ class Shell(wxStyledTextCtrl):
def push(self, command):
"""Send command to the interpreter for execution."""
self.write('\n')
self.write(os.linesep)
self.more = self.interp.push(command)
self.prompt()
# Keep the undo feature from undoing previous responses. The only
@ -353,7 +448,16 @@ class Shell(wxStyledTextCtrl):
self.EmptyUndoBuffer()
def write(self, text):
"""Display text in the shell."""
"""Display text in the shell.
Replace line endings with OS-specific endings."""
lines = text.split('\r\n')
for l in range(len(lines)):
chunks = lines[l].split('\r')
for c in range(len(chunks)):
chunks[c] = os.linesep.join(chunks[c].split('\n'))
lines[l] = os.linesep.join(chunks)
text = os.linesep.join(lines)
self.AddText(text)
self.EnsureCaretVisible()
#self.ScrollToColumn(0)
@ -361,14 +465,13 @@ class Shell(wxStyledTextCtrl):
def prompt(self):
"""Display appropriate prompt for the context, either ps1 or ps2.
If this is a continuation line, autoindent as necessary.
"""
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')
if pos > 0: self.write(os.linesep)
self.promptPos[0] = self.GetCurrentPos()
self.write(prompt)
self.promptPos[1] = self.GetCurrentPos()
@ -386,7 +489,7 @@ class Shell(wxStyledTextCtrl):
try:
if dialog.ShowModal() == wxID_OK:
text = dialog.GetValue()
self.write(text + '\n')
self.write(text + os.linesep)
return text
finally:
dialog.Destroy()
@ -476,3 +579,205 @@ class Shell(wxStyledTextCtrl):
"""Return true if text is selected and can be copied."""
return self.GetSelectionStart() != self.GetSelectionEnd()
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 ShellFrame(wxFrame):
"""Frame containing the PyCrust shell component."""
name = 'PyCrust Shell Frame'
revision = __version__
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
self.CreateStatusBar()
self.SetStatusText(intro)
if wxPlatform == '__WXMSW__':
icon = wxIcon('PyCrust.ico', wxBITMAP_TYPE_ICO)
self.SetIcon(icon)
self.createMenus()
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
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.autocompMenu = wxMenu()
m.Append(ID_AUTOCOMP_SHOW, 'Show Auto Completion', \
'Show auto completion during dot syntax', \
checkable=1)
m.Append(ID_AUTOCOMP_INCLUDE_MAGIC, 'Include Magic Attributes', \
'Include attributes visible to __getattr__ and __setattr__', \
checkable=1)
m.Append(ID_AUTOCOMP_INCLUDE_SINGLE, 'Include Single Underscores', \
'Include attibutes prefixed by a single underscore', \
checkable=1)
m.Append(ID_AUTOCOMP_INCLUDE_DOUBLE, 'Include Double Underscores', \
'Include attibutes prefixed by a double underscore', \
checkable=1)
m = self.calltipsMenu = wxMenu()
m.Append(ID_CALLTIPS_SHOW, 'Show Call Tips', \
'Show call tips with argument specifications', checkable=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)

View File

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