]> git.saurik.com Git - wxWidgets.git/commitdiff
A couple little fixes for wxSTC
authorRobin Dunn <robin@alldunn.com>
Tue, 4 Sep 2001 23:44:17 +0000 (23:44 +0000)
committerRobin Dunn <robin@alldunn.com>
Tue, 4 Sep 2001 23:44:17 +0000 (23:44 +0000)
Updated to 0.6 of PyCrust

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@11560 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

19 files changed:
wxPython/CHANGES.txt
wxPython/contrib/stc/stc_.cpp
wxPython/contrib/stc/stc_.py
wxPython/demo/Main.py
wxPython/demo/PyCrustWithFilling.py [new file with mode: 0644]
wxPython/demo/wxStyledTextCtrl_1.py
wxPython/setup.py
wxPython/src/__version__.py
wxPython/wxPython/lib/PyCrust/PyCrust.ico
wxPython/wxPython/lib/PyCrust/PyCrust.py
wxPython/wxPython/lib/PyCrust/PyFilling.py [new file with mode: 0644]
wxPython/wxPython/lib/PyCrust/PyShell.py [new file with mode: 0644]
wxPython/wxPython/lib/PyCrust/README.txt
wxPython/wxPython/lib/PyCrust/crust.py [new file with mode: 0644]
wxPython/wxPython/lib/PyCrust/filling.py [new file with mode: 0644]
wxPython/wxPython/lib/PyCrust/interpreter.py
wxPython/wxPython/lib/PyCrust/introspect.py
wxPython/wxPython/lib/PyCrust/shell.py
wxPython/wxPython/lib/PyCrust/version.py

index a6f0a558ff31fbaaef453e6a9734cf09875b6b5f..43ef79bba6663e2f0cb633aa8c37acea4d8b30fa 100644 (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.
 
 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.
 
 
 Added the new virtual list capabilities to wxListCtrl.
 
@@ -40,6 +41,8 @@ Added wxGenBitmapTextButton, TablePrint, etc. contribs from Lorne White.
 Added wxNativeFontInfo and wxFontMapper.
 
 
 Added wxNativeFontInfo and wxFontMapper.
 
 
+
+
 2.3.1
 -----
 Added EVT_GRID_EDITOR_CREATED and wxGridEditorCreatedEvent so the user
 2.3.1
 -----
 Added EVT_GRID_EDITOR_CREATED and wxGridEditorCreatedEvent so the user
index ebd8dec5b5222c3c71c11f7fb2306c3497258bdf..1ad28148806dfdbe41ea565009a599f09cc0c0db 100644 (file)
@@ -988,7 +988,7 @@ static PyObject *_wrap_wxStyledTextCtrl_GetCurLine(PyObject *self, PyObject *arg
     PyObject * _resultobj;
     wxString * _result;
     wxStyledTextCtrl * _arg0;
     PyObject * _resultobj;
     wxString * _result;
     wxStyledTextCtrl * _arg0;
-    int * _arg1 = (int *) NULL;
+    int * _arg1;
     int  temp;
     PyObject * _argo0 = 0;
     char *_kwnames[] = { "self", NULL };
     int  temp;
     PyObject * _argo0 = 0;
     char *_kwnames[] = { "self", NULL };
@@ -7532,8 +7532,8 @@ static PyObject *_wrap_wxStyledTextCtrl_GetModEventMask(PyObject *self, PyObject
     return _resultobj;
 }
 
     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;
     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;
     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")) {
         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;
         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);
 
     wxPy_END_ALLOW_THREADS;
 }    Py_INCREF(Py_None);
@@ -7562,8 +7562,8 @@ static PyObject *_wrap_wxStyledTextCtrl_SetFocus(PyObject *self, PyObject *args,
     return _resultobj;
 }
 
     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;
     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;
     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")) {
         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;
         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);
 
     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_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 },
         { "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},
     { "_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},
     { "_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},
     { "_signed_int","_wxCoord",0},
     { "_signed_int","_wxPrintQuality",0},
     { "_signed_int","_EBool",0},
index 079b8cc4fd97f3ef6d503c55b6540152ed04bb8f..83863a5c3bf1e85f29476a5cbe48dafa09f92f4e 100644 (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 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
         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)
         return val
     def SetStatus(self, *_args, **_kwargs):
         val = apply(stc_c.wxStyledTextCtrl_SetStatus,(self,) + _args, _kwargs)
index 74318bcd627877aafd88a6bf4d3f92e3b711302f..5eebb3513788902b349d5d24fe2e4120aff4273e 100644 (file)
@@ -24,6 +24,7 @@ import images
 _treeList = [
     ('New since last release', ['ContextHelp',
                                 'PyCrust',
 _treeList = [
     ('New since last release', ['ContextHelp',
                                 'PyCrust',
+                                'PyCrustWithFilling',
                                 'VirtualListCtrl',
                                 'wxListCtrl',
                                 'TablePrint',
                                 'VirtualListCtrl',
                                 'wxListCtrl',
                                 'TablePrint',
diff --git a/wxPython/demo/PyCrustWithFilling.py b/wxPython/demo/PyCrustWithFilling.py
new file mode 100644 (file)
index 0000000..78a200a
--- /dev/null
@@ -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__
index cf589e92f337f2eae5a1a61c9ea37e8025c53b98..76aba88b50cb9b6e72eca5ed589f533feaaee95f 100644 (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())
         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
         print
         print "GetLine(1): ", repr(ed.GetLine(1))
         print
index ee2b3d47f9ef0f676754f1a8629e5abcee08941d..d9a0bb2e232d2f0808f25957942b4e67f8d8c673 100755 (executable)
@@ -13,7 +13,7 @@ from my_distutils import run_swig, contrib_copy_tree
 # flags and values that affect this script
 #----------------------------------------------------------------------
 
 # 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>"
 DESCRIPTION      = "Cross platform GUI toolkit for Python"
 AUTHOR           = "Robin Dunn"
 AUTHOR_EMAIL     = "Robin Dunn <robin@alldunn.com>"
index eea883684f5736d1e139a2cf6f14d8f932fff6ee..f50900a0017bc0d658f9cd8bb729622b4ae9dfc9 100644 (file)
@@ -1 +1 @@
-ver = '2.3.2b1'
+ver = '2.3.2b2'
index bb29c8edd7e66d24e5acde41c632ebb805b87891..2075eec3978f1651c5dad964e71cab2e074089b1 100644 (file)
Binary files a/wxPython/wxPython/lib/PyCrust/PyCrust.ico and b/wxPython/wxPython/lib/PyCrust/PyCrust.ico differ
index 84edad7ca06ff1b3b9ae848600af62c6c735d570..d2281ce306115af88470c670f7c02523c75b2fd3 100644 (file)
@@ -1,6 +1,5 @@
 #!/usr/bin/env python
 #!/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$"
 
 __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 *
 __version__ = "$Revision$"[11:-2]
 
 from wxPython.wx import *
+from crust import CrustFrame
 
 
-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)
-            
 
 class App(wxApp):
 
 class App(wxApp):
+    """PyCrust standalone application."""
+    
     def OnInit(self):
     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():
         return true
 
 
 def main():
-    import sys
     application = App(0)
     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()
     application.MainLoop()
 
 if __name__ == '__main__':
     main()
+
diff --git a/wxPython/wxPython/lib/PyCrust/PyFilling.py b/wxPython/wxPython/lib/PyCrust/PyFilling.py
new file mode 100644 (file)
index 0000000..bb2c72b
--- /dev/null
@@ -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()
+
diff --git a/wxPython/wxPython/lib/PyCrust/PyShell.py b/wxPython/wxPython/lib/PyCrust/PyShell.py
new file mode 100644 (file)
index 0000000..0fea2d5
--- /dev/null
@@ -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()
+
index 73ad07bc2b2e21c143fd5dc57bc19aee2b4ef298..df1431c41ec0f0bfafc4765d1b8e847af38a5628 100644 (file)
@@ -4,40 +4,63 @@ Half-baked by Patrick K. O'Brien (pobrien@orbtech.com)
 
 What is PyCrust?
 ----------------
 
 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.
+
 
 
-Latest PyCrust releases:
+Where can I get the latest release of PyCrust?
+------------------------------------------------------------
+The latest PyCrust releases are available at:
 http://sourceforge.net/project/showfiles.php?group_id=31263
 
 http://sourceforge.net/project/showfiles.php?group_id=31263
 
-PyCrust home page:
-http://pycrust.sourceforge.net/
 
 
-SourceForge summary page:
+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 (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/
 
 http://sourceforge.net/projects/pycrust/
 
-PyCrust Mailing lists:
+
+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
 
 
 http://sourceforge.net/mail/?group_id=31263
 
 
-What else do I need to use PyCrust?
------------------------------------
+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
 
 
-PyCrust requires Python 2.1 or later, and wxPython 2.3.1 or later.
-PyCrust uses wxPython and the Scintilla wrapper class (wxStyledTextCtrl).
-Python is available at http://www.python.org/.
-wxPython is available at http://www.wxpython.org/.
+
+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?
 -------------------------------------------------
 
 
 What is the CVS information for this README file?
 -------------------------------------------------
-
 $Date$
 $Revision$
 $Id$
 $Date$
 $Revision$
 $Id$
diff --git a/wxPython/wxPython/lib/PyCrust/crust.py b/wxPython/wxPython/lib/PyCrust/crust.py
new file mode 100644 (file)
index 0000000..d45941a
--- /dev/null
@@ -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()
+
+
diff --git a/wxPython/wxPython/lib/PyCrust/filling.py b/wxPython/wxPython/lib/PyCrust/filling.py
new file mode 100644 (file)
index 0000000..ef3292e
--- /dev/null
@@ -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
+
+
index 5f12c01f3403be4ee30cb73a038dbc23ae703c88..48e9056464e0a044dc97f11f7ca77ad55d5d881d 100644 (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$"
 
 __author__ = "Patrick K. O'Brien <pobrien@orbtech.com>"
 __cvsid__ = "$Id$"
@@ -8,15 +7,16 @@ __version__ = "$Revision$"[11:-2]
 
 import os
 import sys
 
 import os
 import sys
-
 from code import InteractiveInterpreter
 import introspect
 
 
 class Interpreter(InteractiveInterpreter):
     """PyCrust Interpreter based on code.InteractiveInterpreter."""
 from code import InteractiveInterpreter
 import introspect
 
 
 class Interpreter(InteractiveInterpreter):
     """PyCrust Interpreter based on code.InteractiveInterpreter."""
+    
     revision = __version__
     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)
                  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.'
             __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:
         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)
 
         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
+
index 8cf6ae85051e69d96b68bd9f9e90392786cb8579..4f3abd1477ea638bb201981d8390b6fcfea2b817 100644 (file)
@@ -19,27 +19,28 @@ def getAutoCompleteList(command='', locals=None, includeMagic=1, \
     root = getRoot(command, terminator='.')
     try:
         object = eval(root, locals)
     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 []
     
         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 = {}
     """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()
     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):
     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])
         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:
         # Let empty type delimiter pairs go through.
         root = command
     else:
index 0c71206bd24af8624e1a1123d3549d7e024e81e9..e14e6c6d4e47b9d3a90bd8a6b134f0ea46f40dc3 100644 (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$"
 
 __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 *
 
 from wxPython.wx import *
 from wxPython.stc import *
-
 import keyword
 import os
 import sys
 import keyword
 import os
 import sys
-
 from version import VERSION
 
 from version import VERSION
 
+
 if wxPlatform == '__WXMSW__':
     faces = { 'times'  : 'Times New Roman',
               'mono'   : 'Courier New',
 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',
               '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."""
               'backcol': '#FFFFFF',
             }
 
 
 class Shell(wxStyledTextCtrl):
     """PyCrust Shell based on wxStyledTextCtrl."""
+    
     name = 'PyCrust Shell'
     revision = __version__
     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
         # 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)
         # 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()
         # 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.
         # 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):
             
     def destroy(self):
-        del self.stdin
-        del self.stdout
-        del self.stderr
         del self.interp
         
     def config(self):
         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:
     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)
             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.
         """
         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 = \
         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."""
 
     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 
         """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()
         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()
         # 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 
         """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]
         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()
         # 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:
         # 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:
             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)
 
                 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.
         
         """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
         # 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)
         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."""
     
     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
         self.more = self.interp.push(command)
         self.prompt()
         # Keep the undo feature from undoing previous responses. The only
@@ -353,22 +448,30 @@ class Shell(wxStyledTextCtrl):
         self.EmptyUndoBuffer()
 
     def write(self, text):
         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)
         self.AddText(text)
         self.EnsureCaretVisible()
         #self.ScrollToColumn(0)
-    
+
     def prompt(self):
         """Display appropriate prompt for the context, either ps1 or ps2.
         
     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 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()
         self.promptPos[0] = self.GetCurrentPos()
         self.write(prompt)
         self.promptPos[1] = self.GetCurrentPos()
@@ -377,7 +480,7 @@ class Shell(wxStyledTextCtrl):
             self.write('\t')  # Temporary hack indentation.
         self.EnsureCaretVisible()
         self.ScrollToColumn(0)
             self.write('\t')  # Temporary hack indentation.
         self.EnsureCaretVisible()
         self.ScrollToColumn(0)
-    
+
     def readIn(self):
         """Replacement for stdin."""
         prompt = 'Please enter your response:'
     def readIn(self):
         """Replacement for stdin."""
         prompt = 'Please enter your response:'
@@ -386,7 +489,7 @@ class Shell(wxStyledTextCtrl):
         try:
             if dialog.ShowModal() == wxID_OK:
                 text = dialog.GetValue()
         try:
             if dialog.ShowModal() == wxID_OK:
                 text = dialog.GetValue()
-                self.write(text + '\n')
+                self.write(text + os.linesep)
                 return text
         finally:
             dialog.Destroy()
                 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()
 
         """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)
+            
+
index 0c48e4021de287125b0f689230c3a7ec3981fe73..5fc855db6dc8a8c9cfd85154b4ec4ebdbb4de847 100644 (file)
@@ -1,5 +1,5 @@
 """Provides an object representing the current "version" or "release" of
 """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>"
 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]
 
 __date__ = "July 1, 2001"
 __version__ = "$Revision$"[11:-2]
 
-VERSION = '0.5.2'
+VERSION = '0.6'